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

📄 scompression.cpp.svn-base

📁 絲路server源碼 Silk Road server source
💻 SVN-BASE
📖 第 1 页 / 共 2 页
字号:

    // Do the decompression
    explode(ReadInputData, WriteOutputData, work_buf, &Info);
    
    // Fix: If PKLIB is unable to decompress the data, they are uncompressed
    if(Info.nOutPos == 0)
    {
        Info.nOutPos = min(*pdwOutLength, dwInLength);
        memcpy(pbOutBuffer, pbInBuffer, Info.nOutPos);
    }

    *pdwOutLength = Info.nOutPos;
    FREEMEM(work_buf);
    return 0;
}

/*****************************************************************************/
/*                                                                           */
/*  The "10" (de)compression is the Bzip2 (de)compression                    */
/*                                                                           */
/*****************************************************************************/

int Compress_bzip2(char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength, int * pCmpType, int nCmpLevel)
{
    bz_stream strm;
    int blockSize100k;
    int workFactor = 30;

    // Keep compiler happy
    nCmpLevel = nCmpLevel;

    // Initialize the BZLIB compression
    strm.bzalloc = NULL;
    strm.bzfree  = NULL;

    // Adjust the block size
    blockSize100k = *pCmpType;
    if(blockSize100k < 1 || blockSize100k > 9)
        blockSize100k = 9;

    // Blizzard uses 9 as blockSize100k, (0 as workFactor)
    if(BZ2_bzCompressInit(&strm, blockSize100k, 0, workFactor) == 0)
    {
        strm.next_in   = pbInBuffer;
        strm.avail_in  = dwInLength;
        strm.next_out  = pbOutBuffer;
        strm.avail_out = *pdwOutLength;

        // Perform the compression
        while(BZ2_bzCompress(&strm, (strm.avail_in != 0) ? BZ_RUN : BZ_FINISH) != BZ_STREAM_END);

        // Put the stream into idle state
        BZ2_bzCompressEnd(&strm);
        *pdwOutLength = strm.total_out_lo32;
    }
    else
    {
        *pdwOutLength = 0;
    }

    return 0;
}

int Decompress_bzip2(char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength)
{
    bz_stream strm;

    // Initialize the BZLIB decompression
    strm.bzalloc = NULL;
    strm.bzfree  = NULL;
    if(BZ2_bzDecompressInit(&strm, 0, 0) == 0)
    {
        strm.next_in   = pbInBuffer;
        strm.avail_in  = dwInLength;
        strm.next_out  = pbOutBuffer;
        strm.avail_out = *pdwOutLength;

        // Perform the decompression
        while(BZ2_bzDecompress(&strm) != BZ_STREAM_END);

        // Put the stream into idle state
        BZ2_bzDecompressEnd(&strm);
        *pdwOutLength = strm.total_out_lo32;
    }
    else
    {
        // Set zero output length
        *pdwOutLength = 0;
    }

    return 0;
}

/*****************************************************************************/
/*                                                                           */
/*   SCompCompress                                                           */
/*                                                                           */
/*****************************************************************************/

// This table contains compress functions which can be applied to
// uncompressed blocks. Each bit set means the corresponding
// compression method/function must be applied.
//
//   WAVes compression            Data compression
//   ------------------           -------------------
//   1st block   - 0x08           0x08 (D, HF, W2, SC, D2)
//   Rest blocks - 0x81           0x02 (W3)

static TCompressTable cmp_table[] =
{
    {MPQ_COMPRESSION_WAVE_MONO,   Compress_wave_mono},   // IMA ADPCM mono compression
    {MPQ_COMPRESSION_WAVE_STEREO, Compress_wave_stereo}, // IMA ADPCM stereo compression
    {MPQ_COMPRESSION_HUFFMANN,    Compress_huff},        // Huffmann compression
    {MPQ_COMPRESSION_ZLIB,        Compress_zlib},        // Compression with the "zlib" library
    {MPQ_COMPRESSION_PKWARE,      Compress_pklib},       // Compression with Pkware DCL
    {MPQ_COMPRESSION_BZIP2,       Compress_bzip2}        // Compression Bzip2 library
};

