📄 implode.c
字号:
while(esp12 < nreps);
//---------------------------------------------------------------------------
esi = nreps;
pin27CC = pWork->work_buff + pin49D0[0] + nreps;
esp14 = pin27CC;
for(;;) // 0040268B
{
esi = pWork->offs09BC[esi];
if(esi == 0xFFFF)
esi = 0;
pin49D0 = pWork->offs49D0 + esp18;
do
{
pin49D0++;
esp18++;
pin27CC = pWork->work_buff + pin49D0[0];
if(pin27CC >= srcbuff2)
return nreps;
}
while(pin27CC + esi < esp14);
//---------------------------------------------------------------------------
esp20 = srcbuff[nreps - 2];
if(esp20 == pin27CC[nreps - 2])
{
if(pin27CC + esi != esp14)
{
esp14 = pin27CC;
esi = 0;
}
}
else
{
pin49D0 = pWork->offs49D0 + esp18;
do
{
pin49D0++;
esp18++;
pin27CC = pWork->work_buff + pin49D0[0];
if(pin27CC >= srcbuff2)
return nreps;
}
while(pin27CC[nreps - 2] != esp20 || pin27CC[0] != *srcbuff);
esp14 = pin27CC + 2;
esi = 2;
}
//---------------------------------------------------------------------------
for(; esp14[0] == srcbuff[esi]; esp14++)
{
if(++esi >= DICT_OFFSET)
break;
}
if(esi < nreps)
continue;
pWork->offs0000 = (unsigned int)(srcbuff - pin27CC - 1);
if(esi <= nreps)
continue;
nreps = esi;
if(esi == DICT_OFFSET)
return nreps;
do
{
if(srcbuff[esp12] != srcbuff[di])
{
di = pWork->offs09BC[di];
if(di != 0xFFFF)
continue;
}
pWork->offs09BC[++esp12] = ++di;
}
while(esp12 < esi);
}
}
static void WriteCmpData(TCmpStruct * pWork)
{
unsigned int nreps = 0; // ESP+10 : Number of repeats
unsigned char * uncmp_end; // ESP+14 : End of uncompressed data
unsigned int esp18 = 0; // ESP+18 :
unsigned int bytes_required; // ESP+1C : Number of bytes required to read
unsigned int esp20 = 0; // ESP+20 :
unsigned char * uncmp_begin = pWork->work_buff + UNCMP_OFFSET; // EDI
unsigned long nreps1;
unsigned long save_offs0000 = 0;
// Store the compression type and dictionary size
pWork->out_buff[0] = (char)pWork->ctype;
pWork->out_buff[1] = (char)pWork->dsize_bits;
pWork->out_bytes = 2;
// Reset output buffer to zero
lmemset(&pWork->out_buff[2], 0, sizeof(pWork->out_buff) - 2);
pWork->out_bits = 0;
do
{
int total_loaded = 0;
for(bytes_required = 0x1000; bytes_required != 0; )
{
int loaded = pWork->read_buf((char *)pWork->work_buff + UNCMP_OFFSET + total_loaded,
&bytes_required, pWork->param);
if(loaded == 0)
{
if(total_loaded == 0 && esp20 == 0)
goto __Exit;
esp18 = 1;
break;
}
else
{
total_loaded += loaded;
bytes_required -= loaded;
}
}
uncmp_end = pWork->work_buff + pWork->dsize_bytes + total_loaded;
if(esp18 != 0)
uncmp_end += DICT_OFFSET;
//
// Warning: Passing "uncmp_end + 1" to the SortBuffer function may cause
// the output to be unpredictable in Storm.dll's compression. Because Storm.dll
// does not pass the zeroed buffer to the "implode" function, the byte after
// uncmp_end contains random data. This causes difference within dictionary
// created in SortBuffer function and may also cause different compressed output.
// We always zero the data before compression, so this thing never occurs.
// Funny is that it is actually not a bug, because if we decompress the data back,
// we'll get the identical data with the original input.
//
switch(esp20)
{
case 0:
SortBuffer(pWork, uncmp_begin, uncmp_end + 1);
esp20++;
if(pWork->dsize_bytes != 0x1000)
esp20++;
break;
case 1:
SortBuffer(pWork, uncmp_begin - pWork->dsize_bytes + DICT_OFFSET, uncmp_end + 1);
esp20++;
break;
default:
SortBuffer(pWork, uncmp_begin - pWork->dsize_bytes, uncmp_end + 1);
break;
}
while(uncmp_end > uncmp_begin)
{
nreps1 = FindRep(pWork, uncmp_begin);
while(nreps1 != 0)
{
if(nreps1 == 2 && pWork->offs0000 >= 0x100)
break;
if(esp18 != 0 && uncmp_begin + nreps1 > uncmp_end)
goto _004022DB;
if(nreps1 >= 8 || uncmp_begin + 1 >= uncmp_end)
goto _004022FF;
save_offs0000 = pWork->offs0000; // ebp
nreps = nreps1;
nreps1 = FindRep(pWork, uncmp_begin + 1);
if(nreps >= nreps1)
goto _004022F9;
if(nreps + 1 >= nreps1 && save_offs0000 <= 0x80)
goto _004022F9;
OutputBits(pWork, pWork->nChBits[*uncmp_begin], pWork->nChCodes[*uncmp_begin]);
uncmp_begin++;
}
_0040222F:
OutputBits(pWork, pWork->nChBits[*uncmp_begin], pWork->nChCodes[*uncmp_begin]);
uncmp_begin++;
_00402252:;
}
if(esp18 == 0)
{
uncmp_begin -= 0x1000;
lmemcpy(pWork->work_buff, pWork->work_buff + 0x1000, pWork->dsize_bytes + DICT_OFFSET);
}
}
while(esp18 == 0);
__Exit:
OutputBits(pWork, pWork->nChBits[0x305], pWork->nChCodes[0x305]);
if(pWork->out_bits != 0)
pWork->out_bytes++;
pWork->write_buf(pWork->out_buff, &pWork->out_bytes, pWork->param);
return;
_004022DB:
nreps1 = (unsigned long)(uncmp_end - uncmp_begin);
if(nreps1 < 2)
goto _0040222F;
if(nreps1 != 2 || pWork->offs0000 < 0x100)
goto _004022FF;
goto _0040222F;
_004022F9:
nreps1 = nreps;
pWork->offs0000 = save_offs0000;
_004022FF:
OutputBits(pWork, pWork->nChBits[nreps1 + 0xFE], pWork->nChCodes[nreps1 + 0xFE]);
if(nreps1 == 2)
{
OutputBits(pWork, pWork->dist_bits[pWork->offs0000 >> 2],
pWork->dist_codes[pWork->offs0000 >> 2]);
OutputBits(pWork, 2, pWork->offs0000 & 3);
}
else
{
OutputBits(pWork, pWork->dist_bits[pWork->offs0000 >> pWork->dsize_bits],
pWork->dist_codes[pWork->offs0000 >> pWork->dsize_bits]);
OutputBits(pWork, pWork->dsize_bits, pWork->dsize_mask & pWork->offs0000);
}
uncmp_begin += nreps1;
goto _00402252;
}
//-----------------------------------------------------------------------------
// Main imploding function
unsigned int PKEXPORT implode(
unsigned int (*read_buf)(char *buf, unsigned int *size, void *param),
void (*write_buf)(char *buf, unsigned int *size, void *param),
char *work_buf,
void *param,
unsigned int *type,
unsigned int *dsize)
{
TCmpStruct * pWork = (TCmpStruct *)work_buf;
unsigned int nChCode;
unsigned int nCount;
unsigned int i;
// Initialize the work buffer. This is not in the Pklib,
// but it seems to be a bug. Storm always pre-fills the data with zeros,
// and always compresses one block only. So the bug will not appear.
// But when a larger data block (size > 0x1000) is compressed,
// it may fail.
memset(pWork, 0, sizeof(TCmpStruct));
// Fill the work buffer information
pWork->read_buf = read_buf;
pWork->write_buf = write_buf;
pWork->dsize_bytes = *dsize;
pWork->ctype = *type;
pWork->param = param;
pWork->dsize_bits = 4;
pWork->dsize_mask = 0x0F;
// Test dictionary size
switch(*dsize)
{
case 0x1000 :
pWork->dsize_bits++;
pWork->dsize_mask |= 0x20;
// No break here !!!
case 0x0800 :
pWork->dsize_bits++;
pWork->dsize_mask |= 0x10;
// No break here !!!
case 0x0400 :
break;
default:
return CMP_INVALID_DICTSIZE;
}
// Test the compression type
switch(*type)
{
case CMP_BINARY: // We will compress data with binary compression type
for(nChCode = 0, nCount = 0; nCount < 0x100; nCount++)
{
pWork->nChBits[nCount] = 9;
pWork->nChCodes[nCount] = (unsigned short)nChCode;
nChCode = (nChCode & 0x0000FFFF) + 2;
}
break;
case CMP_ASCII: // We will compress data with ASCII compression type
for(nCount = 0; nCount < 0x100; nCount++)
{
pWork->nChBits[nCount] = (unsigned char )(ChBitsAsc[nCount] + 1);
pWork->nChCodes[nCount] = (unsigned short)(ChCodeAsc[nCount] * 2);
}
break;
default:
return CMP_INVALID_MODE;
}
for(i = 0; i < 0x10; i++)
{
int nCount2 = 0; // EBX
if((1 << ExLenBits[i]) == 0)
continue;
do
{
pWork->nChBits[nCount] = (unsigned char)(ExLenBits[i] + LenBits[i] + 1);
pWork->nChCodes[nCount] = (unsigned short)((nCount2 << (LenBits[i] + 1)) | ((LenCode[i] & 0xFFFF00FF) * 2) | 1);
nCount2++;
nCount++;
}
while((1 << ExLenBits[i]) > nCount2);
}
// Copy the distance codes and distance bits and perform the compression
lmemcpy(&pWork->dist_codes, DistCode, sizeof(DistCode));
lmemcpy(&pWork->dist_bits, DistBits, sizeof(DistBits));
WriteCmpData(pWork);
return CMP_NO_ERROR;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -