📄 explode.c.svn-base
字号:
if((pWork->in_bytes = pWork->read_buf((char *)pWork->in_buff, &pWork->in_pos, pWork->param)) == 0)
return 1;
pWork->in_pos = 0;
}
// Update bit buffer
pWork->bit_buff |= (pWork->in_buff[pWork->in_pos++] << 8);
pWork->bit_buff >>= (nBits - pWork->extra_bits);
pWork->extra_bits = (pWork->extra_bits - nBits) + 8;
return 0;
}
//-----------------------------------------------------------------------------
// Returns : 0x000 - 0x0FF : One byte from compressed file.
// 0x100 - 0x305 : Copy previous block (0x100 = 1 byte)
// 0x306 : Out of buffer (?)
static unsigned long DecodeLit(TDcmpStruct * pWork)
{
unsigned long nBits; // Number of bits to skip
unsigned long value; // Position in buffers
// Test the current bit in byte buffer. If is not set, simply return the next byte.
if(pWork->bit_buff & 1)
{
// Skip current bit in the buffer
if(WasteBits(pWork, 1))
return 0x306;
// The next bits are position in buffers
value = pWork->position2[(pWork->bit_buff & 0xFF)];
// Get number of bits to skip
if(WasteBits(pWork, pWork->LenBits[value]))
return 0x306;
if((nBits = pWork->ExLenBits[value]) != 0)
{
unsigned long val2 = pWork->bit_buff & ((1 << nBits) - 1);
if(WasteBits(pWork, nBits))
{
if((value + val2) != 0x10E)
return 0x306;
}
value = pWork->LenBase[value] + val2;
}
return value + 0x100; // Return number of bytes to repeat
}
// Waste one bit
if(WasteBits(pWork, 1))
return 0x306;
// If the binary compression type, read 8 bits and return them as one byte.
if(pWork->ctype == CMP_BINARY)
{
value = pWork->bit_buff & 0xFF;
if(WasteBits(pWork, 8))
return 0x306;
return value;
}
// When ASCII compression ...
if(pWork->bit_buff & 0xFF)
{
value = pWork->offs2C34[pWork->bit_buff & 0xFF];
if(value == 0xFF)
{
if(pWork->bit_buff & 0x3F)
{
if(WasteBits(pWork, 4))
return 0x306;
value = pWork->offs2D34[pWork->bit_buff & 0xFF];
}
else
{
if(WasteBits(pWork, 6))
return 0x306;
value = pWork->offs2E34[pWork->bit_buff & 0x7F];
}
}
}
else
{
if(WasteBits(pWork, 8))
return 0x306;
value = pWork->offs2EB4[pWork->bit_buff & 0xFF];
}
return WasteBits(pWork, pWork->ChBitsAsc[value]) ? 0x306 : value;
}
//-----------------------------------------------------------------------------
// Retrieves the number of bytes to move back
static unsigned long DecodeDist(TDcmpStruct * pWork, unsigned long dwLength)
{
unsigned long pos = pWork->position1[(pWork->bit_buff & 0xFF)];
unsigned long nSkip = pWork->DistBits[pos]; // Number of bits to skip
// Skip the appropriate number of bits
if(WasteBits(pWork, nSkip) == 1)
return 0;
if(dwLength == 2)
{
pos = (pos << 2) | (pWork->bit_buff & 0x03);
if(WasteBits(pWork, 2) == 1)
return 0;
}
else
{
pos = (pos << pWork->dsize_bits) | (pWork->bit_buff & pWork->dsize_mask);
// Skip the bits
if(WasteBits(pWork, pWork->dsize_bits) == 1)
return 0;
}
return pos+1;
}
static unsigned long Expand(TDcmpStruct * pWork)
{
unsigned int copyBytes; // Number of bytes to copy
unsigned long oneByte; // One byte from compressed file
unsigned long dwResult;
pWork->outputPos = 0x1000; // Initialize output buffer position
// If end of data or error, terminate decompress
while((dwResult = oneByte = DecodeLit(pWork)) < 0x305)
{
// If one byte is greater than 0x100, means "Repeat n - 0xFE bytes"
if(oneByte >= 0x100)
{
unsigned char * source; // ECX
unsigned char * target; // EDX
unsigned long copyLength = oneByte - 0xFE;
unsigned long moveBack;
// Get length of data to copy
if((moveBack = DecodeDist(pWork, copyLength)) == 0)
{
dwResult = 0x306;
break;
}
// Target and source pointer
target = &pWork->out_buff[pWork->outputPos];
source = target - moveBack;
pWork->outputPos += copyLength;
while(copyLength-- > 0)
*target++ = *source++;
}
else
pWork->out_buff[pWork->outputPos++] = (unsigned char)oneByte;
// If number of extracted bytes has reached 1/2 of output buffer,
// flush output buffer.
if(pWork->outputPos >= 0x2000)
{
// Copy decompressed data into user buffer
copyBytes = 0x1000;
pWork->write_buf((char *)&pWork->out_buff[0x1000], ©Bytes, pWork->param);
// If there are some data left, keep them alive
lmemcpy(pWork->out_buff, &pWork->out_buff[0x1000], pWork->outputPos - 0x1000);
pWork->outputPos -= 0x1000;
}
}
copyBytes = pWork->outputPos - 0x1000;
pWork->write_buf((char *)&pWork->out_buff[0x1000], ©Bytes, pWork->param);
return dwResult;
}
//-----------------------------------------------------------------------------
// Main exploding function.
unsigned int explode(
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)
{
TDcmpStruct * pWork = (TDcmpStruct *)work_buf;
// Set the whole work buffer to zeros
memset(pWork, 0, sizeof(TDcmpStruct));
// Initialize work struct and load compressed data
pWork->read_buf = read_buf;
pWork->write_buf = write_buf;
pWork->param = param;
pWork->in_pos = sizeof(pWork->in_buff);
pWork->in_bytes = pWork->read_buf((char *)pWork->in_buff, &pWork->in_pos, pWork->param);
if(pWork->in_bytes <= 4)
return CMP_BAD_DATA;
pWork->ctype = pWork->in_buff[0]; // Get the compression type
pWork->dsize_bits = pWork->in_buff[1]; // Get the dictionary size
pWork->bit_buff = pWork->in_buff[2]; // Initialize 16-bit bit buffer
pWork->extra_bits = 0; // Extra (over 8) bits
pWork->in_pos = 3; // Position in input buffer
// Test for the valid dictionary size
if(4 > pWork->dsize_bits || pWork->dsize_bits > 6)
return CMP_INVALID_DICTSIZE;
pWork->dsize_mask = 0xFFFF >> (0x10 - pWork->dsize_bits); // Shifted by 'sar' instruction
if(pWork->ctype != CMP_BINARY)
{
if(pWork->ctype != CMP_ASCII)
return CMP_INVALID_MODE;
lmemcpy(pWork->ChBitsAsc, ChBitsAsc, sizeof(pWork->ChBitsAsc));
GenAscTabs(pWork);
}
lmemcpy(pWork->LenBits, LenBits, sizeof(pWork->LenBits));
GenDecodeTabs(0x10, pWork->LenBits, LenCode, pWork->position2);
lmemcpy(pWork->ExLenBits, ExLenBits, sizeof(pWork->ExLenBits));
lmemcpy(pWork->LenBase, LenBase, sizeof(pWork->LenBase));
lmemcpy(pWork->DistBits, DistBits, sizeof(pWork->DistBits));
GenDecodeTabs(0x40, pWork->DistBits, DistCode, pWork->position1);
if(Expand(pWork) != 0x306)
return CMP_NO_ERROR;
return CMP_ABORT;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -