Initial commit

This commit is contained in:
2026-02-02 04:50:13 +01:00
commit 5b11698731
22592 changed files with 7677434 additions and 0 deletions

View File

@@ -0,0 +1,39 @@
/* 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 "scumm/bomp.h"
namespace Scumm {
void smushDecodeRLE(byte *dst, const byte *src, int left, int top, int width, int height, int pitch) {
dst += top * pitch;
do {
dst += left;
bompDecodeLine(dst, src + 2, width, false);
src += READ_LE_UINT16(src) + 2;
dst += pitch - left;
} while (--height);
}
} // End of namespace Scumm

View File

@@ -0,0 +1,40 @@
/* 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"
namespace Scumm {
void smushDecodeUncompressed(byte *dst, const byte *src, int left, int top, int width, int height, int pitch) {
if (width == 0 || height == 0)
return;
dst += left * pitch + top;
while (height--) {
memcpy(dst, src, width);
src += width;
dst += pitch;
}
}
} // End of namespace Scumm

View File

@@ -0,0 +1,614 @@
/* 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/textconsole.h"
#include "common/util.h"
#include "scumm/bomp.h"
#include "scumm/smush/codec37.h"
namespace Scumm {
SmushDeltaBlocksDecoder::SmushDeltaBlocksDecoder(int width, int height) {
_width = width;
_height = height;
_frameSize = _width * _height;
_deltaSize = _frameSize * 3 + 0x13600;
_deltaBuf = (byte *)calloc(_deltaSize, sizeof(byte));
if (_deltaBuf == nullptr)
error("SmushDeltaBlocksDecoder::SmushDeltaBlocksDecoder(): ERROR: Unable to allocate decoder buffer.");
_deltaBufs[0] = _deltaBuf + 0x4D80;
_deltaBufs[1] = _deltaBuf + 0xE880 + _frameSize;
_offsetTable = new int16[255];
if (_offsetTable == nullptr)
error("SmushDeltaBlocksDecoder::SmushDeltaBlocksDecoder(): ERROR: Unable to allocate decoder offset table.");
_curTable = 0;
_prevSeqNb = 0;
_tableLastPitch = -1;
_tableLastIndex = -1;
}
SmushDeltaBlocksDecoder::~SmushDeltaBlocksDecoder() {
if (_offsetTable) {
delete[] _offsetTable;
_offsetTable = nullptr;
_tableLastPitch = -1;
_tableLastIndex = -1;
}
if (_deltaBuf) {
free(_deltaBuf);
_deltaSize = 0;
_deltaBuf = nullptr;
_deltaBufs[0] = nullptr;
_deltaBufs[1] = nullptr;
}
}
void SmushDeltaBlocksDecoder::makeTable(int pitch, int index) {
static const int8 makeTableBytes[] = {
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,
0, 0, -8, -29, 8, -29, -18, -25, 17, -25,
0, -23, -6, -22, 6, -22, -13, -19, 12, -19,
0, -18, 25, -18, -25, -17, -5, -17, 5, -17,
-10, -15, 10, -15, 0, -14, -4, -13, 4, -13,
19, -13, -19, -12, -8, -11, -2, -11, 0, -11,
2, -11, 8, -11, -15, -10, -4, -10, 4, -10,
15, -10, -6, -9, -1, -9, 1, -9, 6, -9,
-29, -8, -11, -8, -8, -8, -3, -8, 3, -8,
8, -8, 11, -8, 29, -8, -5, -7, -2, -7,
0, -7, 2, -7, 5, -7, -22, -6, -9, -6,
-6, -6, -3, -6, -1, -6, 1, -6, 3, -6,
6, -6, 9, -6, 22, -6, -17, -5, -7, -5,
-4, -5, -2, -5, 0, -5, 2, -5, 4, -5,
7, -5, 17, -5, -13, -4, -10, -4, -5, -4,
-3, -4, -1, -4, 0, -4, 1, -4, 3, -4,
5, -4, 10, -4, 13, -4, -8, -3, -6, -3,
-4, -3, -3, -3, -2, -3, -1, -3, 0, -3,
1, -3, 2, -3, 4, -3, 6, -3, 8, -3,
-11, -2, -7, -2, -5, -2, -3, -2, -2, -2,
-1, -2, 0, -2, 1, -2, 2, -2, 3, -2,
5, -2, 7, -2, 11, -2, -9, -1, -6, -1,
-4, -1, -3, -1, -2, -1, -1, -1, 0, -1,
1, -1, 2, -1, 3, -1, 4, -1, 6, -1,
9, -1, -31, 0, -23, 0, -18, 0, -14, 0,
-11, 0, -7, 0, -5, 0, -4, 0, -3, 0,
-2, 0, -1, 0, 0, -31, 1, 0, 2, 0,
3, 0, 4, 0, 5, 0, 7, 0, 11, 0,
14, 0, 18, 0, 23, 0, 31, 0, -9, 1,
-6, 1, -4, 1, -3, 1, -2, 1, -1, 1,
0, 1, 1, 1, 2, 1, 3, 1, 4, 1,
6, 1, 9, 1, -11, 2, -7, 2, -5, 2,
-3, 2, -2, 2, -1, 2, 0, 2, 1, 2,
2, 2, 3, 2, 5, 2, 7, 2, 11, 2,
-8, 3, -6, 3, -4, 3, -2, 3, -1, 3,
0, 3, 1, 3, 2, 3, 3, 3, 4, 3,
6, 3, 8, 3, -13, 4, -10, 4, -5, 4,
-3, 4, -1, 4, 0, 4, 1, 4, 3, 4,
5, 4, 10, 4, 13, 4, -17, 5, -7, 5,
-4, 5, -2, 5, 0, 5, 2, 5, 4, 5,
7, 5, 17, 5, -22, 6, -9, 6, -6, 6,
-3, 6, -1, 6, 1, 6, 3, 6, 6, 6,
9, 6, 22, 6, -5, 7, -2, 7, 0, 7,
2, 7, 5, 7, -29, 8, -11, 8, -8, 8,
-3, 8, 3, 8, 8, 8, 11, 8, 29, 8,
-6, 9, -1, 9, 1, 9, 6, 9, -15, 10,
-4, 10, 4, 10, 15, 10, -8, 11, -2, 11,
0, 11, 2, 11, 8, 11, 19, 12, -19, 13,
-4, 13, 4, 13, 0, 14, -10, 15, 10, 15,
-5, 17, 5, 17, 25, 17, -25, 18, 0, 18,
-12, 19, 13, 19, -6, 22, 6, 22, 0, 23,
-17, 25, 18, 25, -8, 29, 8, 29, 0, 31,
0, 0, -6, -22, 6, -22, -13, -19, 12, -19,
0, -18, -5, -17, 5, -17, -10, -15, 10, -15,
0, -14, -4, -13, 4, -13, 19, -13, -19, -12,
-8, -11, -2, -11, 0, -11, 2, -11, 8, -11,
-15, -10, -4, -10, 4, -10, 15, -10, -6, -9,
-1, -9, 1, -9, 6, -9, -11, -8, -8, -8,
-3, -8, 0, -8, 3, -8, 8, -8, 11, -8,
-5, -7, -2, -7, 0, -7, 2, -7, 5, -7,
-22, -6, -9, -6, -6, -6, -3, -6, -1, -6,
1, -6, 3, -6, 6, -6, 9, -6, 22, -6,
-17, -5, -7, -5, -4, -5, -2, -5, -1, -5,
0, -5, 1, -5, 2, -5, 4, -5, 7, -5,
17, -5, -13, -4, -10, -4, -5, -4, -3, -4,
-2, -4, -1, -4, 0, -4, 1, -4, 2, -4,
3, -4, 5, -4, 10, -4, 13, -4, -8, -3,
-6, -3, -4, -3, -3, -3, -2, -3, -1, -3,
0, -3, 1, -3, 2, -3, 3, -3, 4, -3,
6, -3, 8, -3, -11, -2, -7, -2, -5, -2,
-4, -2, -3, -2, -2, -2, -1, -2, 0, -2,
1, -2, 2, -2, 3, -2, 4, -2, 5, -2,
7, -2, 11, -2, -9, -1, -6, -1, -5, -1,
-4, -1, -3, -1, -2, -1, -1, -1, 0, -1,
1, -1, 2, -1, 3, -1, 4, -1, 5, -1,
6, -1, 9, -1, -23, 0, -18, 0, -14, 0,
-11, 0, -7, 0, -5, 0, -4, 0, -3, 0,
-2, 0, -1, 0, 0, -23, 1, 0, 2, 0,
3, 0, 4, 0, 5, 0, 7, 0, 11, 0,
14, 0, 18, 0, 23, 0, -9, 1, -6, 1,
-5, 1, -4, 1, -3, 1, -2, 1, -1, 1,
0, 1, 1, 1, 2, 1, 3, 1, 4, 1,
5, 1, 6, 1, 9, 1, -11, 2, -7, 2,
-5, 2, -4, 2, -3, 2, -2, 2, -1, 2,
0, 2, 1, 2, 2, 2, 3, 2, 4, 2,
5, 2, 7, 2, 11, 2, -8, 3, -6, 3,
-4, 3, -3, 3, -2, 3, -1, 3, 0, 3,
1, 3, 2, 3, 3, 3, 4, 3, 6, 3,
8, 3, -13, 4, -10, 4, -5, 4, -3, 4,
-2, 4, -1, 4, 0, 4, 1, 4, 2, 4,
3, 4, 5, 4, 10, 4, 13, 4, -17, 5,
-7, 5, -4, 5, -2, 5, -1, 5, 0, 5,
1, 5, 2, 5, 4, 5, 7, 5, 17, 5,
-22, 6, -9, 6, -6, 6, -3, 6, -1, 6,
1, 6, 3, 6, 6, 6, 9, 6, 22, 6,
-5, 7, -2, 7, 0, 7, 2, 7, 5, 7,
-11, 8, -8, 8, -3, 8, 0, 8, 3, 8,
8, 8, 11, 8, -6, 9, -1, 9, 1, 9,
6, 9, -15, 10, -4, 10, 4, 10, 15, 10,
-8, 11, -2, 11, 0, 11, 2, 11, 8, 11,
19, 12, -19, 13, -4, 13, 4, 13, 0, 14,
-10, 15, 10, 15, -5, 17, 5, 17, 0, 18,
-12, 19, 13, 19, -6, 22, 6, 22, 0, 23,
};
if (_tableLastPitch == pitch && _tableLastIndex == index)
return;
_tableLastPitch = pitch;
_tableLastIndex = index;
index *= 255;
assert(index + 254 < (int32)(sizeof(makeTableBytes) / 2));
for (int32 i = 0; i < 255; i++) {
int32 j = (i + index) * 2;
_offsetTable[i] = makeTableBytes[j + 1] * pitch + makeTableBytes[j];
}
}
#if defined(SCUMM_NEED_ALIGNMENT)
#define DECLARE_LITERAL_TEMP(v) \
byte v
#define READ_LITERAL_PIXEL(src, v) \
v = *src++
#define READ_LITERAL_2PIXEL(src, v) \
do { \
v = *src | (*src << 8); \
src++; \
} while (0)
#define WRITE_4X1_LINE(dst, v) \
do { \
int j; \
for (j = 0; j < 4; j++) \
(dst)[j] = v; \
} while (0)
#define COPY_4X1_LINE(dst, src) \
do { \
int j; \
for (j = 0; j < 4; j++) \
(dst)[j] = (src)[j]; \
} while (0)
#define WRITE_2X1_LINE(dst, v) \
do { \
int j; \
for (j = 0; j < 2; j++) \
(dst)[j] = v; \
} while (0)
#else /* SCUMM_NEED_ALIGNMENT */
#define DECLARE_LITERAL_TEMP(v) \
uint32 v
#define READ_LITERAL_PIXEL(src, v) \
do { \
v = *src++; \
v += (v << 8) + (v << 16) + (v << 24); \
} while (0)
#define READ_LITERAL_2PIXEL(src, v) \
do { \
v = *src | (*src << 8); \
src++; \
} while (0)
#define WRITE_4X1_LINE(dst, v) \
*(uint32 *)(dst) = v
#define COPY_4X1_LINE(dst, src) \
*(uint32 *)(dst) = *(const uint32 *)(src)
#define WRITE_2X1_LINE(dst, v) \
*(uint16 *)(dst) = v
#endif /* SCUMM_NEED_ALIGNMENT */
/* Fill a 4x4 pixel block with a literal pixel value */
#define LITERAL_4X4(src, dst, pitch) \
do { \
int x; \
DECLARE_LITERAL_TEMP(t); \
READ_LITERAL_PIXEL(src, t); \
for (x = 0; x < 4; x++) { \
WRITE_4X1_LINE(dst + pitch * x, t); \
} \
dst += 4; \
} while (0)
/* Fill four 4x1 pixel blocks with literal pixel values */
#define LITERAL_4X1(src, dst, pitch) \
do { \
int x; \
DECLARE_LITERAL_TEMP(t); \
for (x = 0; x < 4; x++) { \
READ_LITERAL_PIXEL(src, t); \
WRITE_4X1_LINE(dst + pitch * x, t); \
} \
dst += 4; \
} while (0)
/* Fill a 4x4 pixel block with four 2x2 sub-blocks of different pixel values */
#define LITERAL_2X2(src, dst, pitch) \
do { \
uint16 p1, p2, p3, p4; \
READ_LITERAL_2PIXEL(src, p1); \
READ_LITERAL_2PIXEL(src, p2); \
READ_LITERAL_2PIXEL(src, p3); \
READ_LITERAL_2PIXEL(src, p4); \
WRITE_2X1_LINE(dst, p1); \
WRITE_2X1_LINE(dst + pitch, p1); \
WRITE_2X1_LINE(dst + 2, p2); \
WRITE_2X1_LINE(dst + pitch + 2, p2); \
WRITE_2X1_LINE(dst + pitch * 2, p3); \
WRITE_2X1_LINE(dst + pitch * 2 + 2, p4); \
WRITE_2X1_LINE(dst + pitch * 3, p3); \
WRITE_2X1_LINE(dst + pitch * 3 + 2, p4); \
dst += 4; \
} while (0)
/* Fill sixteen 1x1 pixel blocks with literal pixel values */
#define LITERAL_1X1(src, dst, pitch) \
do { \
int x; \
for (x = 0; x < 4; x++) { \
COPY_4X1_LINE(dst + pitch * x, src); \
src += 4; \
} \
dst += 4; \
} while (0)
/* Copy a 4x4 pixel block from a different place in the framebuffer */
#define COPY_4X4(dst2, dst, pitch) \
do { \
int x; \
for (x=0; x<4; x++) { \
COPY_4X1_LINE(dst + pitch * x, dst2 + pitch * x); \
} \
dst += 4; \
} while (0)
void SmushDeltaBlocksDecoder::proc1(byte *dst, const byte *src, int32 nextOffs, int bw, int bh, int pitch, int16 *offsetTable) {
uint8 code;
bool filling, skipCode;
int32 len;
int i, p;
uint32 pitches[16];
i = bw;
for (p = 0; p < 16; ++p) {
pitches[p] = (p >> 2) * pitch + (p & 0x3);
}
code = 0;
filling = false;
len = -1;
while (1) {
if (len < 0) {
filling = (*src & 1) == 1;
len = *src++ >> 1;
skipCode = false;
} else {
skipCode = true;
}
if (!filling || !skipCode) {
code = *src++;
if (code == 0xFF) {
--len;
for (p = 0; p < 0x10; ++p) {
if (len < 0) {
filling = (*src & 1) == 1;
len = *src++ >> 1;
if (filling) {
code = *src++;
}
}
if (filling) {
*(dst + pitches[p]) = code;
} else {
*(dst + pitches[p]) = *src++;
}
--len;
}
dst += 4;
--i;
if (i == 0) {
dst += pitch * 3;
--bh;
if (bh == 0) return;
i = bw;
}
continue;
}
}
byte *dst2 = dst + offsetTable[code] + nextOffs;
COPY_4X4(dst2, dst, pitch);
--i;
if (i == 0) {
dst += pitch * 3;
--bh;
if (bh == 0) return;
i = bw;
}
--len;
}
}
void SmushDeltaBlocksDecoder::proc3WithFDFE(byte *dst, const byte *src, int32 nextOffs, int bw, int bh, int pitch, int16 *offsetTable) {
do {
int32 i = bw;
do {
int32 code = *src++;
if (code == 0xFD) {
LITERAL_4X4(src, dst, pitch);
} else if (code == 0xFE) {
LITERAL_2X2(src, dst, pitch);
} else if (code == 0xFF) {
LITERAL_1X1(src, dst, pitch);
} else {
byte *dst2 = dst + _offsetTable[code] + nextOffs;
COPY_4X4(dst2, dst, pitch);
}
} while (--i);
dst += pitch * 3;
} while (--bh);
}
void SmushDeltaBlocksDecoder::proc3WithoutFDFE(byte *dst, const byte *src, int32 nextOffs, int bw, int bh, int pitch, int16 *offsetTable) {
do {
int32 i = bw;
do {
int32 code = *src++;
if (code == 0xFF) {
LITERAL_1X1(src, dst, pitch);
} else {
byte *dst2 = dst + _offsetTable[code] + nextOffs;
COPY_4X4(dst2, dst, pitch);
}
} while (--i);
dst += pitch * 3;
} while (--bh);
}
void SmushDeltaBlocksDecoder::proc4WithFDFE(byte *dst, const byte *src, int32 nextOffs, int bw, int bh, int pitch, int16 *offsetTable) {
do {
int32 i = bw;
do {
int32 code = *src++;
if (code == 0xFD) {
LITERAL_4X4(src, dst, pitch);
} else if (code == 0xFE) {
LITERAL_4X1(src, dst, pitch);
} else if (code == 0xFF) {
LITERAL_1X1(src, dst, pitch);
} else if (code == 0x00) {
int32 length = *src++ + 1;
for (int32 l = 0; l < length; l++) {
byte *dst2 = dst + nextOffs;
COPY_4X4(dst2, dst, pitch);
i--;
if (i == 0) {
dst += pitch * 3;
bh--;
i = bw;
}
}
if (bh == 0) {
return;
}
i++;
} else {
byte *dst2 = dst + _offsetTable[code] + nextOffs;
COPY_4X4(dst2, dst, pitch);
}
} while (--i);
dst += pitch * 3;
} while (--bh);
}
void SmushDeltaBlocksDecoder::proc4WithoutFDFE(byte *dst, const byte *src, int32 nextOffs, int bw, int bh, int pitch, int16 *offsetTable) {
do {
int32 i = bw;
do {
int32 code = *src++;
if (code == 0xFF) {
LITERAL_1X1(src, dst, pitch);
} else if (code == 0x00) {
int32 length = *src++ + 1;
for (int32 l = 0; l < length; l++) {
byte *dst2 = dst + nextOffs;
COPY_4X4(dst2, dst, pitch);
i--;
if (i == 0) {
dst += pitch * 3;
bh--;
i = bw;
}
}
if (bh == 0) {
return;
}
i++;
} else {
byte *dst2 = dst + _offsetTable[code] + nextOffs;
COPY_4X4(dst2, dst, pitch);
}
} while (--i);
dst += pitch * 3;
} while (--bh);
}
void SmushDeltaBlocksDecoder::decode(byte *dst, const byte *src) {
int32 bw = (_width + 3) / 4, bh = (_height + 3) / 4;
int32 pitch = bw * 4;
int16 seqNb = READ_LE_UINT16(src + 2);
int32 decodedSize = READ_LE_UINT32(src + 4);
byte maskFlags = src[12];
makeTable(pitch, src[1]);
int32 tmp;
switch (src[0]) {
case 0:
if ((_deltaBufs[_curTable] - _deltaBuf) > 0) {
memset(_deltaBuf, 0, _deltaBufs[_curTable] - _deltaBuf);
}
tmp = (_deltaBuf + _deltaSize) - _deltaBufs[_curTable] - decodedSize;
if (tmp > 0) {
memset(_deltaBufs[_curTable] + decodedSize, 0, tmp);
}
memcpy(_deltaBufs[_curTable], src + 16, decodedSize);
break;
case 1:
if ((seqNb & 1) || !(maskFlags & 1)) {
_curTable ^= 1;
}
proc1(_deltaBufs[_curTable], src + 16, _deltaBufs[_curTable ^ 1] - _deltaBufs[_curTable],
bw, bh, pitch, _offsetTable);
break;
case 2:
bompDecodeLine(_deltaBufs[_curTable], src + 16, decodedSize);
if ((_deltaBufs[_curTable] - _deltaBuf) > 0) {
memset(_deltaBuf, 0, _deltaBufs[_curTable] - _deltaBuf);
}
tmp = (_deltaBuf + _deltaSize) - _deltaBufs[_curTable] - decodedSize;
if (tmp > 0) {
memset(_deltaBufs[_curTable] + decodedSize, 0, tmp);
}
break;
case 3:
if ((seqNb & 1) || !(maskFlags & 1)) {
_curTable ^= 1;
}
if ((maskFlags & 4) != 0) {
proc3WithFDFE(_deltaBufs[_curTable], src + 16,
_deltaBufs[_curTable ^ 1] - _deltaBufs[_curTable], bw, bh,
pitch, _offsetTable);
} else {
proc3WithoutFDFE(_deltaBufs[_curTable], src + 16,
_deltaBufs[_curTable ^ 1] - _deltaBufs[_curTable], bw, bh,
pitch, _offsetTable);
}
break;
case 4:
if ((seqNb & 1) || !(maskFlags & 1)) {
_curTable ^= 1;
}
if ((maskFlags & 4) != 0) {
proc4WithFDFE(_deltaBufs[_curTable], src + 16,
_deltaBufs[_curTable ^ 1] - _deltaBufs[_curTable], bw, bh,
pitch, _offsetTable);
} else {
proc4WithoutFDFE(_deltaBufs[_curTable], src + 16,
_deltaBufs[_curTable ^ 1] - _deltaBufs[_curTable], bw, bh,
pitch, _offsetTable);
}
break;
default:
break;
}
_prevSeqNb = seqNb;
memcpy(dst, _deltaBufs[_curTable], _frameSize);
}
} // End of namespace Scumm