int WINAPI SCompCompress(char * pbCompressed, int * pdwOutLength, char * pbUncompressed, int dwInLength,
                  int uCompressions, int nCmpType, int nCmpLevel)
{
    char * pbTempBuff = NULL;           // Temporary storage for decompressed data
    char * pbOutput = pbCompressed;     // Current output buffer
    char * pbInput;                     // Current input buffer
    int uCompressions2;
    int dwCompressCount = 0;
    int dwDoneCount = 0;
    int dwOutSize = 0;
    int dwInSize  = dwInLength;
    int dwEntries = (sizeof(cmp_table) / sizeof(TCompressTable));
    int nResult = 1;
    int i;       

    // Check for valid parameters
    if(!pdwOutLength || *pdwOutLength < dwInLength || !pbCompressed || !pbUncompressed)
    {
        SetLastError(ERROR_INVALID_PARAMETER);
        return 0;
    }

    // Count the compressions
    for(i = 0, uCompressions2 = uCompressions; i < dwEntries; i++)
    {
        if(uCompressions & cmp_table[i].dwMask)
            dwCompressCount++;

        uCompressions2 &= ~cmp_table[i].dwMask;
    }

    // If a compression remains, do nothing
    if(uCompressions2 != 0)
    {
        SetLastError(ERROR_INVALID_PARAMETER);
        return 0;
    }

    // If more that one compression, allocate intermediate buffer
    if(dwCompressCount >= 2)
        pbTempBuff = ALLOCMEM(char, *pdwOutLength + 1);

    // Perform the compressions
    pbInput = pbUncompressed;
    dwInSize = dwInLength;
    for(i = 0, uCompressions2 = uCompressions; i < dwEntries; i++)
    {
        if(uCompressions2 & cmp_table[i].dwMask)
        {
            // Set the right output buffer 
            dwCompressCount--;
            pbOutput = (dwCompressCount & 1) ? pbTempBuff : pbCompressed;

            // Perform the partial compression
            dwOutSize = *pdwOutLength - 1;

            cmp_table[i].Compress(pbOutput + 1, &dwOutSize, pbInput, dwInSize, &nCmpType, nCmpLevel);
            if(dwOutSize == 0)
            {
                SetLastError(ERROR_GEN_FAILURE);
                *pdwOutLength = 0;
                nResult = 0;
                break;
            }

            // If the compression failed, copy the block instead
            if(dwOutSize >= dwInSize - 1)
            {
                if(dwDoneCount > 0)
                    pbOutput++;

                memcpy(pbOutput, pbInput, dwInSize);
                pbInput = pbOutput;
                uCompressions &= ~cmp_table[i].dwMask;
                dwOutSize = dwInSize;
            }
            else
            {
                pbInput = pbOutput + 1;
                dwInSize = dwOutSize;
                dwDoneCount++;
            }
        }
    }

    // Copy the compressed data to the correct output buffer
    if(nResult != 0)
    {
        if(uCompressions && (dwInSize + 1) < *pdwOutLength)
        {
            if(pbOutput != pbCompressed  && pbOutput != pbCompressed + 1)
                memcpy(pbCompressed, pbOutput, dwInSize);
            *pbCompressed = (char)uCompressions;
            *pdwOutLength = dwInSize + 1;
        }
        else
        {
            memmove(pbCompressed, pbUncompressed, dwInSize);
            *pdwOutLength = dwInSize;
        }
    }

    // Cleanup and return
    if(pbTempBuff != NULL)
        FREEMEM(pbTempBuff);
    return nResult;
}

/*****************************************************************************/
/*                                                                           */
/*   SCompDecompress                                                         */
/*                                                                           */
/*****************************************************************************/

// This table contains decompress functions which can be applied to
// uncompressed blocks. The compression mask is stored in the first byte
// of compressed block
static TDecompressTable dcmp_table[] =
{
    {MPQ_COMPRESSION_BZIP2,       Decompress_bzip2},       // Decompression with Bzip2 library
    {MPQ_COMPRESSION_PKWARE,      Decompress_pklib},       // Decompression with Pkware Data Compression Library
    {MPQ_COMPRESSION_ZLIB,        Decompress_zlib},        // Decompression with the "zlib" library
    {MPQ_COMPRESSION_HUFFMANN,    Decompress_huff},        // Huffmann decompression
    {MPQ_COMPRESSION_WAVE_STEREO, Decompress_wave_stereo}, // IMA ADPCM stereo decompression
    {MPQ_COMPRESSION_WAVE_MONO,   Decompress_wave_mono}    // IMA ADPCM mono decompression
};

