Some clean-up of DecompressorComp3 class

svn-id: r39323
This commit is contained in:
Greg Frieger 2009-03-11 00:23:18 +00:00
parent e2d33d81ab
commit 738160d17a
2 changed files with 99 additions and 114 deletions

View File

@ -35,18 +35,20 @@ namespace Sci {
int Decompressor::unpack(Common::ReadStream *src, Common::WriteStream *dest, uint32 nPacked, int Decompressor::unpack(Common::ReadStream *src, Common::WriteStream *dest, uint32 nPacked,
uint32 nUnpacked) { uint32 nUnpacked) {
init(src, dest, nPacked, nUnpacked); return copyBytes(src, dest, nPacked);
byte buff[1024];
uint32 chunk;
while (_szPacked && !_src->ioFailed() && !_dest->ioFailed()) {
chunk = MIN<uint32>(1024, _szPacked);
_src->read(buff, chunk);
_dest->write(buff, chunk);
_szPacked -= chunk;
}
return _src->ioFailed() || _dest->ioFailed() ? 1 : 0;
} }
int Decompressor::copyBytes(Common::ReadStream *src, Common::WriteStream *dest, uint32 nSize) {
byte buff[1024];
uint32 chunk;
while (nSize && !src->ioFailed() && !dest->ioFailed()) {
chunk = MIN<uint32>(1024, nSize);
src->read(buff, chunk);
dest->write(buff, chunk);
nSize -= chunk;
}
return src->ioFailed() || dest->ioFailed() ? 1 : 0;
}
void Decompressor::init(Common::ReadStream *src, Common::WriteStream *dest, uint32 nPacked, void Decompressor::init(Common::ReadStream *src, Common::WriteStream *dest, uint32 nPacked,
uint32 nUnpacked) { uint32 nUnpacked) {
_src = src; _src = src;
@ -147,6 +149,7 @@ int DecompressorComp3::unpack(Common::ReadStream *src, Common::WriteStream *dest
byte *buffer = NULL; byte *buffer = NULL;
byte *buffer2 = NULL; byte *buffer2 = NULL;
Common::MemoryWriteStream *pBuff = NULL; Common::MemoryWriteStream *pBuff = NULL;
Common::MemoryReadStream *pBuffIn = NULL;
switch (_compression) { switch (_compression) {
case kComp3: // Comp3 compression case kComp3: // Comp3 compression
@ -155,16 +158,21 @@ int DecompressorComp3::unpack(Common::ReadStream *src, Common::WriteStream *dest
case kComp3View: case kComp3View:
case kComp3Pic: case kComp3Pic:
buffer = new byte[nUnpacked]; buffer = new byte[nUnpacked];
buffer2 = new byte[nUnpacked];
pBuff = new Common::MemoryWriteStream(buffer, nUnpacked); pBuff = new Common::MemoryWriteStream(buffer, nUnpacked);
doUnpack(src, pBuff, nPacked, nUnpacked); doUnpack(src, pBuff, nPacked, nUnpacked);
if (_compression == kComp3View) if (_compression == kComp3View) {
buffer2 = new byte[nUnpacked];
view_reorder(buffer, buffer2); view_reorder(buffer, buffer2);
else dest->write(buffer2, nUnpacked);
pic_reorder(buffer, buffer2, nUnpacked); }
dest->write(buffer2, nUnpacked); else {
pBuffIn = new Common::MemoryReadStream(buffer, nUnpacked);
reorderPic(pBuffIn, dest, nUnpacked);
}
delete[] buffer2; delete[] buffer2;
delete[] buffer; delete[] buffer;
delete pBuff;
delete pBuffIn;
break; break;
} }
return 0; return 0;
@ -243,36 +251,32 @@ int DecompressorComp3::doUnpack(Common::ReadStream *src, Common::WriteStream *de
return _dwWrote ? 0 : 1; return _dwWrote ? 0 : 1;
} }
enum {
PIC_OP_SET_COLOR = 0xf0,
PIC_OP_DISABLE_VISUAL = 0xf1,
PIC_OP_SET_PRIORITY = 0xf2,
PIC_OP_DISABLE_PRIORITY = 0xf3,
PIC_OP_SHORT_PATTERNS = 0xf4,
PIC_OP_MEDIUM_LINES = 0xf5,
PIC_OP_LONG_LINES = 0xf6,
PIC_OP_SHORT_LINES = 0xf7,
PIC_OP_FILL = 0xf8,
PIC_OP_SET_PATTERN = 0xf9,
PIC_OP_ABSOLUTE_PATTERN = 0xfa,
PIC_OP_SET_CONTROL = 0xfb,
PIC_OP_DISABLE_CONTROL = 0xfc,
PIC_OP_MEDIUM_PATTERNS = 0xfd,
PIC_OP_OPX = 0xfe,
PIC_OP_TERMINATE = 0xff
};
enum {
PIC_OPX_SET_PALETTE_ENTRIES = 0,
PIC_OPX_EMBEDDED_VIEW = 1,
PIC_OPX_SET_PALETTE = 2,
PIC_OPX_PRIORITY_TABLE_EQDIST = 3,
PIC_OPX_PRIORITY_TABLE_EXPLICIT = 4
};
#define PAL_SIZE 1284 #define PAL_SIZE 1284
#define CEL_HEADER_SIZE 7
#define EXTRA_MAGIC_SIZE 15 #define EXTRA_MAGIC_SIZE 15
#define VIEW_HEADER_COLORS_8BIT 0x80
void DecompressorComp3::decodeRLE(Common::ReadStream *src, Common::WriteStream *dest, byte *pixeldata, uint16 size) {
int pos = 0;
byte nextbyte;
while (pos < size) {
nextbyte = src->readByte();
dest->writeByte(nextbyte);
pos ++;
switch (nextbyte & 0xC0) {
case 0x40 :
case 0x00 :
dest->write(pixeldata, nextbyte);
pixeldata += nextbyte;
pos += nextbyte;
break;
case 0xC0 :
break;
case 0x80 :
dest->writeByte(*pixeldata++);
break;
}
}
}
void DecompressorComp3::decode_rle(byte **rledata, byte **pixeldata, byte *outbuffer, int size) { void DecompressorComp3::decode_rle(byte **rledata, byte **pixeldata, byte *outbuffer, int size) {
int pos = 0; int pos = 0;
@ -339,80 +343,53 @@ int DecompressorComp3::rle_size(byte *rledata, int dsize) {
return size; return size;
} }
void DecompressorComp3::pic_reorder(byte *inbuffer, byte *outbuffer, int dsize) { void DecompressorComp3::reorderPic(Common::ReadStream *src, Common::WriteStream *dest, int dsize) {
int view_size; int view_size, view_start, cdata_size;
int view_start; byte viewdata[7];
int cdata_size; byte *cdata = NULL;
int i; byte *extra = NULL;
byte *seeker = inbuffer;
byte *writer;
char viewdata[CEL_HEADER_SIZE];
byte *cdata, *cdata_start;
writer = outbuffer; // Setting palette
dest->writeByte(PIC_OP_OPX);
dest->writeByte(PIC_OPX_SET_PALETTE);
*writer++ = PIC_OP_OPX; for (int i = 0; i < 256; i++) // Palette translation map
*writer++ = PIC_OPX_SET_PALETTE; dest->writeByte(i);
dest->writeUint32LE(0); //Palette timestamp
for (i = 0; i < 256; i++) /* Palette translation map */ view_size = src->readUint16LE();
*writer++ = i; view_start = src->readUint16LE();
cdata_size = src->readUint16LE();
WRITE_LE_UINT16(writer, 0); /* Palette stamp */ src->read(viewdata, sizeof(viewdata));
writer += 2; // Copy palette colors
WRITE_LE_UINT16(writer, 0); copyBytes(src, dest, 1024);
writer += 2; // copy drawing opcodes
if (view_start != PAL_SIZE + 2)
view_size = READ_LE_UINT16(seeker); copyBytes(src, dest, view_start - PAL_SIZE - 2);
seeker += 2; // storing extra opcodes to be pasted after the cel
view_start = READ_LE_UINT16(seeker); if (dsize != view_start + EXTRA_MAGIC_SIZE + view_size) {
seeker += 2; extra = new byte[dsize - view_size - view_start - EXTRA_MAGIC_SIZE];
cdata_size = READ_LE_UINT16(seeker); src->read(extra, dsize - view_size - view_start - EXTRA_MAGIC_SIZE);
seeker += 2;
memcpy(viewdata, seeker, sizeof(viewdata));
seeker += sizeof(viewdata);
memcpy(writer, seeker, 4*256); /* Palette */
seeker += 4*256;
writer += 4*256;
if (view_start != PAL_SIZE + 2) { /* +2 for the opcode */
memcpy(writer, seeker, view_start-PAL_SIZE-2);
seeker += view_start - PAL_SIZE - 2;
writer += view_start - PAL_SIZE - 2;
} }
// Writing picture cel opcode and header
if (dsize != view_start+EXTRA_MAGIC_SIZE+view_size) { dest->writeByte(PIC_OP_OPX);
memcpy(outbuffer+view_size+view_start+EXTRA_MAGIC_SIZE, seeker, dest->writeByte(PIC_OPX_EMBEDDED_VIEW);
dsize-view_size-view_start-EXTRA_MAGIC_SIZE); dest->writeByte(0);
seeker += dsize-view_size-view_start-EXTRA_MAGIC_SIZE; dest->writeUint16LE(0);
} dest->writeUint16LE(view_size + 8);
dest->write(viewdata, sizeof(viewdata));
cdata_start = cdata = (byte *)malloc(cdata_size); dest->writeByte(0);
memcpy(cdata, seeker, cdata_size); // Unpacking RLE cel data
seeker += cdata_size; cdata = new byte[cdata_size];
src->read(cdata, cdata_size);
writer = outbuffer + view_start; decodeRLE(src, dest, cdata, view_size);
*writer++ = PIC_OP_OPX; // writing stored extra opcodes
*writer++ = PIC_OPX_EMBEDDED_VIEW; if (extra)
*writer++ = 0; dest->write(extra, dsize - view_size - view_start - EXTRA_MAGIC_SIZE);
*writer++ = 0; delete[] extra;
*writer++ = 0; delete[] cdata;
WRITE_LE_UINT16(writer, view_size + 8);
writer += 2;
memcpy(writer, viewdata, sizeof(viewdata));
writer += sizeof(viewdata);
*writer++ = 0;
decode_rle(&seeker, &cdata, writer, view_size);
free(cdata_start);
} }
#define VIEW_HEADER_COLORS_8BIT 0x80
void DecompressorComp3::build_cel_headers(byte **seeker, byte **writer, int celindex, int *cc_lengths, int max) { void DecompressorComp3::build_cel_headers(byte **seeker, byte **writer, int celindex, int *cc_lengths, int max) {
for (int c = 0; c < max; c++) { for (int c = 0; c < max; c++) {
memcpy(*writer, *seeker, 6); memcpy(*writer, *seeker, 6);

View File

@ -79,6 +79,7 @@ protected:
*/ */
virtual void putByte(byte b); virtual void putByte(byte b);
virtual void fetchBits(); virtual void fetchBits();
int copyBytes(Common::ReadStream *src, Common::WriteStream *dest, uint32 nSize);
uint32 _dwBits; uint32 _dwBits;
byte _nBits; byte _nBits;
@ -120,20 +121,27 @@ public:
uint32 nUnpacked); uint32 nUnpacked);
protected: protected:
enum {
PIC_OPX_EMBEDDED_VIEW = 1,
PIC_OPX_SET_PALETTE = 2,
PIC_OP_OPX = 0xfe,
};
// actual unpacking procedure // actual unpacking procedure
int doUnpack(Common::ReadStream *src, Common::WriteStream *dest, uint32 nPacked, int doUnpack(Common::ReadStream *src, Common::WriteStream *dest, uint32 nPacked,
uint32 nUnpacked); uint32 nUnpacked);
// functions to post-process view and pic resources // functions to post-process view and pic resources
void decodeRLE(Common::ReadStream *src, Common::WriteStream *dest, byte *pixeldata, uint16 size);
void reorderPic(Common::ReadStream *src, Common::WriteStream *dest, int dsize);
//
void decode_rle(byte **rledata, byte **pixeldata, byte *outbuffer, int size); void decode_rle(byte **rledata, byte **pixeldata, byte *outbuffer, int size);
int rle_size(byte *rledata, int dsize); int rle_size(byte *rledata, int dsize);
void pic_reorder(byte *inbuffer, byte *outbuffer, int dsize);
void build_cel_headers(byte **seeker, byte **writer, int celindex, int *cc_lengths, int max); void build_cel_headers(byte **seeker, byte **writer, int celindex, int *cc_lengths, int max);
void view_reorder(byte *inbuffer, byte *outbuffer); void view_reorder(byte *inbuffer, byte *outbuffer);
// decompressor data
struct tokenlist { struct tokenlist {
byte data; byte data;
uint16 next; uint16 next;
} _tokens[0x1004]; } _tokens[0x1004];
byte _stak[0x1014]; byte _stak[0x1014];
byte _lastchar; byte _lastchar;
uint16 _stakptr; uint16 _stakptr;