View File

@@ -0,0 +1,59 @@
/* 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/>.
*
*/
#ifndef SCUMM_SMUSH_CODEC37_H
#define SCUMM_SMUSH_CODEC37_H
#include "common/scummsys.h"
namespace Scumm {
class SmushDeltaBlocksDecoder {
private:
int32 _deltaSize;
byte *_deltaBufs[2];
byte *_deltaBuf;
int16 *_offsetTable;
int _curTable;
uint16 _prevSeqNb;
int _tableLastPitch;
int _tableLastIndex;
int32 _frameSize;
int _width, _height;
public:
SmushDeltaBlocksDecoder(int width, int height);
~SmushDeltaBlocksDecoder();
protected:
void makeTable(int, int);
void proc1(byte *dst, const byte *src, int32, int, int, int, int16 *);
void proc3WithFDFE(byte *dst, const byte *src, int32, int, int, int, int16 *);
void proc3WithoutFDFE(byte *dst, const byte *src, int32, int, int, int, int16 *);
void proc4WithFDFE(byte *dst, const byte *src, int32, int, int, int, int16 *);
void proc4WithoutFDFE(byte *dst, const byte *src, int32, int, int, int, int16 *);
public:
void decode(byte *dst, const byte *src);
};
} // End of namespace Scumm
#endif

View File

@@ -0,0 +1,639 @@
/* 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/textconsole.h"
#include "common/util.h"
#include "scumm/bomp.h"
#include "scumm/smush/codec47.h"
namespace Scumm {
#if defined(SCUMM_NEED_ALIGNMENT)
#define COPY_4X1_LINE(dst, src) \
do { \
(dst)[0] = (src)[0]; \
(dst)[1] = (src)[1]; \
(dst)[2] = (src)[2]; \
(dst)[3] = (src)[3]; \
} while (0)
#define COPY_2X1_LINE(dst, src) \
do { \
(dst)[0] = (src)[0]; \
(dst)[1] = (src)[1]; \
} while (0)
#else /* SCUMM_NEED_ALIGNMENT */
#define COPY_4X1_LINE(dst, src) \
*(uint32 *)(dst) = *(const uint32 *)(src)
#define COPY_2X1_LINE(dst, src) \
*(uint16 *)(dst) = *(const uint16 *)(src)
#endif
#define FILL_4X1_LINE(dst, val) \
do { \
(dst)[0] = val; \
(dst)[1] = val; \
(dst)[2] = val; \
(dst)[3] = val; \
} while (0)
#define FILL_2X1_LINE(dst, val) \
do { \
(dst)[0] = val; \
(dst)[1] = val; \
} while (0)
#define MOTION_OFFSET_TABLE_SIZE 0xF8
#define PROCESS_SUBBLOCKS 0xFF
#define FILL_SINGLE_COLOR 0xFE
#define DRAW_GLYPH 0xFD
#define COPY_PREV_BUFFER 0xFC
static const int8 codecGlyph4XVec[] = {
0, 1, 2, 3, 3, 3, 3, 2, 1, 0, 0, 0, 1, 2, 2, 1,
};
static const int8 codecGlyph4YVec[] = {
0, 0, 0, 0, 1, 2, 3, 3, 3, 3, 2, 1, 1, 1, 2, 2,
};
static const int8 codecGlyph8XVec[] = {
0, 2, 5, 7, 7, 7, 7, 7, 7, 5, 2, 0, 0, 0, 0, 0,
};
static const int8 codecGlyph8YVec[] = {
0, 0, 0, 0, 1, 3, 4, 6, 7, 7, 7, 7, 6, 4, 3, 1,
};
static const int8 codecTable[] = {
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
};
enum Edge {
kEdgeLeft,
kEdgeTop,
kEdgeRight,
kEdgeBottom,
kEdgeNone,
};
#define NGLYPHS 256
void SmushDeltaGlyphsDecoder::makeTablesInterpolation(int sideLength) {
int32 pos, npoints;
int32 edge0, edge1;
int32 x1, x0, y1, y0;
int32 tableSmallBig[64], s;
const int8 *xGlyph = nullptr, *yGlyph = nullptr;
int32 *ptrSmallBig;
byte *ptr;
int i, x, y;
if (sideLength == 8) {
xGlyph = codecGlyph8XVec;
yGlyph = codecGlyph8YVec;
ptr = _tableBig;
for (i = 0; i < NGLYPHS; i++) {
ptr[384] = 0;
ptr[385] = 0;
ptr += 388;
}
} else if (sideLength == 4) {
xGlyph = codecGlyph4XVec;
yGlyph = codecGlyph4YVec;
ptr = _tableSmall;
for (i = 0; i < NGLYPHS; i++) {
ptr[96] = 0;
ptr[97] = 0;
ptr += 128;
}
} else {
error("SmushDeltaGlyphsDecoder::makeTablesInterpolation(): ERROR: Unknown sideLength %d.", sideLength);
}
s = 0;
for (x = 0; x < 16; x++) {
x0 = xGlyph[x];
y0 = yGlyph[x];
if (y0 == 0) {
edge0 = kEdgeBottom;
} else if (y0 == sideLength - 1) {
edge0 = kEdgeTop;
} else if (x0 == 0) {
edge0 = kEdgeLeft;
} else if (x0 == sideLength - 1) {
edge0 = kEdgeRight;
} else {
edge0 = kEdgeNone;
}
for (y = 0; y < 16; y++) {
x1 = xGlyph[y];
y1 = yGlyph[y];
if (y1 == 0) {
edge1 = kEdgeBottom;
} else if (y1 == sideLength - 1) {
edge1 = kEdgeTop;
} else if (x1 == 0) {
edge1 = kEdgeLeft;
} else if (x1 == sideLength - 1) {
edge1 = kEdgeRight;
} else {
edge1 = kEdgeNone;
}
memset(tableSmallBig, 0, sideLength * sideLength * 4);
npoints = MAX(ABS(y1 - y0), ABS(x1 - x0));
for (pos = 0; pos <= npoints; pos++) {
int32 yPoint, xPoint;
if (npoints > 0) {
// Linearly interpolate between x0 and x1
// respectively y0 and y1.
xPoint = (x0 * pos + x1 * (npoints - pos) + npoints / 2) / npoints;
yPoint = (y0 * pos + y1 * (npoints - pos) + npoints / 2) / npoints;
} else {
xPoint = x0;
yPoint = y0;
}
ptrSmallBig = &tableSmallBig[sideLength * yPoint + xPoint];
*ptrSmallBig = 1;
if ((edge0 == kEdgeLeft && edge1 == kEdgeRight) || (edge1 == kEdgeLeft && edge0 == kEdgeRight) ||
(edge0 == kEdgeBottom && edge1 != kEdgeTop) || (edge1 == kEdgeBottom && edge0 != kEdgeTop)) {
if (yPoint >= 0) {
i = yPoint + 1;
while (i--) {
*ptrSmallBig = 1;
ptrSmallBig -= sideLength;
}
}
} else if ((edge1 != kEdgeBottom && edge0 == kEdgeTop) || (edge0 != kEdgeBottom && edge1 == kEdgeTop)) {
if (sideLength > yPoint) {
i = sideLength - yPoint;
while (i--) {
*ptrSmallBig = 1;
ptrSmallBig += sideLength;
}
}
} else if ((edge0 == kEdgeLeft && edge1 != kEdgeRight) || (edge1 == kEdgeLeft && edge0 != kEdgeRight)) {
if (xPoint >= 0) {
i = xPoint + 1;
while (i--) {
*(ptrSmallBig--) = 1;
}
}
} else if ((edge0 == kEdgeBottom && edge1 == kEdgeTop) || (edge1 == kEdgeBottom && edge0 == kEdgeTop) ||
(edge0 == kEdgeRight && edge1 != kEdgeLeft) || (edge1 == kEdgeRight && edge0 != kEdgeLeft)) {
if (sideLength > xPoint) {
i = sideLength - xPoint;
while (i--) {
*(ptrSmallBig++) = 1;
}
}
}
}
if (sideLength == 8) {
for (i = 64 - 1; i >= 0; i--) {
if (tableSmallBig[i] != 0) {
_tableBig[256 + s + _tableBig[384 + s]] = (byte)i;
_tableBig[384 + s]++;
} else {
_tableBig[320 + s + _tableBig[385 + s]] = (byte)i;
_tableBig[385 + s]++;
}
}
s += 388;
}
if (sideLength == 4) {
for (i = 16 - 1; i >= 0; i--) {
if (tableSmallBig[i] != 0) {
_tableSmall[64 + s + _tableSmall[96 + s]] = (byte)i;
_tableSmall[96 + s]++;
} else {
_tableSmall[80 + s + _tableSmall[97 + s]] = (byte)i;
_tableSmall[97 + s]++;
}
}
s += 128;
}
}
}
}
void SmushDeltaGlyphsDecoder::makeCodecTables(int width) {
if (_lastTableWidth == width)
return;
_lastTableWidth = width;
int32 a, c, d;
int16 tmp;
for (int l = 0; l < ARRAYSIZE(codecTable); l += 2) {
_table[l / 2] = (int16)(codecTable[l + 1] * width + codecTable[l]);
}
// Note: _table[255] is never inited; but since only the first 0xF8
// entries of it are used anyway, this doesn't matter.
a = 0;
c = 0;
do {
for (d = 0; d < _tableSmall[96 + c]; d++) {
tmp = _tableSmall[64 + c + d];
tmp = (int16)((byte)(tmp >> 2) * width + (tmp & 3));
_tableSmall[c + d * 2] = (byte)tmp;
_tableSmall[c + d * 2 + 1] = tmp >> 8;
}
for (d = 0; d < _tableSmall[97 + c]; d++) {
tmp = _tableSmall[80 + c + d];
tmp = (int16)((byte)(tmp >> 2) * width + (tmp & 3));
_tableSmall[32 + c + d * 2] = (byte)tmp;
_tableSmall[32 + c + d * 2 + 1] = tmp >> 8;
}
for (d = 0; d < _tableBig[384 + a]; d++) {
tmp = _tableBig[256 + a + d];
tmp = (int16)((byte)(tmp >> 3) * width + (tmp & 7));
_tableBig[a + d * 2] = (byte)tmp;
_tableBig[a + d * 2 + 1] = tmp >> 8;
}
for (d = 0; d < _tableBig[385 + a]; d++) {
tmp = _tableBig[320 + a + d];
tmp = (int16)((byte)(tmp >> 3) * width + (tmp & 7));
_tableBig[128 + a + d * 2] = (byte)tmp;
_tableBig[128 + a + d * 2 + 1] = tmp >> 8;
}
a += 388;
c += 128;
} while (c < 32768);
}
#ifdef USE_ARM_SMUSH_ASM
#ifndef IPHONE
#define ARM_Smush_decode2 _ARM_Smush_decode2
#endif
extern "C" void ARM_Smush_decode2( byte *dst,
const byte *src,
int width,
int height,
const byte *param_ptr,
int16 *_table,
byte *_tableBig,
int32 offset1,
int32 offset2,
byte *_tableSmall);
#define decode2(SRC,DST,WIDTH,HEIGHT,PARAM) \
ARM_Smush_decode2(SRC,DST,WIDTH,HEIGHT,PARAM,_table,_tableBig, \
_offset1,_offset2,_tableSmall)
#else
void SmushDeltaGlyphsDecoder::level3(byte *dDst) {
int32 tmp;
byte code = *_dSrc++;
if (code < MOTION_OFFSET_TABLE_SIZE) {
tmp = _table[code] + _offset1;
COPY_2X1_LINE(dDst, dDst + tmp);
COPY_2X1_LINE(dDst + _dPitch, dDst + _dPitch + tmp);
} else if (code == PROCESS_SUBBLOCKS) {
COPY_2X1_LINE(dDst, _dSrc + 0);
COPY_2X1_LINE(dDst + _dPitch, _dSrc + 2);
_dSrc += 4;
} else if (code == FILL_SINGLE_COLOR) {
byte t = *_dSrc++;
FILL_2X1_LINE(dDst, t);
FILL_2X1_LINE(dDst + _dPitch, t);
} else if (code == COPY_PREV_BUFFER) {
tmp = _offset2;
COPY_2X1_LINE(dDst, dDst + tmp);
COPY_2X1_LINE(dDst + _dPitch, dDst + _dPitch + tmp);
} else {
byte t = _paramPtr[code];
FILL_2X1_LINE(dDst, t);
FILL_2X1_LINE(dDst + _dPitch, t);
}
}
void SmushDeltaGlyphsDecoder::level2(byte *d_dst) {
int32 tmp;
byte code = *_dSrc++;
int i;
if (code < MOTION_OFFSET_TABLE_SIZE) {
tmp = _table[code] + _offset1;
for (i = 0; i < 4; i++) {
COPY_4X1_LINE(d_dst, d_dst + tmp);
d_dst += _dPitch;
}
} else if (code == PROCESS_SUBBLOCKS) {
level3(d_dst);
d_dst += 2;
level3(d_dst);
d_dst += _dPitch * 2 - 2;
level3(d_dst);
d_dst += 2;
level3(d_dst);
} else if (code == FILL_SINGLE_COLOR) {
byte t = *_dSrc++;
for (i = 0; i < 4; i++) {
FILL_4X1_LINE(d_dst, t);
d_dst += _dPitch;
}
} else if (code == DRAW_GLYPH) {
byte *tmpPtr = _tableSmall + *_dSrc++ * 128;
int32 l = tmpPtr[96];
byte val = *_dSrc++;
int16 *tmpPtr2 = (int16 *)tmpPtr;
while (l--) {
*(d_dst + READ_LE_UINT16(tmpPtr2)) = val;
tmpPtr2++;
}
l = tmpPtr[97];
val = *_dSrc++;
tmpPtr2 = (int16 *)(tmpPtr + 32);
while (l--) {
*(d_dst + READ_LE_UINT16(tmpPtr2)) = val;
tmpPtr2++;
}
} else if (code == COPY_PREV_BUFFER) {
tmp = _offset2;
for (i = 0; i < 4; i++) {
COPY_4X1_LINE(d_dst, d_dst + tmp);
d_dst += _dPitch;
}
} else {
byte t = _paramPtr[code];
for (i = 0; i < 4; i++) {
FILL_4X1_LINE(d_dst, t);
d_dst += _dPitch;
}
}
}
void SmushDeltaGlyphsDecoder::level1(byte *d_dst) {
int32 tmp;
byte code = *_dSrc++;
int i;
if (code < MOTION_OFFSET_TABLE_SIZE) {
tmp = _table[code] + _offset1;
for (i = 0; i < 8; i++) {
COPY_4X1_LINE(d_dst + 0, d_dst + tmp);
COPY_4X1_LINE(d_dst + 4, d_dst + tmp + 4);
d_dst += _dPitch;
}
} else if (code == PROCESS_SUBBLOCKS) {
level2(d_dst);
d_dst += 4;
level2(d_dst);
d_dst += _dPitch * 4 - 4;
level2(d_dst);
d_dst += 4;
level2(d_dst);
} else if (code == FILL_SINGLE_COLOR) {
byte t = *_dSrc++;
for (i = 0; i < 8; i++) {
FILL_4X1_LINE(d_dst, t);
FILL_4X1_LINE(d_dst + 4, t);
d_dst += _dPitch;
}
} else if (code == DRAW_GLYPH) {
tmp = *_dSrc++;
byte *tmpPtr = _tableBig + tmp * 388;
byte l = tmpPtr[384];
byte val = *_dSrc++;
int16 *tmpPtr2 = (int16 *)tmpPtr;
while (l--) {
*(d_dst + READ_LE_UINT16(tmpPtr2)) = val;
tmpPtr2++;
}
l = tmpPtr[385];
val = *_dSrc++;
tmpPtr2 = (int16 *)(tmpPtr + 128);
while (l--) {
*(d_dst + READ_LE_UINT16(tmpPtr2)) = val;
tmpPtr2++;
}
} else if (code == COPY_PREV_BUFFER) {
tmp = _offset2;
for (i = 0; i < 8; i++) {
COPY_4X1_LINE(d_dst + 0, d_dst + tmp);
COPY_4X1_LINE(d_dst + 4, d_dst + tmp + 4);
d_dst += _dPitch;
}
} else {
byte t = _paramPtr[code];
for (i = 0; i < 8; i++) {
FILL_4X1_LINE(d_dst, t);
FILL_4X1_LINE(d_dst + 4, t);
d_dst += _dPitch;
}
}
}
void SmushDeltaGlyphsDecoder::decode2(byte *dst, const byte *src, int width, int height, const byte *param_ptr) {
_dSrc = src;
_paramPtr = param_ptr - MOTION_OFFSET_TABLE_SIZE;
int bw = (width + 7) / 8;
int bh = (height + 7) / 8;
int nextLine = width * 7;
_dPitch = width;
do {
int tmpBw = bw;
do {
level1(dst);
dst += 8;
} while (--tmpBw);
dst += nextLine;
} while (--bh);
}
#endif
SmushDeltaGlyphsDecoder::SmushDeltaGlyphsDecoder(int width, int height) : _prevSeqNb(0), _dSrc(nullptr), _paramPtr(nullptr), _dPitch(0), _offset1(0), _offset2(0) {
_lastTableWidth = -1;
_width = width;
_height = height;
_tableBig = (byte *)malloc(NGLYPHS * 388);
_tableSmall = (byte *)malloc(NGLYPHS * 128);
if ((_tableBig != nullptr) && (_tableSmall != nullptr)) {
makeTablesInterpolation(4);
makeTablesInterpolation(8);
}
_frameSize = _width * _height;
_deltaSize = _frameSize * 3;
_deltaBuf = (byte *)malloc(_deltaSize);
_deltaBufs[0] = _deltaBuf;
_deltaBufs[1] = _deltaBuf + _frameSize;
_curBuf = _deltaBuf + _frameSize * 2;
}
SmushDeltaGlyphsDecoder::~SmushDeltaGlyphsDecoder() {
if (_tableBig) {
free(_tableBig);
_tableBig = nullptr;
}
if (_tableSmall) {
free(_tableSmall);
_tableSmall = nullptr;
}
_lastTableWidth = -1;
if (_deltaBuf) {
free(_deltaBuf);
_deltaSize = 0;
_deltaBuf = nullptr;
_deltaBufs[0] = nullptr;
_deltaBufs[1] = nullptr;
}
}
bool SmushDeltaGlyphsDecoder::decode(byte *dst, const byte *src) {
if ((_tableBig == nullptr) || (_tableSmall == nullptr) || (_deltaBuf == nullptr))
return false;
_offset1 = _deltaBufs[1] - _curBuf;
_offset2 = _deltaBufs[0] - _curBuf;
int32 seqNb = READ_LE_UINT16(src + 0);
const byte *gfxData = src + 26;
if (seqNb == 0) {
makeCodecTables(_width);
memset(_deltaBufs[0], src[12], _frameSize);
memset(_deltaBufs[1], src[13], _frameSize);
_prevSeqNb = -1;
}
if ((src[4] & 1) != 0) {
gfxData += 32896;
}
switch (src[2]) {
case 0:
memcpy(_curBuf, gfxData, _frameSize);
break;
case 1:
// Used by Outlaws, but not by any SCUMM game.
error("SmushDeltaGlyphsDecoder::decode(): ERROR: Case 1 not implemented (used by Outlaws).");
break;
case 2:
if (seqNb == _prevSeqNb + 1) {
decode2(_curBuf, gfxData, _width, _height, src + 8);
}
break;
case 3:
memcpy(_curBuf, _deltaBufs[1], _frameSize);
break;
case 4:
memcpy(_curBuf, _deltaBufs[0], _frameSize);
break;
case 5:
bompDecodeLine(_curBuf, gfxData, READ_LE_UINT32(src + 14));
break;
default:
break;
}
memcpy(dst, _curBuf, _frameSize);
if (seqNb == _prevSeqNb + 1) {
if (src[3] == 1) {
SWAP(_curBuf, _deltaBufs[1]);
} else if (src[3] == 2) {
SWAP(_deltaBufs[0], _deltaBufs[1]);
SWAP(_deltaBufs[1], _curBuf);
}
}
_prevSeqNb = seqNb;
return true;
}
} // End of namespace Scumm