int WINAPI SCompDecompress(char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength)
{
    char *   pbTempBuff = NULL;           // Temporary storage for decompressed data
    char *   pbWorkBuff = NULL;           // Where to store decompressed data
    int      dwOutLength = *pdwOutLength; // For storage number of output bytes
    unsigned fDecompressions1;            // Decompressions applied to the block
    unsigned fDecompressions2;            // Just another copy of decompressions applied to the block
    int      dwCount = 0;                 // Counter for every use
    int      dwEntries = (sizeof(dcmp_table) / sizeof(TDecompressTable));
    int      nResult = 1;
    int      i;       

    // If the input length is the same as output, do nothing.
    if(dwInLength == dwOutLength)
    {
        if(pbInBuffer == pbOutBuffer)
            return 1;

        memcpy(pbOutBuffer, pbInBuffer, dwInLength);
        *pdwOutLength = dwInLength;
        return 1;
    }
    
    // Get applied compression types and decrement data length
    fDecompressions1 = fDecompressions2 = (unsigned char)*pbInBuffer++;              
    dwInLength--;
    
    // Search decompression table type and get all types of compression
    for(i = 0; i < dwEntries; i++)
    {
        // We have to apply this decompression ?
        if(fDecompressions1 & dcmp_table[i].dwMask)
            dwCount++;

        // Clear this flag from temporary variable.
        fDecompressions2 &= ~dcmp_table[i].dwMask;
    }

    // Check if there is some method unhandled
    // (E.g. compressed by future versions)
    if(fDecompressions2 != 0)
    {
        SetLastError(ERROR_INVALID_PARAMETER);
        return 0;
    }

    // If there is more than only one compression, we have to allocate extra buffer
    if(dwCount >= 2)
        pbTempBuff = ALLOCMEM(char, dwOutLength);

    // Apply all decompressions
    for(i = 0, dwCount = 0; i < dwEntries; i++)
    {
        // If not used this kind of compression, skip the loop
        if(fDecompressions1 & dcmp_table[i].dwMask)
        {
            // If odd case, use target buffer for output, otherwise use allocated tempbuffer
            pbWorkBuff  = (dwCount++ & 1) ? pbTempBuff : pbOutBuffer;
            dwOutLength = *pdwOutLength;

            // Decompress buffer using corresponding function
            dcmp_table[i].Decompress(pbWorkBuff, &dwOutLength, pbInBuffer, dwInLength);
            if(dwOutLength == 0)
            {
                SetLastError(ERROR_GEN_FAILURE);
                nResult = 0;
                break;
            }

            // Move output length to src length for next compression
            dwInLength = dwOutLength;
            pbInBuffer = pbWorkBuff;
        }
    }

    // If output buffer is not the same like target buffer, we have to copy data
    if(nResult != 0)
    {
        if(pbWorkBuff != pbOutBuffer)
            memcpy(pbOutBuffer, pbInBuffer, dwOutLength);
        
    }

    // Delete temporary buffer, if necessary
    if(pbTempBuff != NULL)
        FREEMEM(pbTempBuff);
    
    *pdwOutLength = dwOutLength;
    return nResult;
}

/*****************************************************************************/
/*                                                                           */
/*   SCompSetDataCompression                                                 */
/*                                                                           */
/*****************************************************************************/

int WINAPI SCompSetDataCompression(int nDataCompression)
{
    int nValidMask = (MPQ_COMPRESSION_ZLIB | MPQ_COMPRESSION_PKWARE | MPQ_COMPRESSION_BZIP2);

    if((nDataCompression & nValidMask) != nDataCompression)
    {
        SetLastError(ERROR_INVALID_PARAMETER);
        return FALSE;
    }

    SetDataCompression(nDataCompression);
    return TRUE;
}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -