⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 explode.c.svn-base

📁 絲路server源碼 Silk Road server source
💻 SVN-BASE
📖 第 1 页 / 共 2 页
字号:
        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], &copyBytes, 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], &copyBytes, 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 + -