View File

@@ -0,0 +1,62 @@
/* 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/>.
*
*/
#ifndef SCUMM_SMUSH_CODEC_47_H
#define SCUMM_SMUSH_CODEC_47_H
#include "common/scummsys.h"
namespace Scumm {
class SmushDeltaGlyphsDecoder {
private:
int32 _deltaSize;
byte *_deltaBufs[2];
byte *_deltaBuf;
byte *_curBuf;
int32 _prevSeqNb;
int _lastTableWidth;
const byte *_dSrc, *_paramPtr;
int _dPitch;
int32 _offset1, _offset2;
byte *_tableBig;
byte *_tableSmall;
int16 _table[256];
int32 _frameSize;
int _width, _height;
void makeTablesInterpolation(int param);
void makeCodecTables(int width);
void level1(byte *d_dst);
void level2(byte *d_dst);
void level3(byte *d_dst);
void decode2(byte *dst, const byte *src, int width, int height, const byte *param_ptr);
public:
SmushDeltaGlyphsDecoder(int width, int height);
~SmushDeltaGlyphsDecoder();
bool decode(byte *dst, const byte *src);
};
} // End of namespace Scumm
#endif

View File

@@ -0,0 +1,369 @@
@ 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/>.
@
@ @author Robin Watts (robin@wss.co.uk)
@
@ This file, provides an ARM optimised version of sections of codec47.cpp.
@ The algorithm is essentially the same as that within codec47.cpp
@ so to understand this file you should understand codec47.cpp first.
.text
.global _ARM_Smush_decode2
.align 2
_ARM_Smush_decode2:
@ r0 = dst
@ r1 = src
@ r2 = width
@ r3 = height
@ r4 = param
@ <> = _table
@ <> = _tableBig
@ <> = _offset1
@ <> = _offset2
@ <> = _tableSmall
STMFD r13!,{r2,r4-r11,R14}
LDR r4,[r13,#40] @ r4 = param (40 = (9+1)*4)
@ stall
@ stall
SUB r4,r4,#0xF8
@ r0 = dst
@ r1 = _d_src
@ r2 = _d_pitch
@ r3 = height
@ r4 = param
ADD r7,r2,#7 @ r14 = bw
MOV r7,r7,LSR #3
y_loop:
x_loop:
@ LEVEL 1
LDRB r6,[r1],#1 @ r6 = *_d_src++
@ stall
@ stall
CMP r6,#0xF8
BLT level1codeSMALL
CMP r6,#0xFC
BLT level1codeMID
BEQ level1codeFC
CMP r6,#0xFE
BGT level1codeFF
BEQ level1codeFE
level1codeFD:
LDRB r6,[r1],#1 @ r6 = tmp = *_d_src++
LDR r8,[r13,#48] @ r8 = _tableBig (48 = (9+1+2)*4)
@ stall
ADD r12,r6,r6,LSL #1 @ r12= tmp*3
ADD r6,r6,r12,LSL #5 @ r6 = tmp*97
ADD r8,r8,r6,LSL #2 @ r8 = _tableBig + tmp*388
LDRB r9,[r8,#384] @ r9 = l = tmp_ptr[384]
LDRB r6,[r1],#1 @ r6 = val = *_d_src++
ADD r12,r8,#384 @ r12= &tmp_ptr[384]
@ I don''t really believe the next 2 lines are necessary, but...
CMP r9,#0
BEQ level1codeFD_over1
level1codeFD_loop1:
LDRB r10,[r8],#1
LDRB r11,[r8],#1
SUBS r9,r9,#1
ADD r10,r10,r0
STRB r6,[r10,r11,LSL #8] @ *(_d_dst + (*tmp_ptr2++)) = val
BGT level1codeFD_loop1
level1codeFD_over1:
LDRB r9,[r12,#1] @ r9 = l = tmp_ptr[385]
LDRB r6,[r1],#1 @ r6 = val = *_d_src++
SUB r12,r12,#256 @ r12= &tmp_ptr[128] (256 = 384-128)
@ I don''t really believe the next 2 lines are necessary, but...
CMP r9,#0
BEQ level1codeFD_over2
level1codeFD_loop2:
LDRB r10,[r12],#1
LDRB r11,[r12],#1
SUBS r9,r9,#1
ADD r10,r10,r0
STRB r6,[r10,r11,LSL #8] @ *(_d_dst + (*tmp_ptr2++)) = val
BGT level1codeFD_loop2
level1codeFD_over2:
level1_end:
ADD r0,r0,#8
SUBS r7,r7,#1
BGT x_loop
ADD r7,r2,#7
MOV r7,r7,LSR #3
ADD r0,r0,r2,LSL #3
SUB r0,r0,r7,LSL #3 @ r0 = dst += next_line
SUBS r3,r3,#8 @ if (--bh > 0)
BGT y_loop @ loop back
LDMFD r13!,{r2,r4-r11,PC}
level1codeSMALL:
LDR r8,[r13,#44] @ r8 = _table (44 = (9+1+1)*4)
LDR r9,[r13,#52] @ r9 = _offset1 (52 = (9+1+3)*4)
MOV r6,r6,LSL #1 @ r6 = code<<1
LDRSH r8,[r8,r6] @ tmp2 = _table[code]
level1codeFC:
@ EQ => FC
LDREQ r9,[r13,#56] @ r9 = _offset2 (56 = (9+1+4)*4)
MOVEQ r8,#0
SUB r11,r2,#7 @ r11 = _d_pitch-7
ADD r9,r9,r0 @ tmp2 = _d_dst+_offset
ADD r8,r8,r9 @ tmp2 = _d_dst+_table[code]+_offset
@ r8 = &_dst[tmp2]
MOV r12,#8
level1codeSMALL_loop:
LDRB r5, [r8],#1 @ r5 = d_dst[tmp2]
LDRB r6, [r8],#1 @ r10 = d_dst[tmp2]
LDRB r9, [r8],#1 @ r10 = d_dst[tmp2]
LDRB r10,[r8],#1 @ r10 = d_dst[tmp2]
STRB r5, [r0],#1 @ d_dst[0] = r5
STRB r6, [r0],#1 @ d_dst[1] = r6
STRB r9, [r0],#1 @ d_dst[2] = r9
STRB r10,[r0],#1 @ d_dst[3] = r10
LDRB r5, [r8],#1 @ r5 = d_dst[tmp2]
LDRB r6, [r8],#1 @ r10 = d_dst[tmp2]
LDRB r9, [r8],#1 @ r10 = d_dst[tmp2]
LDRB r10,[r8],r11 @ r10 = d_dst[tmp2]
STRB r5, [r0],#1 @ d_dst[4] = r5
STRB r6, [r0],#1 @ d_dst[5] = r6
STRB r9, [r0],#1 @ d_dst[6] = r9
STRB r10,[r0],r11 @ d_dst[7] = r10 d_dst += d_pitch
SUBS r12,r12,#1
BGT level1codeSMALL_loop
SUB r0,r0,r2,LSL #3 @ revert d_dst
B level1_end
level1codeMID:
@ LT => F8<=code<FC case
@ EQ => FE case
LDRB r6,[r4,r6] @ r6 = t = _paramPtr[code]
level1codeFE:
LDREQB r6,[r1],#1 @ r6 = t = *_d_src++
MOV r12,#8
SUB r11,r2,#7 @ r11 = _d_pitch-7
level1codeMID_loop:
STRB r6,[r0],#1
STRB r6,[r0],#1
STRB r6,[r0],#1
STRB r6,[r0],#1
STRB r6,[r0],#1
STRB r6,[r0],#1
STRB r6,[r0],#1
STRB r6,[r0],r11
SUBS r12,r12,#1
BGT level1codeMID_loop
SUB r0,r0,r2,LSL #3 @ revert d_dst
B level1_end
level1codeFF:
BL level2
ADD r0,r0,#4
BL level2
ADD r0,r0,r2,LSL #2
SUB r0,r0,#4
BL level2
ADD r0,r0,#4
BL level2
SUB r0,r0,#4
SUB r0,r0,r2,LSL #2
B level1_end
level2:
@ r0 = _d_dst
@ r1 = _d_src
@ r2 = _d_pitch
@ r3 = PRESERVE
@ r4 = param
@ r7 = PRESERVE
@ r14= return address
LDRB r6,[r1],#1 @ r6 = *_d_src++
@ stall
@ stall
CMP r6,#0xF8
BLT level2codeSMALL
CMP r6,#0xFC
BLT level2codeMID
BEQ level2codeFC
CMP r6,#0xFE
BGT level2codeFF
BEQ level2codeFE
level2codeFD:
LDRB r6,[r1],#1 @ r6 = tmp = *_d_src++
LDR r8,[r13,#60] @ r8 = _tableSmall (60 = (9+1+5)*4)
@ stall
@ stall
ADD r8,r8,r6,LSL #7 @ r8 = _tableSmall + tmp*128
LDRB r9,[r8,#96] @ r9 = l = tmp_ptr[96]
LDRB r6,[r1],#1 @ r6 = val = *_d_src++
ADD r12,r8,#32 @ r12 = tmp_ptr + 32
@ I don''t really believe the next 2 lines are necessary, but...
CMP r9,#0
BEQ level2codeFD_over1
level2codeFD_loop1:
LDRB r10,[r8],#1
LDRB r11,[r8],#1
SUBS r9,r9,#1
ADD r10,r10,r0
STRB r6,[r10,r11,LSL #8] @ *(_d_dst + (*tmp_ptr2++)) = val
BGT level2codeFD_loop1
level2codeFD_over1:
LDRB r9,[r12,#65] @ r9 = l = tmp_ptr[97] (65 = 97-32)
LDRB r6,[r1],#1 @ r6 = val = *_d_src++
@ I don''t really believe the next 2 lines are necessary, but...
CMP r9,#0
MOVEQ PC,R14
level2codeFD_loop2:
LDRB r10,[r12],#1
LDRB r11,[r12],#1
SUBS r9,r9,#1
ADD r10,r10,r0
STRB r6,[r10,r11,LSL #8] @ *(_d_dst + (*tmp_ptr2++)) = val
BGT level2codeFD_loop2
MOV PC,R14
level2codeSMALL:
LDR r8,[r13,#44] @ r8 = _table (44 = (9+1+1)*4)
LDR r9,[r13,#52] @ r9 = _offset1 (52 = (9+1+3)*4)
MOV r6,r6,LSL #1 @ r6 = code<<1
LDRSH r8,[r8,r6] @ tmp2 = _table[code]
level2codeFC:
@ EQ => FC
LDREQ r9,[r13,#56] @ r9 = _offset2 (56 = (9+1+4)*4)
MOVEQ r8,#0
SUB r11,r2,#3 @ r11 = _d_pitch-3
ADD r9,r9,r0 @ tmp2 = _d_dst + _table[code]
ADD r8,r8,r9 @ tmp2 = _d_dst+_table[code]+_offset1
@ r8 = &_dst[tmp2]
MOV r12,#4
level2codeSMALL_loop:
LDRB r5, [r8],#1 @ r5 = d_dst[tmp2]
LDRB r6, [r8],#1 @ r10 = d_dst[tmp2]
LDRB r9, [r8],#1 @ r10 = d_dst[tmp2]
LDRB r10,[r8],r11 @ r10 = d_dst[tmp2]
STRB r5, [r0],#1 @ d_dst[4] = r5
STRB r6, [r0],#1 @ d_dst[5] = r6
STRB r9, [r0],#1 @ d_dst[6] = r9
STRB r10,[r0],r11 @ d_dst[7] = r10 d_dst += d_pitch
SUBS r12,r12,#1
BGT level2codeSMALL_loop
SUB r0,r0,r2,LSL #2 @ revert d_dst
MOV PC,R14
level2codeMID:
@ LT => F8<=code<FC case
@ EQ => FE case
LDRB r6,[r4,r6] @ r6 = t = _paramPtr[code]
level2codeFE:
LDREQB r6,[r1],#1 @ r6 = t = *_d_src++
MOV r12,#4
SUB r11,r2,#3 @ r11 = _d_pitch-7
level2codeMID_loop:
STRB r6,[r0],#1
STRB r6,[r0],#1
STRB r6,[r0],#1
STRB r6,[r0],r11
SUBS r12,r12,#1
BGT level2codeMID_loop
SUB r0,r0,r2,LSL #2 @ revert d_dst
MOV PC,R14
level2codeFF:
MOV r5,r14
BL level3
ADD r0,r0,#2
BL level3
ADD r0,r0,r2,LSL #1
SUB r0,r0,#2
BL level3
ADD r0,r0,#2
BL level3
SUB r0,r0,#2
SUB r0,r0,r2,LSL #1
MOV PC,R5
level3:
@ r0 = _d_dst
@ r1 = _d_src
@ r2 = _d_pitch
@ r3 = PRESERVE
@ r4 = param
@ r5 = preserve
@ r7 = PRESERVE
@ r14= return address
LDRB r6,[r1],#1 @ r6 = code = *_d_src++
@ stall
@ stall
CMP r6,#0xF8
BLT level3codeSMALL
CMP r6,#0xFC
BLT level3codeMID
BEQ level3codeFC
CMP r6,#0xFE
BGT level3codeFF
level3codeFE:
LDRB r6,[r1],#1 @ r6 = t = *_d_src++
level3codeMID:
@ LT => F8<=code<FC case
@ EQ => FE case
LDRLTB r6,[r4,r6] @ r6 = t = _paramPtr[code]
@ stall
@ stall
STRB r6,[r0,#1]
STRB r6,[r0],r2
STRB r6,[r0,#1]
STRB r6,[r0],-r2
MOV PC,R14
level3codeFF:
LDRB r6,[r1],#1
LDRB r9,[r1],#1
LDRB r10,[r1],#1
LDRB r11,[r1],#1
STRB r9, [r0,#1]
STRB r6, [r0],r2
STRB r11,[r0,#1]
STRB r10,[r0],-r2
MOV PC,R14
level3codeSMALL:
LDR r8,[r13,#44] @ r8 = _table (44 = (9+1+1)*4)
LDR r9,[r13,#52] @ r9 = _offset1 (52 = (9+1+3)*4)
MOV r6,r6,LSL #1 @ r6 = code<<1
LDRSH r8,[r8,r6] @ tmp2 = _table[code]
level3codeFC:
@ EQ => FC
LDREQ r9,[r13,#56] @ r9 = _offset2 (56 = (9+1+4)*4)
MOVEQ r8,#0
ADD r9,r9,r0 @ tmp2 = _d_dst+offset
ADD r8,r8,r9 @ tmp2 = _d_dst+_table[code]+_offset
@ r8 = &_dst[tmp2]
LDRB r6, [r8,#1] @ r6 = d_dst[tmp2+1]
LDRB r9, [r8],r2 @ r9 = d_dst[tmp2+0]
LDRB r10,[r8,#1] @ r10= d_dst[tmp2+dst+1]
LDRB r11,[r8],-r2 @ r11= d_dst[tmp2+dst]
STRB r6, [r0,#1] @ d_dst[1 ] = r6
STRB r9, [r0],r2 @ d_dst[0 ] = r9
STRB r10,[r0,#1] @ d_dst[dst+1] = r10
STRB r11,[r0],-r2 @ d_dst[dst ] = r11
MOV PC,R14

View File

@@ -0,0 +1,70 @@
/* 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/>.
*
*/
#ifndef SCUMM_SMUSH_FONT_H
#define SCUMM_SMUSH_FONT_H
#include "common/scummsys.h"
#include "scumm/nut_renderer.h"
#include "scumm/scumm.h"
#include "scumm/string_v7.h"
namespace Scumm {
class SmushFont : public NutRenderer, public GlyphRenderer_v7 {
public:
SmushFont(ScummEngine *vm, const char *filename, bool useOriginalColors) :
NutRenderer(vm, filename), _hardcodedFontColors(useOriginalColors) {
_r = new TextRenderer_v7(vm, this);
}
~SmushFont() override { delete _r;}
void drawString(const char *str, byte *buffer, Common::Rect &clipRect, int x, int y, int16 col, TextStyleFlags flags) {
_r->drawString(str, buffer, clipRect, x, y, _vm->_screenWidth, col, flags);
}
void drawStringWrap(const char *str, byte *buffer, Common::Rect &clipRect, int x, int y, int16 col, TextStyleFlags flags) {
_r->drawStringWrap(str, buffer, clipRect, x, y, _vm->_screenWidth, col, flags);
}
private:
int draw2byte(byte *buffer, Common::Rect &clipRect, int x, int y, int pitch, int16 col, uint16 chr) override {
return NutRenderer::draw2byte(buffer, clipRect, x, y, pitch, _vm->_game.id == GID_CMI ? 255 : (_vm->_game.id == GID_DIG && col == -1 ? 1 : col), chr);
}
int drawCharV7(byte *buffer, Common::Rect &clipRect, int x, int y, int pitch, int16 col, TextStyleFlags flags, byte chr) override {
return NutRenderer::drawCharV7(buffer, clipRect, x, y, pitch, col, flags, chr, _hardcodedFontColors, true);
}
int getCharWidth(uint16 chr) const override { return NutRenderer::getCharWidth(chr & 0xFF); }
int getCharHeight(uint16 chr) const override { return NutRenderer::getCharHeight(chr & 0xFF); }
int getFontHeight() const override { return NutRenderer::getFontHeight(); }
int setFont(int) override { return 0; }
bool newStyleWrapping() const override { return true; }
TextRenderer_v7 *_r;
const bool _hardcodedFontColors;
};
} // End of namespace Scumm
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,268 @@
/* 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/>.
*
*/
#if !defined(SCUMM_SMUSH_PLAYER_H) && defined(ENABLE_SCUMM_7_8)
#define SCUMM_SMUSH_PLAYER_H
#include "common/util.h"
namespace Audio {
class SoundHandle;
class QueuingAudioStream;
}
namespace Scumm {
#define SMUSH_MAX_TRACKS 4
#define SMUSH_FADE_SIZE 0xC00
#define IS_SFX 0x00
#define IS_BKG_MUSIC 0x40
#define IS_SPEECH 0x80
#define CHN_BKGMUS 1
#define CHN_SPEECH 2
#define CHN_OTHER 3
#define GRP_MASTER 0xFF01
#define GRP_SFX 0xFF02
#define GRP_BKGMUS 0xFF03
#define GRP_SPEECH 0xFF04
#define TRK_STATE_INACTIVE 0
#define TRK_STATE_PLAYING 1
#define TRK_STATE_FADING 2
#define TRK_STATE_ENDING 3
#define TRK_TYPE_MASK 0xC0
#define SAUD_OP_INIT 1
#define SAUD_OP_UPDATE_HEADER 2
#define SAUD_OP_SET_PARAM 3
#define SAUD_OP_INCR_PARAM 4
#define SAUD_OP_SET_OFFSET 6
#define SAUD_OP_SET_LENGTH 7
#define SAUD_OP_COMPARE_GT 8
#define SAUD_OP_COMPARE_LT 9
#define SAUD_OP_COMPARE_EQ 10
#define SAUD_OP_COMPARE_NE 11
#define SAUD_VALUEID_ALL_VOLS 0xFF
#define SAUD_VALUEID_TRK_VOL 0xFE
#define SAUD_VALUEID_TRK_PAN 0xFD
#define TRK_USERID_SPEECH 1
#define TRK_USERID_MUSIC 2
#define TRK_USERID_SFX 3
#define SMUSH_CODEC_RLE 1
#define SMUSH_CODEC_RLE_ALT 3
#define SMUSH_CODEC_UNCOMPRESSED 20
#define SMUSH_CODEC_DELTA_BLOCKS 37
#define SMUSH_CODEC_DELTA_GLYPHS 47
class ScummEngine_v7;
class SmushFont;
class SmushMixer;
class StringResource;
class SmushDeltaBlocksDecoder;
class SmushDeltaGlyphsDecoder;
class IMuseDigital;
class Insane;
class SmushPlayer {
friend class Insane;
private:
struct SmushAudioDispatch {
uint8 *headerPtr;
uint8 *dataBuf;
int32 dataSize;
int32 audioRemaining;
int32 currentOffset;
int sampleRate;
int state;
int fadeSampleRate;
int fadeVolume;
int32 fadeRemaining;
int volumeStep;
int32 elapsedAudio;
int32 audioLength;
};
struct SmushAudioTrack {
uint8 *blockPtr;
uint8 *fadeBuf;
uint8 *dataBuf;
uint8 *subChunkPtr;
int32 blockSize;
byte volume;
byte pan;
int16 state;
int16 flags;
int groupId;
int parsedChunks;
int32 dataSize;
int32 availableSize;
int32 audioRemaining;
int32 sdatSize;
};
ScummEngine_v7 *_vm;
IMuseDigital *_imuseDigital;
Insane *_insane;
int32 _nbframes;
int16 _deltaPal[0x300];
int32 _shiftedDeltaPal[0x300];
byte _pal[0x300];
SmushFont *_sf[5];
StringResource *_strings;
SmushDeltaBlocksDecoder *_deltaBlocksCodec;
SmushDeltaGlyphsDecoder *_deltaGlyphsCodec;
Common::SeekableReadStream *_base;
uint32 _baseSize;
byte *_frameBuffer;
byte *_specialBuffer;
Common::String _seekFile;
uint32 _startFrame;
uint32 _startTime;
int32 _seekPos;
uint32 _seekFrame;
bool _skipNext;
uint32 _frame;
Audio::SoundHandle *_IACTchannel;
Audio::QueuingAudioStream *_IACTstream;
Audio::SoundHandle *_compressedFileSoundHandle;
bool _compressedFileMode;
byte _IACToutput[4096];
int32 _IACTpos;
bool _storeFrame;
int _speed;
bool _endOfFile;
byte *_dst;
bool _updateNeeded;
bool _warpNeeded;
int _palDirtyMin, _palDirtyMax;
int _warpX, _warpY;
int _warpButtons;
bool _insanity;
bool _middleAudio;
bool _skipPalette;
int _iactTable[4];
SmushAudioTrack _smushTracks[SMUSH_MAX_TRACKS];
SmushAudioDispatch _smushDispatch[SMUSH_MAX_TRACKS];
int _smushMaxFrames[SMUSH_MAX_TRACKS];
int _smushTrackIds[SMUSH_MAX_TRACKS];
int _smushTrackIdxs[SMUSH_MAX_TRACKS];
uint8 _smushAudioTable[256];
int _smushNumTracks;
int _smushTrackFlags[SMUSH_MAX_TRACKS];
int _smushTrackVols[SMUSH_MAX_TRACKS];
int _smushAudioSampleRate;
int _gainReductionLowerBound;
int _gainReductionFactor;
int _gainReductionMultiplier;
bool _smushTracksNeedInit;
bool _smushAudioInitialized;
bool _smushAudioCallbackEnabled;
public:
SmushPlayer(ScummEngine_v7 *scumm, IMuseDigital *_imuseDigital, Insane *insane);
~SmushPlayer();
void pause();
void unpause();
void play(const char *filename, int32 speed, int32 offset = 0, int32 startFrame = 0);
void release();
void warpMouse(int x, int y, int buttons);
int setChanFlag(int id, int flagVal);
void setGroupVolume(int groupId, int volValue);
void processDispatches(int16 feedSize);
bool isAudioCallbackEnabled();
byte *getVideoPalette();
void setCurVideoFlags(int16 flags);
protected:
int _width, _height;
int _origPitch, _origNumStrips;
bool _paused;
uint32 _pauseStartTime;
uint32 _pauseTime;
int16 _curVideoFlags = 0;
void insanity(bool);
void setPalette(const byte *palette);
void setPaletteValue(int n, byte r, byte g, byte b);
void setDirtyColors(int min, int max);
void seekSan(const char *file, int32 pos, int32 contFrame);
const char *getString(int id);
private:
SmushFont *getFont(int font);
void parseNextFrame();
void init(int32 spped);
void setupAnim(const char *file);
void updateScreen();
void tryCmpFile(const char *filename);
bool readString(const char *file);
void decodeFrameObject(int codec, const uint8 *src, int left, int top, int width, int height);
void handleAnimHeader(int32 subSize, Common::SeekableReadStream &);
void handleFrame(int32 frameSize, Common::SeekableReadStream &);
void handleNewPalette(int32 subSize, Common::SeekableReadStream &);
void handleZlibFrameObject(int32 subSize, Common::SeekableReadStream &b);
void handleFrameObject(int32 subSize, Common::SeekableReadStream &);
void handleSAUDChunk(uint8 *srcBuf, uint32 size, int groupId, int vol, int pan, int16 flags, int trkId, int index, int maxFrames);
void handleStore(int32 subSize, Common::SeekableReadStream &);
void handleFetch(int32 subSize, Common::SeekableReadStream &);
void handleIACT(int32 subSize, Common::SeekableReadStream &);
void handleTextResource(uint32 subType, int32 subSize, Common::SeekableReadStream &);
void handleDeltaPalette(int32 subSize, Common::SeekableReadStream &);
void readPalette(byte *, Common::SeekableReadStream &);
void initAudio(int samplerate, int32 maxChunkSize);
void terminateAudio();
int isChanActive(int flagId);
int addAudioTrack(int32 trackBlockSize, int32 maxBlockSize);
void resetAudioTracks();
void setGainReductionParams(int16 gainReductionLowerBound, int16 gainReductionMultiplier);
void fillAudioTrackInfo(uint8 *srcBuf, uint16 *flagsAccumulator, uint32 size, int groupId, int vol, int pan, int16 flags, int trkId, int index, int maxFrames);
bool processAudioCodes(int idx, int32 &tmpFeedSize, int &mixVolume);
void feedAudio(uint8 *srcBuf, int groupId, int volume, int pan, int16 flags);
void sendAudioToDiMUSE(uint8 *mixBuf, int32 mixStartingPoint, int32 mixFeedSize, int32 mixInFrameCount, int volume, int pan);
void timerCallback();
};
} // End of namespace Scumm
#endif