mirror of
https://github.com/libretro/scummvm.git
synced 2025-01-03 07:59:38 +00:00
de8f5477af
svn-id: r6048
483 lines
16 KiB
C++
483 lines
16 KiB
C++
/* ScummVM - Scumm Interpreter
|
|
* Copyright (C) 2001/2002 The ScummVM project
|
|
*
|
|
* 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 2
|
|
* 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, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
*
|
|
* $Header$
|
|
*
|
|
*/
|
|
|
|
#include <stdafx.h>
|
|
#include "codec37.h"
|
|
#include "chunk.h"
|
|
#include "blitter.h"
|
|
|
|
#include "common/engine.h" // for debug, warning, error
|
|
|
|
#include <assert.h>
|
|
#include <string.h>
|
|
|
|
bool Codec37Decoder::initSize(const Point & p, const Rect & r) {
|
|
if(r.width() != getRect().width() && r.height() != getRect().height()) {
|
|
if(
|
|
(r.width() != 320 || r.height() != 200) &&
|
|
(r.width() != 384 || r.height() != 242) &&
|
|
(r.width() != 640 || r.height() != 480)
|
|
)
|
|
return false;
|
|
Decoder::initSize(p, r);
|
|
clean();
|
|
int32 frame_size = getRect().width() * getRect().height();
|
|
_deltaSize = frame_size * 2 + DELTA_ADD * 4;
|
|
_deltaBuf = new byte[_deltaSize];
|
|
if(_deltaBuf == 0) error("unable to allocate decoder buffer");
|
|
_deltaBufs[0] = _deltaBuf + DELTA_ADD;
|
|
_deltaBufs[1] = _deltaBuf + frame_size + DELTA_ADD * 3;
|
|
_offsetTable = new int16[255];
|
|
if(_offsetTable == 0) error("unable to allocate decoder offset table");
|
|
_tableLastPitch = -1;
|
|
_tableLastIndex = -1;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
Codec37Decoder::Codec37Decoder() {
|
|
_deltaSize = 0;
|
|
_deltaBuf = 0;
|
|
_deltaBufs[0] = 0;
|
|
_deltaBufs[1] = 0;
|
|
_curtable = 0;
|
|
_offsetTable = 0;
|
|
_tableLastPitch = -1;
|
|
_tableLastIndex = -1;
|
|
_prevSeqNb = 32768; // Some invalid number
|
|
}
|
|
|
|
void Codec37Decoder::clean() {
|
|
if(_offsetTable) {
|
|
delete []_offsetTable;
|
|
_offsetTable = 0;
|
|
_tableLastPitch = -1;
|
|
_tableLastIndex = -1;
|
|
}
|
|
if(_deltaBuf) {
|
|
delete []_deltaBuf;
|
|
_deltaSize = 0;
|
|
_deltaBuf = 0;
|
|
_deltaBufs[0] = 0;
|
|
_deltaBufs[1] = 0;
|
|
}
|
|
}
|
|
|
|
Codec37Decoder::~Codec37Decoder() {
|
|
clean();
|
|
}
|
|
|
|
void Codec37Decoder::maketable(int32 pitch, int32 index) {
|
|
static const int8 maketable_bytes[] = {
|
|
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;
|
|
#ifdef DEBUG_CODEC37
|
|
debug(7, "codec37::maketable(%d, %d) called", pitch, index);
|
|
#endif
|
|
_tableLastPitch = pitch;
|
|
_tableLastIndex = index;
|
|
index *= 255;
|
|
assert(index + 254 < (int32)(sizeof(maketable_bytes) / 2));
|
|
|
|
for (int32 i = 0; i < 255; i++) {
|
|
int32 j = (i + index) << 1; // * 2
|
|
_offsetTable[i] = maketable_bytes[j + 1] * pitch + maketable_bytes[j];
|
|
}
|
|
}
|
|
|
|
void Codec37Decoder::proc1(Blitter & dst, Chunk & src, int32 next_offs, int32 bw, int32 bh, int32 size) {
|
|
byte * decoded = new byte[size];
|
|
int32 w = 0;
|
|
while(!src.eof()) {
|
|
int32 code = src.getByte();
|
|
int32 length = (code >> 1) + 1;
|
|
if (code & 1) {
|
|
byte val = src.getByte();
|
|
while(length--)
|
|
decoded[w++] = val;
|
|
} else {
|
|
while(length--) {
|
|
decoded[w++] = src.getByte();
|
|
}
|
|
}
|
|
}
|
|
assert(w == size);
|
|
w = 0;
|
|
// Now we have our stream ready...
|
|
for(int32 i = 0; i < size; i++) {
|
|
if(decoded[i] == 0xFF) {
|
|
dst.putBlock(decoded + i + 1);
|
|
i += 16;
|
|
} else {
|
|
dst.blockCopy(_offsetTable[decoded[i]] + next_offs);
|
|
}
|
|
if(++w == bw) {
|
|
w = 0;
|
|
dst.advance(0, 3);
|
|
}
|
|
}
|
|
delete []decoded;
|
|
}
|
|
|
|
void Codec37Decoder::proc2(Blitter & dst, Chunk & src, int32 size) { // This is codec1 like...
|
|
#ifdef DEBUG_CODEC37_PROC2
|
|
int32 decoded_size = 0;
|
|
int32 coded_size = 0;
|
|
#endif
|
|
do {
|
|
int32 code = src.getByte();
|
|
int32 length = (code >> 1) + 1;
|
|
size -= length;
|
|
#ifdef DEBUG_CODEC37_PROC2
|
|
decoded_size += length;
|
|
coded_size += 1 + ((code & 1) ? 1 : length);
|
|
|
|
debug(7, "proc2() : code == %d : length == %d : decoded_size == %d : coded_size == %d : seek - header == %d : size == %d",
|
|
code, length, decoded_size, coded_size, src.tell() - 31, size + decoded_size);
|
|
#endif
|
|
if (code & 1)
|
|
dst.put(src.getChar(), length);
|
|
else
|
|
// while(length--) dst.put(src.get_char());
|
|
dst.blit(src, length);
|
|
} while (size);
|
|
}
|
|
|
|
void Codec37Decoder::proc3WithFDFE(Blitter & dst, Chunk & src, int32 next_offs, int32 bw, int32 bh) {
|
|
do {
|
|
int32 i = bw;
|
|
do {
|
|
int32 code = src.getByte();
|
|
if (code == 0xFD) {
|
|
#ifdef USE_COLOR_CODE_FOR_BLOCK
|
|
dst.putBlock(expand(1));
|
|
#else
|
|
dst.putBlock(expand(src.getByte()));
|
|
#endif
|
|
} else if (code == 0xFE) {
|
|
#ifdef USE_COLOR_CODE_FOR_BLOCK
|
|
dst.putBlock(expand(2));
|
|
#else
|
|
dst.putBlock(expand(src.getByte()), expand(src.getByte()), expand(src.getByte()), expand(src.getByte()));
|
|
#endif
|
|
} else if (code == 0xFF) {
|
|
#ifdef USE_COLOR_CODE_FOR_BLOCK
|
|
dst.putBlock(expand(3));
|
|
#else
|
|
dst.putBlock(src);
|
|
#endif
|
|
} else {
|
|
#ifdef USE_COLOR_CODE_FOR_BLOCK
|
|
dst.putBlock(expand(4));
|
|
#else
|
|
dst.blockCopy(_offsetTable[code] + next_offs); // copy from an offset !
|
|
#endif
|
|
}
|
|
} while (--i);
|
|
dst.advance(0, 3); // advance 3 lines
|
|
} while (--bh);
|
|
}
|
|
|
|
void Codec37Decoder::proc3WithoutFDFE(Blitter & dst, Chunk & src, int32 next_offs, int32 bw, int32 bh) {
|
|
do {
|
|
int32 i = bw;
|
|
do {
|
|
int32 code = src.getByte();
|
|
if (code == 0xFF) {
|
|
#ifdef USE_COLOR_CODE_FOR_BLOCK
|
|
dst.putBlock(expand(5));
|
|
#else
|
|
dst.putBlock(src);
|
|
#endif
|
|
} else {
|
|
#ifdef USE_COLOR_CODE_FOR_BLOCK
|
|
dst.putBlock(expand(6));
|
|
#else
|
|
dst.blockCopy(_offsetTable[code] + next_offs); // copy from an offset !
|
|
#endif
|
|
}
|
|
} while (--i);
|
|
dst.advance(0, 3); // advance 3 lines
|
|
} while (--bh);
|
|
}
|
|
|
|
void Codec37Decoder::proc4WithFDFE(Blitter & dst, Chunk & src, int32 next_offs, int32 bw, int32 bh) {
|
|
do {
|
|
int32 i = bw;
|
|
do {
|
|
int32 code = src.getByte();
|
|
if (code == 0xFD) {
|
|
#ifdef USE_COLOR_CODE_FOR_BLOCK
|
|
dst.putBlock(expand(7));
|
|
#else
|
|
dst.putBlock(expand(src.getByte()));
|
|
#endif
|
|
} else if (code == 0xFE) {
|
|
#ifdef USE_COLOR_CODE_FOR_BLOCK
|
|
dst.putBlock(expand(8));
|
|
#else
|
|
dst.putBlock(expand(src.getByte()), expand(src.getByte()), expand(src.getByte()), expand(src.getByte()));
|
|
#endif
|
|
} else if (code == 0xFF) {
|
|
#ifdef USE_COLOR_CODE_FOR_BLOCK
|
|
dst.putBlock(expand(9));
|
|
#else
|
|
dst.putBlock(src);
|
|
#endif
|
|
} else if (code == 0x00) {
|
|
int32 length = src.getByte() + 1;
|
|
for (int32 l = 0; l < length; l++) {
|
|
#ifdef USE_COLOR_CODE_FOR_BLOCK
|
|
dst.putBlock(expand(10));
|
|
#else
|
|
dst.blockCopy(next_offs);
|
|
#endif
|
|
i--;
|
|
if (i == 0) {
|
|
dst.advance(0, 3); // advance 3 lines
|
|
bh--;
|
|
i = bw;
|
|
}
|
|
}
|
|
if(bh == 0) return;
|
|
i++;
|
|
} else {
|
|
#ifdef USE_COLOR_CODE_FOR_BLOCK
|
|
dst.putBlock(expand(11));
|
|
#else
|
|
dst.blockCopy(_offsetTable[code] + next_offs); // copy from an offset !
|
|
#endif
|
|
}
|
|
} while (--i);
|
|
dst.advance(0, 3); // advance 3 lines
|
|
} while (--bh);
|
|
}
|
|
|
|
void Codec37Decoder::proc4WithoutFDFE(Blitter & dst, Chunk & src, int32 next_offs, int32 bw, int32 bh) {
|
|
do {
|
|
int32 i = bw;
|
|
do {
|
|
int32 code = src.getByte();
|
|
if (code == 0xFF) {
|
|
#ifdef USE_COLOR_CODE_FOR_BLOCK
|
|
dst.putBlock(expand(9));
|
|
#else
|
|
dst.putBlock(src);
|
|
#endif
|
|
} else if (code == 0x00) {
|
|
int32 length = src.getByte() + 1;
|
|
for (int32 l = 0; l < length; l++) {
|
|
#ifdef USE_COLOR_CODE_FOR_BLOCK
|
|
dst.putBlock(expand(10));
|
|
#else
|
|
dst.blockCopy(next_offs);
|
|
#endif
|
|
i--;
|
|
if (i == 0) {
|
|
dst.advance(0, 3); // advance 3 lines
|
|
bh--;
|
|
i = bw;
|
|
}
|
|
}
|
|
if(bh == 0) return;
|
|
i++;
|
|
} else {
|
|
#ifdef USE_COLOR_CODE_FOR_BLOCK
|
|
dst.putBlock(expand(11));
|
|
#else
|
|
dst.blockCopy(_offsetTable[code] + next_offs); // copy from an offset !
|
|
#endif
|
|
}
|
|
} while (--i);
|
|
dst.advance(0, 3); // advance 3 lines
|
|
} while (--bh);
|
|
}
|
|
|
|
bool Codec37Decoder::decode(Blitter & dst, Chunk & src) {
|
|
int32 width = getRect().width();
|
|
int32 height = getRect().height();
|
|
int32 bw = (width + 3) >> 2, bh = (height + 3) >> 2;
|
|
int32 pitch = bw << 2;
|
|
#ifdef DEBUG_CODEC37
|
|
debug(7, "codec37::decode() : width == %d : height == %d : pitch == %d : _prevSeqNb == %d",
|
|
width, height, pitch, _prevSeqNb);
|
|
#endif
|
|
int32 code = src.getByte(); // 0 -> 1 (1)
|
|
int32 index = src.getByte(); // 1 -> 2 (1)
|
|
uint16 seq_nb = src.getWord(); // 2 -> 4 (2)
|
|
uint32 decoded_size = src.getDword(); // 4 -> 8 (4)
|
|
#ifdef DEBUG_CODEC37
|
|
uint32 coded_size = src.getDword(); // 8 -> 12 (4)
|
|
#else
|
|
src.seek(4);
|
|
#endif
|
|
uint32 mask_flag = src.getDword(); // 12 -> 16 (4)
|
|
#ifdef DEBUG_CODEC37
|
|
debug(7, "codec37::decode() : code == %d : index == %d : seq_nb == %d : decoded_size == %d : coded_size == %d : mask_flag == %d",
|
|
code, index, seq_nb, decoded_size, coded_size, mask_flag);
|
|
#endif
|
|
maketable(pitch, index);
|
|
if(code == 3 || code == 4 || code == 1) {
|
|
assert(seq_nb && _prevSeqNb + 1 == seq_nb);
|
|
if (seq_nb & 1 || !(mask_flag & 1)) _curtable ^= 1;
|
|
}
|
|
Blitter blit((byte *)_deltaBufs[_curtable], Point(width, height), Rect(0, 0, width, height));
|
|
switch(code) {
|
|
case 0:
|
|
memset(_deltaBuf, 0, _deltaBufs[_curtable] - _deltaBuf);
|
|
memset(_deltaBufs[_curtable] + decoded_size, 0, _deltaBuf + _deltaSize - _deltaBufs[_curtable] - decoded_size);
|
|
blit.blit(src, decoded_size);
|
|
break;
|
|
case 1:
|
|
proc1(blit, src, _deltaBufs[_curtable ^ 1] - _deltaBufs[_curtable], bw, bh, decoded_size);
|
|
break;
|
|
case 2:
|
|
memset(_deltaBuf, 0, _deltaBufs[_curtable] - _deltaBuf);
|
|
memset(_deltaBufs[_curtable] + decoded_size, 0, _deltaBuf + _deltaSize - _deltaBufs[_curtable] - decoded_size);
|
|
proc2(blit, src, decoded_size);
|
|
break;
|
|
case 3:
|
|
if(mask_flag & 4)
|
|
proc3WithFDFE(blit, src, _deltaBufs[_curtable ^ 1] - _deltaBufs[_curtable], bw, bh);
|
|
else
|
|
proc3WithoutFDFE(blit, src, _deltaBufs[_curtable ^ 1] - _deltaBufs[_curtable], bw, bh);
|
|
break;
|
|
case 4:
|
|
if(mask_flag & 4)
|
|
proc4WithFDFE(blit, src, _deltaBufs[_curtable ^ 1] - _deltaBufs[_curtable], bw, bh);
|
|
else
|
|
proc4WithoutFDFE(blit, src, _deltaBufs[_curtable ^ 1] - _deltaBufs[_curtable], bw, bh);
|
|
break;
|
|
default:
|
|
#ifdef DEBUG_CODEC37
|
|
error("codec37::decode() received an invalid code : %d", code);
|
|
#endif
|
|
break;
|
|
}
|
|
if(mask_flag & 2) {
|
|
error("smush:codec37 missing transparent_blitting");
|
|
} else {
|
|
dst.blit((byte *)_deltaBufs[_curtable], width * height);
|
|
}
|
|
_prevSeqNb = seq_nb;
|
|
return true;
|
|
}
|
|
|