378 lines
8.1 KiB
C++
378 lines
8.1 KiB
C++
#include "stdafx.h"
|
|
|
|
|
|
|
|
// decompress CT Raw dump format
|
|
int CCTRawCodec::DecompressDump(PUBYTE buf, int len)
|
|
{
|
|
CapsPack cpk;
|
|
PCAPSPACK pk;
|
|
|
|
// free all buffers
|
|
Free();
|
|
|
|
// check dump header
|
|
int hlen = sizeof(CapsRaw);
|
|
if (len < hlen)
|
|
return imgeShort;
|
|
wh.cr = *(PCAPSRAW)buf;
|
|
Swap((PUDWORD)&wh.cr, sizeof(CapsRaw));
|
|
|
|
// check dump size
|
|
int tlen = wh.cr.time;
|
|
int rlen = wh.cr.raw;
|
|
if (len < hlen + tlen + rlen)
|
|
return imgeShort;
|
|
|
|
// check density information
|
|
PUBYTE denbuf = buf + hlen;
|
|
pk = GetPackHeader(&cpk, denbuf, tlen);
|
|
if (!pk)
|
|
return imgeDensityHeader;
|
|
|
|
// check track information
|
|
PUBYTE trkbuf = denbuf + tlen;
|
|
pk = GetPackHeader(&cpk, trkbuf, rlen);
|
|
if (!pk)
|
|
return imgeTrackHeader;
|
|
|
|
int err;
|
|
|
|
// decompress density information
|
|
wh.cdbuf = denbuf;
|
|
wh.cdlen = tlen;
|
|
if (!(err = DecompressDensity(1)))
|
|
err = DecompressDensity();
|
|
wh.cdbuf = NULL;
|
|
if (err)
|
|
return err;
|
|
|
|
// decompress track data
|
|
wh.ctbuf = trkbuf;
|
|
wh.ctlen = rlen;
|
|
if (!(err = DecompressTrack(1)))
|
|
err = DecompressTrack();
|
|
wh.ctbuf = NULL;
|
|
|
|
return err;
|
|
}
|
|
|
|
|
|
|
|
// decompress or verify compressed CT Raw density information
|
|
int CCTRawCodec::DecompressDensity(int verify)
|
|
{
|
|
CapsPack cpk;
|
|
|
|
// in decompress mode free result buffer first
|
|
if (!verify)
|
|
FreeUncompressedDensity();
|
|
|
|
// get density header
|
|
PCAPSPACK pk = GetPackHeader(&cpk, wh.cdbuf, wh.cdlen);
|
|
if (!pk)
|
|
return imgeDensityHeader;
|
|
|
|
// check crc on compressed data in verify mode
|
|
if (verify)
|
|
if (pk->ccrc != CalcCRC(wh.cdbuf + sizeof(CapsPack), pk->csize))
|
|
return imgeDensityStream;
|
|
|
|
// decompress density data
|
|
PUDWORD dst = DecompressDensity(wh.cdbuf, wh.cdlen);
|
|
int res = imgeOk;
|
|
|
|
if (verify) {
|
|
// in verify mode get density data in target format
|
|
Swap(dst, pk->usize);
|
|
|
|
// check crc on uncompressed data
|
|
if (pk->ucrc != CalcCRC((PUBYTE)dst, pk->usize))
|
|
res = imgeDensityData;
|
|
|
|
// free density data
|
|
delete[] dst;
|
|
} else {
|
|
// in decompress mode save density data
|
|
wh.timbuf = dst;
|
|
wh.timlen = pk->usize >> 2;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
// decompress CT Raw density information
|
|
PUDWORD CCTRawCodec::DecompressDensity(PUBYTE src, int slen, PUDWORD dst)
|
|
{
|
|
CapsPack cpk;
|
|
|
|
// get density header
|
|
PCAPSPACK pk = GetPackHeader(&cpk, src, slen);
|
|
if (!pk)
|
|
return NULL;
|
|
|
|
// use caller supplied buffer or allocate a new one
|
|
PUDWORD buf = dst;
|
|
if (!buf && pk->usize)
|
|
buf = new UDWORD[pk->usize >> 2];
|
|
|
|
// buffer pointer to end of destionation and source buffer
|
|
PUDWORD mem = buf + (pk->usize >> 2);
|
|
src += slen;
|
|
|
|
// decode the data, see compressor for encoding
|
|
while (mem > buf) {
|
|
int size, ofs;
|
|
UBYTE cb0 = *--src;
|
|
|
|
switch (cb0 & 0x03) {
|
|
// data block
|
|
case 0x0:
|
|
// 12 or 4 bit size
|
|
if (cb0 & 0x08)
|
|
size = ((cb0 << 4) & 0xf00) | (*--src);
|
|
else
|
|
size = (cb0 >> 4) + 1;
|
|
if (cb0 & 0x04) {
|
|
// 4 bytes per value
|
|
while (size--) {
|
|
UDWORD data;
|
|
data = (*--src);
|
|
data = (data << 8) | (*--src);
|
|
data = (data << 8) | (*--src);
|
|
data = (data << 8) | (*--src);
|
|
*--mem = data;
|
|
}
|
|
} else {
|
|
// 1 byte per value
|
|
while (size--)
|
|
*--mem = *--src;
|
|
}
|
|
continue;
|
|
|
|
// copy block, 8 bit offset, 6 bit size
|
|
case 0x1:
|
|
size = (cb0 >> 2) + 1;
|
|
ofs = (*--src) + 1;
|
|
break;
|
|
|
|
// copy block, 16 bit offset, 6 bit size
|
|
case 0x2:
|
|
size = (cb0 >> 2) + 1;
|
|
ofs = (*--src);
|
|
ofs = (ofs << 8) | (*--src);
|
|
break;
|
|
|
|
// copy block, 16 bit offset, 14 bit size
|
|
case 0x3:
|
|
size = ((cb0 << 6) & 0x3f00) | (*--src);
|
|
ofs = (*--src);
|
|
ofs = (ofs << 8) | (*--src);
|
|
break;
|
|
}
|
|
|
|
// copy decoded data
|
|
while (size--) {
|
|
mem--;
|
|
*mem = mem[ofs];
|
|
}
|
|
}
|
|
|
|
return buf;
|
|
}
|
|
|
|
|
|
|
|
// decompress or verify compressed CT Raw track information
|
|
int CCTRawCodec::DecompressTrack(int verify)
|
|
{
|
|
CapsPack cpk;
|
|
CapsWH cwh;
|
|
|
|
// in decompress mode free result buffer first
|
|
if (!verify)
|
|
FreeUncompressedTrack();
|
|
|
|
// get track header
|
|
PCAPSPACK pk = GetPackHeader(&cpk, wh.ctbuf, wh.ctlen);
|
|
if (!pk)
|
|
return imgeTrackHeader;
|
|
|
|
// check crc on compressed data in verify mode
|
|
if (verify)
|
|
if (pk->ccrc != CalcCRC(wh.ctbuf + sizeof(CapsPack), pk->csize))
|
|
return imgeTrackStream;
|
|
|
|
// decompress track data
|
|
PCAPSWH wb = DecompressTrack(&cwh, wh.ctbuf, wh.ctlen);
|
|
int res = imgeOk;
|
|
|
|
if (verify) {
|
|
// in verify mode check crc on uncompressed data
|
|
if (pk->ucrc != CalcCRC(wb->rawbuf, wb->rawlen))
|
|
res = imgeTrackData;
|
|
|
|
// free track data
|
|
FreeUncompressedTrack(wb);
|
|
} else {
|
|
// in decompress mode save track data
|
|
wh.rawbuf = wb->rawbuf;
|
|
wh.rawlen = wb->rawlen;
|
|
|
|
for (int trk = 0; trk < CAPS_MTRS; trk++) {
|
|
wh.trkbuf[trk] = wb->trkbuf[trk];
|
|
wh.trklen[trk] = wb->trklen[trk];
|
|
}
|
|
|
|
wh.trkcnt = wb->trkcnt;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
// decompress CT Raw track information
|
|
PCAPSWH CCTRawCodec::DecompressTrack(PCAPSWH w, PUBYTE src, int slen, PUBYTE dst)
|
|
{
|
|
CapsPack cpk;
|
|
|
|
// get track header
|
|
PCAPSPACK pk = GetPackHeader(&cpk, src, slen);
|
|
if (!pk)
|
|
return NULL;
|
|
|
|
// use caller supplied buffer or allocate a new one
|
|
w->rawbuf = NULL;
|
|
FreeUncompressedTrack(w);
|
|
w->rawlen = pk->usize;
|
|
w->rawbuf = dst;
|
|
if (!w->rawbuf && w->rawlen)
|
|
w->rawbuf = new UBYTE[w->rawlen];
|
|
|
|
// read track number
|
|
w->ctmem = src + sizeof(CapsPack);
|
|
w->trkcnt = CTR(w, 1);
|
|
|
|
// read <track number> track sizes and calculate track buffer positions
|
|
dst = w->rawbuf;
|
|
for (int trk = 0; trk < w->trkcnt; trk++) {
|
|
w->trklen[trk] = CTR(w, 2);
|
|
w->trkbuf[trk] = dst;
|
|
dst += w->trklen[trk];
|
|
}
|
|
|
|
// first track is stored
|
|
if (w->trkcnt) {
|
|
w->txsrc = w->trkbuf[0];
|
|
w->txlen = w->trklen[0];
|
|
memmove(w->txsrc, w->ctmem, w->txlen);
|
|
w->ctmem += w->txlen;
|
|
}
|
|
|
|
// other tracks are compressed as deltas against the stored track
|
|
for (w->txact = 1; w->txact < w->trkcnt; w->txact++)
|
|
DecompressTrackData(w);
|
|
|
|
return w;
|
|
}
|
|
|
|
// decompress CT Raw track data
|
|
void CCTRawCodec::DecompressTrackData(PCAPSWH w)
|
|
{
|
|
// source stream
|
|
PUBYTE src = w->ctmem;
|
|
|
|
// destination buffer
|
|
PUBYTE dst = w->trkbuf[w->txact];
|
|
|
|
// end of destination buffer
|
|
PUBYTE max = dst + w->trklen[w->txact];
|
|
|
|
// first, stored track
|
|
PUBYTE mem = w->txsrc;
|
|
|
|
// decode the data, see compressor for encoding
|
|
while (dst < max) {
|
|
UDWORD size = *src++;
|
|
|
|
if (size & 0x80) {
|
|
// copy block
|
|
// 3 bit shift
|
|
int shift = size >> 4 & 7;
|
|
|
|
// 12 bit size
|
|
size = ((size & 0xf) << 8) | (*src++);
|
|
|
|
// 16 bit offset
|
|
UDWORD ofs = *src++;
|
|
ofs = (ofs << 8) | (*src++);
|
|
PUBYTE buf = mem + ofs;
|
|
|
|
if (shift) {
|
|
// bitshift copy
|
|
ofs = *buf++;
|
|
while (size--) {
|
|
ofs = (ofs << 8) | (*buf++);
|
|
*dst++ = (UBYTE)(ofs >> shift);
|
|
}
|
|
} else {
|
|
// simple copy
|
|
while (size--)
|
|
*dst++ = *buf++;
|
|
}
|
|
} else {
|
|
// data block, 15 bit size
|
|
size = (size << 8) | (*src++);
|
|
while (size--)
|
|
*dst++ = *src++;
|
|
}
|
|
}
|
|
|
|
// update the source stream position
|
|
w->ctmem = src;
|
|
}
|
|
|
|
|
|
|
|
// get CT Raw pack format header in host format and test integrity
|
|
PCAPSPACK CCTRawCodec::GetPackHeader(PCAPSPACK cpk, PUBYTE src, int slen)
|
|
{
|
|
// check header size
|
|
if (!src || slen<sizeof(CapsPack))
|
|
return NULL;
|
|
|
|
// check signature
|
|
if (memcmp(src, CAPS_IDPACK, sizeof(cpk->sign)))
|
|
return NULL;
|
|
|
|
// copy header to result
|
|
memcpy(cpk, src, sizeof(CapsPack));
|
|
|
|
// change header crc to host format and check crc
|
|
Swap(&cpk->hcrc, sizeof(cpk->hcrc));
|
|
UDWORD hcrc = cpk->hcrc;
|
|
cpk->hcrc = 0;
|
|
if (hcrc != CalcCRC((PUBYTE)cpk, sizeof(CapsPack)))
|
|
return NULL;
|
|
|
|
// change header to host format
|
|
Swap(PUDWORD(PUBYTE(cpk) + sizeof(cpk->sign)), sizeof(CapsPack) - sizeof(cpk->sign));
|
|
|
|
// buffer length must match the size of header and compressed data size
|
|
if ((UDWORD)slen != sizeof(CapsPack) + cpk->csize)
|
|
return NULL;
|
|
|
|
return cpk;
|
|
}
|
|
|
|
// read up to a dword value from CT Raw stream, update stream position
|
|
UDWORD CCTRawCodec::CTR(PCAPSWH w, int size)
|
|
{
|
|
UDWORD res = 0;
|
|
|
|
for (; size; size--) {
|
|
res <<= 8;
|
|
res |= *w->ctmem++;
|
|
}
|
|
|
|
return res;
|
|
}
|