diff --git a/CMakeLists.txt b/CMakeLists.txt index b393f6d..42e11f3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,6 +29,33 @@ include(lib/system/cmake/system.cmake) find_package(ZLIB REQUIRED) find_package(BZip2 REQUIRED) +include(ExternalProject) + +set(STORMLIB_SOURCE_DIR ${CMAKE_SOURCE_DIR}/lib/stormlib) +set(STORMLIB_BINARY_DIR ${CMAKE_BINARY_DIR}/stormlib) +set(STORMLIB_LIBRARY ${STORMLIB_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${CMAKE_STATIC_LIBRARY_PREFIX}storm${CMAKE_STATIC_LIBRARY_SUFFIX}) + +ExternalProject_Add(stormlib_external + SOURCE_DIR ${STORMLIB_SOURCE_DIR} + BINARY_DIR ${STORMLIB_BINARY_DIR} + BUILD_BYPRODUCTS ${STORMLIB_LIBRARY} + INSTALL_COMMAND "" + CMAKE_ARGS + -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} + -DSTORM_BUILD_TESTS=OFF + -DSTORM_SKIP_INSTALL=ON + -DBUILD_SHARED_LIBS=OFF + -DSTORM_USE_BUNDLED_LIBRARIES=OFF + -DCMAKE_OSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET} +) + +add_library(stormlib STATIC IMPORTED) +set_target_properties(stormlib PROPERTIES + IMPORTED_LOCATION ${STORMLIB_LIBRARY} + INTERFACE_INCLUDE_DIRECTORIES ${STORMLIB_SOURCE_DIR}/src +) +add_dependencies(stormlib stormlib_external) + # Some templates abuse offsetof if(WHOA_SYSTEM_LINUX OR WHOA_SYSTEM_MAC) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-invalid-offsetof") diff --git a/src/util/CMakeLists.txt b/src/util/CMakeLists.txt index b64e585..5c7813f 100644 --- a/src/util/CMakeLists.txt +++ b/src/util/CMakeLists.txt @@ -1,7 +1,5 @@ file(GLOB PRIVATE_SOURCES "*.cpp" - "mpq/*.cpp" - "mpq/*.c" ) if(WHOA_SYSTEM_MAC) @@ -21,7 +19,6 @@ add_library(util STATIC target_include_directories(util PRIVATE ${CMAKE_SOURCE_DIR}/src - ${CMAKE_SOURCE_DIR}/src/util/mpq ${ZLIB_INCLUDE_DIRS} ${BZIP2_INCLUDE_DIRS} ) @@ -32,11 +29,16 @@ target_link_libraries(util lua-5.1 common storm + stormlib tempest ${ZLIB_LIBRARIES} ${BZIP2_LIBRARIES} ) +if(TARGET stormlib_external) + add_dependencies(util stormlib_external) +endif() + if(WHOA_SYSTEM_LINUX OR WHOA_SYSTEM_MAC) target_link_libraries(util PRIVATE diff --git a/src/util/Mpq.cpp b/src/util/Mpq.cpp index 45155f2..53505b0 100644 --- a/src/util/Mpq.cpp +++ b/src/util/Mpq.cpp @@ -1,21 +1,22 @@ #include "util/Mpq.hpp" -#include "util/mpq/Decompress.hpp" +#include #include #include #include #include +#include #include #include #include namespace { - constexpr uint32_t ID_MPQ = 0x1A51504D; - constexpr uint32_t ID_MPQ_USERDATA = 0x1B51504D; + constexpr uint32_t kMpqHeaderId = 0x1A51504D; + constexpr uint32_t kMpqUserDataId = 0x1B51504D; - constexpr uint32_t MPQ_FILE_IMPLODE = 0x00000100; - constexpr uint32_t MPQ_FILE_COMPRESSED = 0x00000200; - constexpr uint32_t MPQ_FILE_ENCRYPTED = 0x00010000; - constexpr uint32_t MPQ_FILE_SINGLE_UNIT = 0x01000000; + constexpr uint32_t kMpqFileImplode = 0x00000100; + constexpr uint32_t kMpqFileCompressed = 0x00000200; + constexpr uint32_t kMpqFileEncrypted = 0x00010000; + constexpr uint32_t kMpqFileSingleUnit = 0x01000000; #pragma pack(push, 1) struct MpqUserDataHeader { @@ -142,6 +143,38 @@ namespace { return 0; } + bool DecompressBlock(const uint8_t* in, size_t inSize, uint8_t* out, size_t outSize) { + if (inSize == outSize) { + std::memcpy(out, in, outSize); + return true; + } + + if (inSize == 0) { + return false; + } + + if (inSize > static_cast(std::numeric_limits::max()) || + outSize > static_cast(std::numeric_limits::max())) { + return false; + } + + uint8_t type = in[0]; + if (type == 0) { + if (inSize - 1 != outSize) { + return false; + } + std::memcpy(out, in + 1, outSize); + return true; + } + + int outLen = static_cast(outSize); + if (!SCompDecompress(out, &outLen, const_cast(in), static_cast(inSize))) { + return false; + } + + return static_cast(outLen) == outSize; + } + struct MpqArchive { std::ifstream stream; uint64_t baseOffset = 0; @@ -165,7 +198,7 @@ namespace { return false; } - if (userHeader.id == ID_MPQ_USERDATA) { + if (userHeader.id == kMpqUserDataId) { baseOffset = userHeader.headerOffset; } else { baseOffset = 0; @@ -177,7 +210,7 @@ namespace { return false; } - if (header.id != ID_MPQ || header.headerSize < 32) { + if (header.id != kMpqHeaderId || header.headerSize < 32) { return false; } @@ -263,11 +296,11 @@ namespace { return false; } - if (block->flags & MPQ_FILE_ENCRYPTED) { + if (block->flags & kMpqFileEncrypted) { return false; } - if (block->flags & MPQ_FILE_IMPLODE) { + if (block->flags & kMpqFileImplode) { return false; } @@ -276,7 +309,7 @@ namespace { std::vector buffer(fileSize); - if (block->flags & MPQ_FILE_SINGLE_UNIT) { + if (block->flags & kMpqFileSingleUnit) { std::vector raw(block->compressedSize); stream.seekg(static_cast(filePos), std::ios::beg); stream.read(reinterpret_cast(raw.data()), raw.size()); @@ -284,8 +317,8 @@ namespace { return false; } - if (block->flags & MPQ_FILE_COMPRESSED) { - if (!MpqCompression::DecompressBlock(raw.data(), raw.size(), buffer.data(), buffer.size())) { + if (block->flags & kMpqFileCompressed) { + if (!DecompressBlock(raw.data(), raw.size(), buffer.data(), buffer.size())) { return false; } } else { @@ -294,7 +327,7 @@ namespace { } std::memcpy(buffer.data(), raw.data(), buffer.size()); } - } else if ((block->flags & MPQ_FILE_COMPRESSED) == 0) { + } else if ((block->flags & kMpqFileCompressed) == 0) { stream.seekg(static_cast(filePos), std::ios::beg); stream.read(reinterpret_cast(buffer.data()), buffer.size()); if (!stream.good()) { @@ -330,7 +363,7 @@ namespace { } uint8_t* outPtr = buffer.data() + i * sectorSize; - if (!MpqCompression::DecompressBlock(raw.data(), raw.size(), outPtr, outSize)) { + if (!DecompressBlock(raw.data(), raw.size(), outPtr, outSize)) { if (raw.size() == outSize) { std::memcpy(outPtr, raw.data(), outSize); } else { diff --git a/src/util/mpq/Decompress.cpp b/src/util/mpq/Decompress.cpp deleted file mode 100644 index ab46b58..0000000 --- a/src/util/mpq/Decompress.cpp +++ /dev/null @@ -1,247 +0,0 @@ -#include "util/mpq/Decompress.hpp" - -#include -#include -#include -#include -#include -#include -#include - -#include "adpcm.h" -#include "huff.h" -#include "pklib.h" -#include "sparse.h" - -namespace MpqCompression { -namespace { - constexpr uint8_t MPQ_COMP_HUFFMANN = 0x01; - constexpr uint8_t MPQ_COMP_ZLIB = 0x02; - constexpr uint8_t MPQ_COMP_PKWARE = 0x08; - constexpr uint8_t MPQ_COMP_BZIP2 = 0x10; - constexpr uint8_t MPQ_COMP_SPARSE = 0x20; - constexpr uint8_t MPQ_COMP_ADPCM_MONO = 0x40; - constexpr uint8_t MPQ_COMP_ADPCM_STEREO = 0x80; - constexpr uint8_t MPQ_COMP_LZMA = 0x12; - - struct MpqDataInfo { - unsigned char* in; - unsigned char* inEnd; - unsigned char* out; - unsigned char* outEnd; - }; - - unsigned int ReadInputData(char* buf, unsigned int* size, void* param) { - MpqDataInfo* info = static_cast(param); - unsigned int maxAvail = static_cast(info->inEnd - info->in); - unsigned int toRead = *size; - if (toRead > maxAvail) { - toRead = maxAvail; - } - std::memcpy(buf, info->in, toRead); - info->in += toRead; - return toRead; - } - - void WriteOutputData(char* buf, unsigned int* size, void* param) { - MpqDataInfo* info = static_cast(param); - unsigned int maxWrite = static_cast(info->outEnd - info->out); - unsigned int toWrite = *size; - if (toWrite > maxWrite) { - toWrite = maxWrite; - } - std::memcpy(info->out, buf, toWrite); - info->out += toWrite; - } - - int DecompressZlib(void* out, int* outSize, void* in, int inSize) { - z_stream z = {}; - z.next_in = reinterpret_cast(in); - z.avail_in = static_cast(inSize); - z.total_in = inSize; - z.next_out = reinterpret_cast(out); - z.avail_out = static_cast(*outSize); - z.total_out = 0; - z.zalloc = nullptr; - z.zfree = nullptr; - - int result = inflateInit(&z); - if (result == Z_OK) { - result = inflate(&z, Z_FINISH); - *outSize = static_cast(z.total_out); - inflateEnd(&z); - } - - return result >= Z_OK; - } - - int DecompressBzip2(void* out, int* outSize, void* in, int inSize) { - bz_stream strm = {}; - strm.next_in = reinterpret_cast(in); - strm.avail_in = inSize; - strm.next_out = reinterpret_cast(out); - strm.avail_out = *outSize; - strm.bzalloc = nullptr; - strm.bzfree = nullptr; - strm.opaque = nullptr; - - int result = BZ2_bzDecompressInit(&strm, 0, 0); - if (result == BZ_OK) { - result = BZ2_bzDecompress(&strm); - *outSize = strm.total_out_lo32; - BZ2_bzDecompressEnd(&strm); - } - - return result >= BZ_OK; - } - - int DecompressPKLIB(void* out, int* outSize, void* in, int inSize) { - std::vector work(EXP_BUFFER_SIZE); - std::memset(work.data(), 0, work.size()); - - MpqDataInfo info = { - static_cast(in), - static_cast(in) + inSize, - static_cast(out), - static_cast(out) + *outSize - }; - - unsigned int result = explode(ReadInputData, WriteOutputData, work.data(), &info); - *outSize = static_cast(info.out - static_cast(out)); - return result == CMP_NO_ERROR ? 1 : 0; - } - - int DecompressHuff(void* out, int* outSize, void* in, int inSize) { - THuffmannTree tree(false); - TInputStream stream(in, static_cast(inSize)); - unsigned int result = tree.Decompress(out, static_cast(*outSize), &stream); - *outSize = static_cast(result); - return result != 0; - } - - int DecompressAdpcmMono(void* out, int* outSize, void* in, int inSize) { - int result = DecompressADPCM(out, *outSize, in, inSize, 1); - *outSize = result; - return result > 0; - } - - int DecompressAdpcmStereo(void* out, int* outSize, void* in, int inSize) { - int result = DecompressADPCM(out, *outSize, in, inSize, 2); - *outSize = result; - return result > 0; - } - - int DecompressSparseWrapper(void* out, int* outSize, void* in, int inSize) { - return DecompressSparse(out, outSize, in, inSize); - } - - struct DecompressEntry { - uint8_t mask; - int (*fn)(void* out, int* outSize, void* in, int inSize); - }; - - constexpr DecompressEntry kDecompressTable[] = { - {MPQ_COMP_BZIP2, DecompressBzip2}, - {MPQ_COMP_PKWARE, DecompressPKLIB}, - {MPQ_COMP_ZLIB, DecompressZlib}, - {MPQ_COMP_HUFFMANN, DecompressHuff}, - {MPQ_COMP_ADPCM_STEREO, DecompressAdpcmStereo}, - {MPQ_COMP_ADPCM_MONO, DecompressAdpcmMono}, - {MPQ_COMP_SPARSE, DecompressSparseWrapper} - }; - - constexpr uint8_t kKnownMask = - MPQ_COMP_HUFFMANN | - MPQ_COMP_ZLIB | - MPQ_COMP_PKWARE | - MPQ_COMP_BZIP2 | - MPQ_COMP_SPARSE | - MPQ_COMP_ADPCM_MONO | - MPQ_COMP_ADPCM_STEREO; -} - -bool DecompressBlock(const uint8_t* in, size_t inSize, uint8_t* out, size_t outSize) { - if (inSize == outSize) { - std::memcpy(out, in, outSize); - return true; - } - - if (inSize < 1) { - return false; - } - - if (inSize > static_cast(std::numeric_limits::max())) { - return false; - } - - if (outSize > static_cast(std::numeric_limits::max())) { - return false; - } - - uint8_t type = in[0]; - const uint8_t* payload = in + 1; - size_t payloadSize = inSize - 1; - - if (type == 0) { - if (payloadSize != outSize) { - return false; - } - std::memcpy(out, payload, outSize); - return true; - } - - if (type == MPQ_COMP_LZMA) { - return false; - } - - if ((type & ~kKnownMask) != 0) { - return false; - } - - int steps = 0; - for (const auto& entry : kDecompressTable) { - if (type & entry.mask) { - ++steps; - } - } - - if (steps == 0) { - return false; - } - - std::vector work; - uint8_t* workBuf = nullptr; - if (steps > 1) { - work.resize(outSize); - workBuf = work.data(); - } - - const uint8_t* currentInput = payload; - size_t currentSize = payloadSize; - int remaining = steps - 1; - - for (const auto& entry : kDecompressTable) { - if ((type & entry.mask) == 0) { - continue; - } - - uint8_t* output = (remaining & 1) ? workBuf : out; - int outputSize = static_cast(outSize); - int inputSize = static_cast(currentSize); - - if (!entry.fn(output, &outputSize, const_cast(currentInput), inputSize)) { - return false; - } - - if (outputSize <= 0) { - return false; - } - - currentInput = output; - currentSize = static_cast(outputSize); - --remaining; - } - - return currentSize == outSize; -} -} diff --git a/src/util/mpq/Decompress.hpp b/src/util/mpq/Decompress.hpp deleted file mode 100644 index c691b50..0000000 --- a/src/util/mpq/Decompress.hpp +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once - -#include -#include - -namespace MpqCompression { - bool DecompressBlock(const uint8_t* in, size_t inSize, uint8_t* out, size_t outSize); -} diff --git a/src/util/mpq/adpcm.cpp b/src/util/mpq/adpcm.cpp deleted file mode 100644 index 1725008..0000000 --- a/src/util/mpq/adpcm.cpp +++ /dev/null @@ -1,539 +0,0 @@ -/*****************************************************************************/ -/* adpcm.cpp Copyright (c) Ladislav Zezula 2003 */ -/*---------------------------------------------------------------------------*/ -/* This module contains implementation of adpcm decompression method used by */ -/* Storm.dll to decompress WAVE files. Thanks to Tom Amigo for releasing */ -/* his sources. */ -/*---------------------------------------------------------------------------*/ -/* Date Ver Who Comment */ -/* -------- ---- --- ------- */ -/* 11.03.03 1.00 Lad Splitted from Pkware.cpp */ -/* 20.05.03 2.00 Lad Added compression */ -/* 19.11.03 2.01 Dan Big endian handling */ -/* 10.01.13 3.00 Lad Refactored, beautified, documented :-) */ -/*****************************************************************************/ - -#include -#include - -#include "adpcm.h" - -//----------------------------------------------------------------------------- -// Tables necessary dor decompression - -static const int NextStepTable[] = -{ - -1, 0, -1, 4, -1, 2, -1, 6, - -1, 1, -1, 5, -1, 3, -1, 7, - -1, 1, -1, 5, -1, 3, -1, 7, - -1, 2, -1, 4, -1, 6, -1, 8 -}; - -static const int StepSizeTable[] = -{ - 7, 8, 9, 10, 11, 12, 13, 14, - 16, 17, 19, 21, 23, 25, 28, 31, - 34, 37, 41, 45, 50, 55, 60, 66, - 73, 80, 88, 97, 107, 118, 130, 143, - 157, 173, 190, 209, 230, 253, 279, 307, - 337, 371, 408, 449, 494, 544, 598, 658, - 724, 796, 876, 963, 1060, 1166, 1282, 1411, - 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024, - 3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484, - 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899, - 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, - 32767 -}; - -//----------------------------------------------------------------------------- -// Helper class for writing output ADPCM data - -class TADPCMStream -{ - public: - - TADPCMStream(void * pvBuffer, size_t cbBuffer) - { - pbBufferEnd = (unsigned char *)pvBuffer + cbBuffer; - pbBuffer = (unsigned char *)pvBuffer; - } - - bool ReadByteSample(unsigned char & ByteSample) - { - // Check if there is enough space in the buffer - if(pbBuffer >= pbBufferEnd) - return false; - - ByteSample = *pbBuffer++; - return true; - } - - bool WriteByteSample(unsigned char ByteSample) - { - // Check if there is enough space in the buffer - if(pbBuffer >= pbBufferEnd) - return false; - - *pbBuffer++ = ByteSample; - return true; - } - - bool ReadWordSample(short & OneSample) - { - // Check if we have enough space in the output buffer - if((size_t)(pbBufferEnd - pbBuffer) < sizeof(short)) - return false; - - // Write the sample - OneSample = pbBuffer[0] + (((short)pbBuffer[1]) << 0x08); - pbBuffer += sizeof(short); - return true; - } - - bool WriteWordSample(short OneSample) - { - // Check if we have enough space in the output buffer - if((size_t)(pbBufferEnd - pbBuffer) < sizeof(short)) - return false; - - // Write the sample - *pbBuffer++ = (unsigned char)(OneSample & 0xFF); - *pbBuffer++ = (unsigned char)(OneSample >> 0x08); - return true; - } - - int LengthProcessed(void * pvOutBuffer) - { - return (int)((unsigned char *)pbBuffer - (unsigned char *)pvOutBuffer); - } - - unsigned char * pbBufferEnd; - unsigned char * pbBuffer; -}; - -//---------------------------------------------------------------------------- -// Local functions - -static inline short GetNextStepIndex(int StepIndex, unsigned int EncodedSample) -{ - // Get the next step index - StepIndex = StepIndex + NextStepTable[EncodedSample & 0x1F]; - - // Don't make the step index overflow - if(StepIndex < 0) - StepIndex = 0; - else if(StepIndex > 88) - StepIndex = 88; - - return (short)StepIndex; -} - -static inline int UpdatePredictedSample(int PredictedSample, int EncodedSample, int Difference, int BitMask = 0x40) -{ - // Is the sign bit set? - if(EncodedSample & BitMask) - { - PredictedSample -= Difference; - if(PredictedSample <= -32768) - PredictedSample = -32768; - } - else - { - PredictedSample += Difference; - if(PredictedSample >= 32767) - PredictedSample = 32767; - } - - return PredictedSample; -} - -static inline int DecodeSample(int PredictedSample, int EncodedSample, int StepSize, int Difference) -{ - if(EncodedSample & 0x01) - Difference += (StepSize >> 0); - - if(EncodedSample & 0x02) - Difference += (StepSize >> 1); - - if(EncodedSample & 0x04) - Difference += (StepSize >> 2); - - if(EncodedSample & 0x08) - Difference += (StepSize >> 3); - - if(EncodedSample & 0x10) - Difference += (StepSize >> 4); - - if(EncodedSample & 0x20) - Difference += (StepSize >> 5); - - return UpdatePredictedSample(PredictedSample, EncodedSample, Difference); -} - -//---------------------------------------------------------------------------- -// Compression routine - -int CompressADPCM(void * pvOutBuffer, int cbOutBuffer, void * pvInBuffer, int cbInBuffer, int ChannelCount, int CompressionLevel) -{ - TADPCMStream os(pvOutBuffer, cbOutBuffer); // The output stream - TADPCMStream is(pvInBuffer, cbInBuffer); // The input stream - unsigned char BitShift = (unsigned char)(CompressionLevel - 1); - short PredictedSamples[MAX_ADPCM_CHANNEL_COUNT];// Predicted samples for each channel - short StepIndexes[MAX_ADPCM_CHANNEL_COUNT]; // Step indexes for each channel - short InputSample; // Input sample for the current channel - int TotalStepSize; - int ChannelIndex; - int AbsDifference; - int Difference; - int MaxBitMask; - int StepSize; - - // First byte in the output stream contains zero. The second one contains the compression level - os.WriteByteSample(0); - if(!os.WriteByteSample(BitShift)) - return 2; - - // Set the initial step index for each channel - PredictedSamples[0] = PredictedSamples[1] = 0; - StepIndexes[0] = StepIndexes[1] = INITIAL_ADPCM_STEP_INDEX; - - // Next, InitialSample value for each channel follows - for(int i = 0; i < ChannelCount; i++) - { - // Get the initial sample from the input stream - if(!is.ReadWordSample(InputSample)) - return os.LengthProcessed(pvOutBuffer); - - // Store the initial sample to our sample array - PredictedSamples[i] = InputSample; - - // Also store the loaded sample to the output stream - if(!os.WriteWordSample(InputSample)) - return os.LengthProcessed(pvOutBuffer); - } - - // Get the initial index - ChannelIndex = ChannelCount - 1; - - // Now keep reading the input data as long as there is something in the input buffer - while(is.ReadWordSample(InputSample)) - { - int EncodedSample = 0; - - // If we have two channels, we need to flip the channel index - ChannelIndex = (ChannelIndex + 1) % ChannelCount; - - // Get the difference from the previous sample. - // If the difference is negative, set the sign bit to the encoded sample - AbsDifference = InputSample - PredictedSamples[ChannelIndex]; - if(AbsDifference < 0) - { - AbsDifference = -AbsDifference; - EncodedSample |= 0x40; - } - - // If the difference is too low (higher that difference treshold), - // write a step index modifier marker - StepSize = StepSizeTable[StepIndexes[ChannelIndex]]; - if(AbsDifference < (StepSize >> CompressionLevel)) - { - if(StepIndexes[ChannelIndex] != 0) - StepIndexes[ChannelIndex]--; - - os.WriteByteSample(0x80); - } - else - { - // If the difference is too high, write marker that - // indicates increase in step size - while(AbsDifference > (StepSize << 1)) - { - if(StepIndexes[ChannelIndex] >= 0x58) - break; - - // Modify the step index - StepIndexes[ChannelIndex] += 8; - if(StepIndexes[ChannelIndex] > 0x58) - StepIndexes[ChannelIndex] = 0x58; - - // Write the "modify step index" marker - StepSize = StepSizeTable[StepIndexes[ChannelIndex]]; - os.WriteByteSample(0x81); - } - - // Get the limit bit value - MaxBitMask = (1 << (BitShift - 1)); - MaxBitMask = (MaxBitMask > 0x20) ? 0x20 : MaxBitMask; - Difference = StepSize >> BitShift; - TotalStepSize = 0; - - for(int BitVal = 0x01; BitVal <= MaxBitMask; BitVal <<= 1) - { - if((TotalStepSize + StepSize) <= AbsDifference) - { - TotalStepSize += StepSize; - EncodedSample |= BitVal; - } - StepSize >>= 1; - } - - PredictedSamples[ChannelIndex] = (short)UpdatePredictedSample(PredictedSamples[ChannelIndex], - EncodedSample, - Difference + TotalStepSize); - // Write the encoded sample to the output stream - if(!os.WriteByteSample((unsigned char)EncodedSample)) - break; - - // Calculates the step index to use for the next encode - StepIndexes[ChannelIndex] = GetNextStepIndex(StepIndexes[ChannelIndex], EncodedSample); - } - } - - return os.LengthProcessed(pvOutBuffer); -} - -//---------------------------------------------------------------------------- -// Decompression routine - -int DecompressADPCM(void * pvOutBuffer, int cbOutBuffer, void * pvInBuffer, int cbInBuffer, int ChannelCount) -{ - TADPCMStream os(pvOutBuffer, cbOutBuffer); // Output stream - TADPCMStream is(pvInBuffer, cbInBuffer); // Input stream - unsigned char EncodedSample; - unsigned char BitShift; - short PredictedSamples[MAX_ADPCM_CHANNEL_COUNT]; // Predicted sample for each channel - short StepIndexes[MAX_ADPCM_CHANNEL_COUNT]; // Predicted step index for each channel - int ChannelIndex; // Current channel index - - // Initialize the StepIndex for each channel - PredictedSamples[0] = PredictedSamples[1] = 0; - StepIndexes[0] = StepIndexes[1] = INITIAL_ADPCM_STEP_INDEX; - - // The first byte is always zero, the second one contains bit shift (compression level - 1) - is.ReadByteSample(BitShift); - is.ReadByteSample(BitShift); - - // Next, InitialSample value for each channel follows - for(int i = 0; i < ChannelCount; i++) - { - // Get the initial sample from the input stream - short InitialSample; - - // Attempt to read the initial sample - if(!is.ReadWordSample(InitialSample)) - return os.LengthProcessed(pvOutBuffer); - - // Store the initial sample to our sample array - PredictedSamples[i] = InitialSample; - - // Also store the loaded sample to the output stream - if(!os.WriteWordSample(InitialSample)) - return os.LengthProcessed(pvOutBuffer); - } - - // Get the initial index - ChannelIndex = ChannelCount - 1; - - // Keep reading as long as there is something in the input buffer - while(is.ReadByteSample(EncodedSample)) - { - // If we have two channels, we need to flip the channel index - ChannelIndex = (ChannelIndex + 1) % ChannelCount; - - if(EncodedSample == 0x80) - { - if(StepIndexes[ChannelIndex] != 0) - StepIndexes[ChannelIndex]--; - - if(!os.WriteWordSample(PredictedSamples[ChannelIndex])) - return os.LengthProcessed(pvOutBuffer); - } - else if(EncodedSample == 0x81) - { - // Modify the step index - StepIndexes[ChannelIndex] += 8; - if(StepIndexes[ChannelIndex] > 0x58) - StepIndexes[ChannelIndex] = 0x58; - - // Next pass, keep going on the same channel - ChannelIndex = (ChannelIndex + 1) % ChannelCount; - } - else - { - int StepIndex = StepIndexes[ChannelIndex]; - int StepSize = StepSizeTable[StepIndex]; - - // Encode one sample - PredictedSamples[ChannelIndex] = (short)DecodeSample(PredictedSamples[ChannelIndex], - EncodedSample, - StepSize, - StepSize >> BitShift); - - // Write the decoded sample to the output stream - if(!os.WriteWordSample(PredictedSamples[ChannelIndex])) - break; - - // Calculates the step index to use for the next encode - StepIndexes[ChannelIndex] = GetNextStepIndex(StepIndex, EncodedSample); - } - } - - // Return total bytes written since beginning of the output buffer - return os.LengthProcessed(pvOutBuffer); -} - -//----------------------------------------------------------------------------- -// ADPCM decompression present in Starcraft I BETA - -typedef struct _ADPCM_DATA -{ - const unsigned int * pValues; - int BitCount; - int field_8; - int field_C; - int field_10; - -} ADPCM_DATA, *PADPCM_DATA; - -static const unsigned int adpcm_values_2[] = {0x33, 0x66}; -static const unsigned int adpcm_values_3[] = {0x3A, 0x3A, 0x50, 0x70}; -static const unsigned int adpcm_values_4[] = {0x3A, 0x3A, 0x3A, 0x3A, 0x4D, 0x66, 0x80, 0x9A}; -static const unsigned int adpcm_values_6[] = -{ - 0x3A, 0x3A, 0x3A, 0x3A, 0x3A, 0x3A, 0x3A, 0x3A, 0x3A, 0x3A, 0x3A, 0x3A, 0x3A, 0x3A, 0x3A, 0x3A, - 0x46, 0x53, 0x60, 0x6D, 0x7A, 0x86, 0x93, 0xA0, 0xAD, 0xBA, 0xC6, 0xD3, 0xE0, 0xED, 0xFA, 0x106 -}; - -static const unsigned int * InitAdpcmData(PADPCM_DATA pData, unsigned char BitCount) -{ - switch(BitCount) - { - case 2: - pData->pValues = adpcm_values_2; - break; - - case 3: - pData->pValues = adpcm_values_3; - break; - - case 4: - pData->pValues = adpcm_values_4; - break; - - default: - pData->pValues = NULL; - break; - - case 6: - pData->pValues = adpcm_values_6; - break; - } - - pData->BitCount = BitCount; - pData->field_C = 0x20000; - pData->field_8 = 1 << BitCount; - pData->field_10 = (1 << BitCount) / 2; - return pData->pValues; -} - -int DecompressADPCM_SC1B(void * pvOutBuffer, int cbOutBuffer, void * pvInBuffer, int cbInBuffer, int ChannelCount) -{ - TADPCMStream os(pvOutBuffer, cbOutBuffer); // Output stream - TADPCMStream is(pvInBuffer, cbInBuffer); // Input stream - ADPCM_DATA AdpcmData; - int LowBitValues[MAX_ADPCM_CHANNEL_COUNT]; - int UpperBits[MAX_ADPCM_CHANNEL_COUNT]; - int BitMasks[MAX_ADPCM_CHANNEL_COUNT]; - int PredictedSamples[MAX_ADPCM_CHANNEL_COUNT]; - int ChannelIndex; - int ChannelIndexMax; - int OutputSample; - unsigned char BitCount; - unsigned char EncodedSample; - short InputValue16; - int reg_eax; - int Difference; - - // The first byte contains number of bits - if(!is.ReadByteSample(BitCount)) - return os.LengthProcessed(pvOutBuffer); - if(!InitAdpcmData(&AdpcmData, BitCount)) - return os.LengthProcessed(pvOutBuffer); - assert(AdpcmData.pValues != NULL); - - // Init bit values - for(int i = 0; i < ChannelCount; i++) - { - unsigned char OneByte; - - if(!is.ReadByteSample(OneByte)) - return os.LengthProcessed(pvOutBuffer); - LowBitValues[i] = OneByte & 0x01; - UpperBits[i] = OneByte >> 1; - } - - // - for(int i = 0; i < ChannelCount; i++) - { - if(!is.ReadWordSample(InputValue16)) - return os.LengthProcessed(pvOutBuffer); - BitMasks[i] = InputValue16 << AdpcmData.BitCount; - } - - // Next, InitialSample value for each channel follows - for(int i = 0; i < ChannelCount; i++) - { - if(!is.ReadWordSample(InputValue16)) - return os.LengthProcessed(pvOutBuffer); - - PredictedSamples[i] = InputValue16; - os.WriteWordSample(InputValue16); - } - - // Get the initial index - ChannelIndexMax = ChannelCount - 1; - ChannelIndex = 0; - - // Keep reading as long as there is something in the input buffer - while(is.ReadByteSample(EncodedSample)) - { - reg_eax = ((PredictedSamples[ChannelIndex] * 3) << 3) - PredictedSamples[ChannelIndex]; - PredictedSamples[ChannelIndex] = ((reg_eax * 10) + 0x80) >> 8; - - Difference = (((EncodedSample >> 1) + 1) * BitMasks[ChannelIndex] + AdpcmData.field_10) >> AdpcmData.BitCount; - - PredictedSamples[ChannelIndex] = UpdatePredictedSample(PredictedSamples[ChannelIndex], EncodedSample, Difference, 0x01); - - BitMasks[ChannelIndex] = (AdpcmData.pValues[EncodedSample >> 1] * BitMasks[ChannelIndex] + 0x80) >> 6; - if(BitMasks[ChannelIndex] < AdpcmData.field_8) - BitMasks[ChannelIndex] = AdpcmData.field_8; - - if(BitMasks[ChannelIndex] > AdpcmData.field_C) - BitMasks[ChannelIndex] = AdpcmData.field_C; - - reg_eax = (cbInBuffer - is.LengthProcessed(pvInBuffer)) >> ChannelIndexMax; - OutputSample = PredictedSamples[ChannelIndex]; - if(reg_eax < UpperBits[ChannelIndex]) - { - if(LowBitValues[ChannelIndex]) - { - OutputSample += (UpperBits[ChannelIndex] - reg_eax); - if(OutputSample > 32767) - OutputSample = 32767; - } - else - { - OutputSample += (reg_eax - UpperBits[ChannelIndex]); - if(OutputSample < -32768) - OutputSample = -32768; - } - } - - // Write the word sample and swap channel - os.WriteWordSample((short)(OutputSample)); - ChannelIndex = (ChannelIndex + 1) % ChannelCount; - } - - return os.LengthProcessed(pvOutBuffer); -} - diff --git a/src/util/mpq/adpcm.h b/src/util/mpq/adpcm.h deleted file mode 100644 index 169d465..0000000 --- a/src/util/mpq/adpcm.h +++ /dev/null @@ -1,27 +0,0 @@ -/*****************************************************************************/ -/* adpcm.h Copyright (c) Ladislav Zezula 2003 */ -/*---------------------------------------------------------------------------*/ -/* Header file for adpcm decompress functions */ -/*---------------------------------------------------------------------------*/ -/* Date Ver Who Comment */ -/* -------- ---- --- ------- */ -/* 31.03.03 1.00 Lad The first version of adpcm.h */ -/*****************************************************************************/ - -#ifndef __ADPCM_H__ -#define __ADPCM_H__ - -//----------------------------------------------------------------------------- -// Defines - -#define MAX_ADPCM_CHANNEL_COUNT 2 -#define INITIAL_ADPCM_STEP_INDEX 0x2C - -//----------------------------------------------------------------------------- -// Public functions - -int CompressADPCM (void * pvOutBuffer, int dwOutLength, void * pvInBuffer, int dwInLength, int ChannelCount, int nCmpType); -int DecompressADPCM (void * pvOutBuffer, int dwOutLength, void * pvInBuffer, int dwInLength, int ChannelCount); -int DecompressADPCM_SC1B(void * pvOutBuffer, int cbOutBuffer, void * pvInBuffer, int cbInBuffer, int ChannelCount); - -#endif // __ADPCM_H__ diff --git a/src/util/mpq/explode.c b/src/util/mpq/explode.c deleted file mode 100644 index 35210fb..0000000 --- a/src/util/mpq/explode.c +++ /dev/null @@ -1,521 +0,0 @@ -/*****************************************************************************/ -/* explode.c Copyright (c) Ladislav Zezula 2003 */ -/*---------------------------------------------------------------------------*/ -/* Implode function of PKWARE Data Compression library */ -/*---------------------------------------------------------------------------*/ -/* Date Ver Who Comment */ -/* -------- ---- --- ------- */ -/* 11.03.03 1.00 Lad Splitted from Pkware.cpp */ -/* 08.04.03 1.01 Lad Renamed to explode.c to be compatible with pklib */ -/* 02.05.03 1.01 Lad Stress test done */ -/* 22.04.10 1.01 Lad Documented */ -/*****************************************************************************/ - -#include -#include - -#include "pklib.h" - -#define PKDCL_OK 0 -#define PKDCL_STREAM_END 1 // All data from the input stream is read -#define PKDCL_NEED_DICT 2 // Need more data (dictionary) -#define PKDCL_CONTINUE 10 // Internal flag, not returned to user -#define PKDCL_GET_INPUT 11 // Internal flag, not returned to user - -char CopyrightPkware[] = "PKWARE Data Compression Library for Win32\r\n" - "Copyright 1989-1995 PKWARE Inc. All Rights Reserved\r\n" - "Patent No. 5,051,745\r\n" - "PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off.\r\n" - "Version 1.11\r\n"; - -//----------------------------------------------------------------------------- -// Tables - -const unsigned char DistBits[0x40] = -{ - 0x02, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, - 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, - 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, - 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08 -}; - -const unsigned char DistCode[0x40] = -{ - 0x03, 0x0D, 0x05, 0x19, 0x09, 0x11, 0x01, 0x3E, 0x1E, 0x2E, 0x0E, 0x36, 0x16, 0x26, 0x06, 0x3A, - 0x1A, 0x2A, 0x0A, 0x32, 0x12, 0x22, 0x42, 0x02, 0x7C, 0x3C, 0x5C, 0x1C, 0x6C, 0x2C, 0x4C, 0x0C, - 0x74, 0x34, 0x54, 0x14, 0x64, 0x24, 0x44, 0x04, 0x78, 0x38, 0x58, 0x18, 0x68, 0x28, 0x48, 0x08, - 0xF0, 0x70, 0xB0, 0x30, 0xD0, 0x50, 0x90, 0x10, 0xE0, 0x60, 0xA0, 0x20, 0xC0, 0x40, 0x80, 0x00 -}; - -const unsigned char ExLenBits[0x10] = -{ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 -}; - -const unsigned short LenBase[0x10] = -{ - 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, - 0x0008, 0x000A, 0x000E, 0x0016, 0x0026, 0x0046, 0x0086, 0x0106 -}; - -const unsigned char LenBits[0x10] = -{ - 0x03, 0x02, 0x03, 0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x07, 0x07 -}; - -const unsigned char LenCode[0x10] = -{ - 0x05, 0x03, 0x01, 0x06, 0x0A, 0x02, 0x0C, 0x14, 0x04, 0x18, 0x08, 0x30, 0x10, 0x20, 0x40, 0x00 -}; - -const unsigned char ChBitsAsc[0x100] = -{ - 0x0B, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x08, 0x07, 0x0C, 0x0C, 0x07, 0x0C, 0x0C, - 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, - 0x04, 0x0A, 0x08, 0x0C, 0x0A, 0x0C, 0x0A, 0x08, 0x07, 0x07, 0x08, 0x09, 0x07, 0x06, 0x07, 0x08, - 0x07, 0x06, 0x07, 0x07, 0x07, 0x07, 0x08, 0x07, 0x07, 0x08, 0x08, 0x0C, 0x0B, 0x07, 0x09, 0x0B, - 0x0C, 0x06, 0x07, 0x06, 0x06, 0x05, 0x07, 0x08, 0x08, 0x06, 0x0B, 0x09, 0x06, 0x07, 0x06, 0x06, - 0x07, 0x0B, 0x06, 0x06, 0x06, 0x07, 0x09, 0x08, 0x09, 0x09, 0x0B, 0x08, 0x0B, 0x09, 0x0C, 0x08, - 0x0C, 0x05, 0x06, 0x06, 0x06, 0x05, 0x06, 0x06, 0x06, 0x05, 0x0B, 0x07, 0x05, 0x06, 0x05, 0x05, - 0x06, 0x0A, 0x05, 0x05, 0x05, 0x05, 0x08, 0x07, 0x08, 0x08, 0x0A, 0x0B, 0x0B, 0x0C, 0x0C, 0x0C, - 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, - 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, - 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, - 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, - 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, - 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, - 0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D, 0x0C, 0x0D, - 0x0D, 0x0D, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D -}; - -const unsigned short ChCodeAsc[0x100] = -{ - 0x0490, 0x0FE0, 0x07E0, 0x0BE0, 0x03E0, 0x0DE0, 0x05E0, 0x09E0, - 0x01E0, 0x00B8, 0x0062, 0x0EE0, 0x06E0, 0x0022, 0x0AE0, 0x02E0, - 0x0CE0, 0x04E0, 0x08E0, 0x00E0, 0x0F60, 0x0760, 0x0B60, 0x0360, - 0x0D60, 0x0560, 0x1240, 0x0960, 0x0160, 0x0E60, 0x0660, 0x0A60, - 0x000F, 0x0250, 0x0038, 0x0260, 0x0050, 0x0C60, 0x0390, 0x00D8, - 0x0042, 0x0002, 0x0058, 0x01B0, 0x007C, 0x0029, 0x003C, 0x0098, - 0x005C, 0x0009, 0x001C, 0x006C, 0x002C, 0x004C, 0x0018, 0x000C, - 0x0074, 0x00E8, 0x0068, 0x0460, 0x0090, 0x0034, 0x00B0, 0x0710, - 0x0860, 0x0031, 0x0054, 0x0011, 0x0021, 0x0017, 0x0014, 0x00A8, - 0x0028, 0x0001, 0x0310, 0x0130, 0x003E, 0x0064, 0x001E, 0x002E, - 0x0024, 0x0510, 0x000E, 0x0036, 0x0016, 0x0044, 0x0030, 0x00C8, - 0x01D0, 0x00D0, 0x0110, 0x0048, 0x0610, 0x0150, 0x0060, 0x0088, - 0x0FA0, 0x0007, 0x0026, 0x0006, 0x003A, 0x001B, 0x001A, 0x002A, - 0x000A, 0x000B, 0x0210, 0x0004, 0x0013, 0x0032, 0x0003, 0x001D, - 0x0012, 0x0190, 0x000D, 0x0015, 0x0005, 0x0019, 0x0008, 0x0078, - 0x00F0, 0x0070, 0x0290, 0x0410, 0x0010, 0x07A0, 0x0BA0, 0x03A0, - 0x0240, 0x1C40, 0x0C40, 0x1440, 0x0440, 0x1840, 0x0840, 0x1040, - 0x0040, 0x1F80, 0x0F80, 0x1780, 0x0780, 0x1B80, 0x0B80, 0x1380, - 0x0380, 0x1D80, 0x0D80, 0x1580, 0x0580, 0x1980, 0x0980, 0x1180, - 0x0180, 0x1E80, 0x0E80, 0x1680, 0x0680, 0x1A80, 0x0A80, 0x1280, - 0x0280, 0x1C80, 0x0C80, 0x1480, 0x0480, 0x1880, 0x0880, 0x1080, - 0x0080, 0x1F00, 0x0F00, 0x1700, 0x0700, 0x1B00, 0x0B00, 0x1300, - 0x0DA0, 0x05A0, 0x09A0, 0x01A0, 0x0EA0, 0x06A0, 0x0AA0, 0x02A0, - 0x0CA0, 0x04A0, 0x08A0, 0x00A0, 0x0F20, 0x0720, 0x0B20, 0x0320, - 0x0D20, 0x0520, 0x0920, 0x0120, 0x0E20, 0x0620, 0x0A20, 0x0220, - 0x0C20, 0x0420, 0x0820, 0x0020, 0x0FC0, 0x07C0, 0x0BC0, 0x03C0, - 0x0DC0, 0x05C0, 0x09C0, 0x01C0, 0x0EC0, 0x06C0, 0x0AC0, 0x02C0, - 0x0CC0, 0x04C0, 0x08C0, 0x00C0, 0x0F40, 0x0740, 0x0B40, 0x0340, - 0x0300, 0x0D40, 0x1D00, 0x0D00, 0x1500, 0x0540, 0x0500, 0x1900, - 0x0900, 0x0940, 0x1100, 0x0100, 0x1E00, 0x0E00, 0x0140, 0x1600, - 0x0600, 0x1A00, 0x0E40, 0x0640, 0x0A40, 0x0A00, 0x1200, 0x0200, - 0x1C00, 0x0C00, 0x1400, 0x0400, 0x1800, 0x0800, 0x1000, 0x0000 -}; - -//----------------------------------------------------------------------------- -// Local functions - -static void GenDecodeTabs( - unsigned char * positions, // [out] Table of positions - const unsigned char * start_indexes, // [in] Table of start indexes - const unsigned char * length_bits, // [in] Table of lengths. Each length is stored as number of bits - size_t elements) // [in] Number of elements in start_indexes and length_bits -{ - unsigned int index; - unsigned int length; - size_t i; - - for(i = 0; i < elements; i++) - { - length = 1 << length_bits[i]; // Get the length in bytes - - for(index = start_indexes[i]; index < 0x100; index += length) - { - positions[index] = (unsigned char)i; - } - } -} - -static void GenAscTabs(TDcmpStruct * pWork) -{ - const unsigned short * pChCodeAsc = &ChCodeAsc[0xFF]; - unsigned int acc, add; - unsigned short count; - - for(count = 0x00FF; pChCodeAsc >= ChCodeAsc; pChCodeAsc--, count--) - { - unsigned char * pChBitsAsc = pWork->ChBitsAsc + count; - unsigned char bits_asc = *pChBitsAsc; - - if(bits_asc <= 8) - { - add = (1 << bits_asc); - acc = *pChCodeAsc; - - do - { - pWork->offs2C34[acc] = (unsigned char)count; - acc += add; - } - while(acc < 0x100); - } - else if((acc = (*pChCodeAsc & 0xFF)) != 0) - { - pWork->offs2C34[acc] = 0xFF; - - if(*pChCodeAsc & 0x3F) - { - bits_asc -= 4; - *pChBitsAsc = bits_asc; - - add = (1 << bits_asc); - acc = *pChCodeAsc >> 4; - do - { - pWork->offs2D34[acc] = (unsigned char)count; - acc += add; - } - while(acc < 0x100); - } - else - { - bits_asc -= 6; - *pChBitsAsc = bits_asc; - - add = (1 << bits_asc); - acc = *pChCodeAsc >> 6; - do - { - pWork->offs2E34[acc] = (unsigned char)count; - acc += add; - } - while(acc < 0x80); - } - } - else - { - bits_asc -= 8; - *pChBitsAsc = bits_asc; - - add = (1 << bits_asc); - acc = *pChCodeAsc >> 8; - do - { - pWork->offs2EB4[acc] = (unsigned char)count; - acc += add; - } - while(acc < 0x100); - } - } -} - -//----------------------------------------------------------------------------- -// Removes given number of bits in the bit buffer. New bits are reloaded from -// the input buffer, if needed. -// Returns: PKDCL_OK: Operation was successful -// PKDCL_STREAM_END: There are no more bits in the input buffer - -static int WasteBits(TDcmpStruct * pWork, unsigned int nBits) -{ - // If number of bits required is less than number of (bits in the buffer) ? - if(nBits <= pWork->extra_bits) - { - pWork->extra_bits -= nBits; - pWork->bit_buff >>= nBits; - return PKDCL_OK; - } - - // Load input buffer if necessary - pWork->bit_buff >>= pWork->extra_bits; - if(pWork->in_pos == pWork->in_bytes) - { - pWork->in_pos = sizeof(pWork->in_buff); - if((pWork->in_bytes = pWork->read_buf((char *)pWork->in_buff, &pWork->in_pos, pWork->param)) == 0) - return PKDCL_STREAM_END; - 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 PKDCL_OK; -} - -//----------------------------------------------------------------------------- -// Decodes next literal from the input (compressed) data. -// Returns : 0x000: One byte 0x00 -// 0x001: One byte 0x01 -// ... -// 0x0FF: One byte 0xFF -// 0x100: Repetition, length of 0x02 bytes -// 0x101: Repetition, length of 0x03 bytes -// ... -// 0x304: Repetition, length of 0x206 bytes -// 0x305: End of stream -// 0x306: Error - -static unsigned int DecodeLit(TDcmpStruct * pWork) -{ - unsigned int extra_length_bits; // Number of bits of extra literal length - unsigned int length_code; // Length code - unsigned int value; - - // Test the current bit in byte buffer. If is not set, simply return the next 8 bits. - if(pWork->bit_buff & 1) - { - // Remove one bit from the input data - if(WasteBits(pWork, 1)) - return 0x306; - - // The next 8 bits hold the index to the length code table - length_code = pWork->LengthCodes[pWork->bit_buff & 0xFF]; - - // Remove the apropriate number of bits - if(WasteBits(pWork, pWork->LenBits[length_code])) - return 0x306; - - // Are there some extra bits for the obtained length code ? - if((extra_length_bits = pWork->ExLenBits[length_code]) != 0) - { - unsigned int extra_length = pWork->bit_buff & ((1 << extra_length_bits) - 1); - - if(WasteBits(pWork, extra_length_bits)) - { - if((length_code + extra_length) != 0x10E) - return 0x306; - } - length_code = pWork->LenBase[length_code] + extra_length; - } - - // In order to distinguish uncompressed byte from repetition length, - // we have to add 0x100 to the length. - return length_code + 0x100; - } - - // Remove one bit from the input data - 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) - { - unsigned int uncompressed_byte = pWork->bit_buff & 0xFF; - - if(WasteBits(pWork, 8)) - return 0x306; - return uncompressed_byte; - } - - // 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; -} - -//----------------------------------------------------------------------------- -// Decodes the distance of the repetition, backwards relative to the -// current output buffer position - -static unsigned int DecodeDist(TDcmpStruct * pWork, unsigned int rep_length) -{ - unsigned int dist_pos_code; // Distance position code - unsigned int dist_pos_bits; // Number of bits of distance position - unsigned int distance; // Distance position - - // Next 2-8 bits in the input buffer is the distance position code - dist_pos_code = pWork->DistPosCodes[pWork->bit_buff & 0xFF]; - dist_pos_bits = pWork->DistBits[dist_pos_code]; - if(WasteBits(pWork, dist_pos_bits)) - return 0; - - if(rep_length == 2) - { - // If the repetition is only 2 bytes length, - // then take 2 bits from the stream in order to get the distance - distance = (dist_pos_code << 2) | (pWork->bit_buff & 0x03); - if(WasteBits(pWork, 2)) - return 0; - } - else - { - // If the repetition is more than 2 bytes length, - // then take "dsize_bits" bits in order to get the distance - distance = (dist_pos_code << pWork->dsize_bits) | (pWork->bit_buff & pWork->dsize_mask); - if(WasteBits(pWork, pWork->dsize_bits)) - return 0; - } - return distance + 1; -} - -static unsigned int Expand(TDcmpStruct * pWork) -{ - unsigned int next_literal; // Literal decoded from the compressed data - unsigned int result; // Value to be returned - unsigned int copyBytes; // Number of bytes to copy to the output buffer - - pWork->outputPos = 0x1000; // Initialize output buffer position - - // Decode the next literal from the input data. - // The returned literal can either be an uncompressed byte (next_literal < 0x100) - // or an encoded length of the repeating byte sequence that - // is to be copied to the current buffer position - while((result = next_literal = DecodeLit(pWork)) < 0x305) - { - // If the literal is greater than 0x100, it holds length - // of repeating byte sequence - // literal of 0x100 means repeating sequence of 0x2 bytes - // literal of 0x101 means repeating sequence of 0x3 bytes - // ... - // literal of 0x305 means repeating sequence of 0x207 bytes - if(next_literal >= 0x100) - { - unsigned char * source; - unsigned char * target; - unsigned int rep_length; // Length of the repetition, in bytes - unsigned int minus_dist; // Backward distance to the repetition, relative to the current buffer position - - // Get the length of the repeating sequence. - // Note that the repeating block may overlap the current output position, - // for example if there was a sequence of equal bytes - rep_length = next_literal - 0xFE; - - // Get backward distance to the repetition - if((minus_dist = DecodeDist(pWork, rep_length)) == 0) - { - result = 0x306; - break; - } - - // Target and source pointer - target = &pWork->out_buff[pWork->outputPos]; - source = target - minus_dist; - - // Update buffer output position - pWork->outputPos += rep_length; - - // Copy the repeating sequence - while(rep_length-- > 0) - *target++ = *source++; - } - else - { - pWork->out_buff[pWork->outputPos++] = (unsigned char)next_literal; - } - - // Flush the output buffer, if number of extracted bytes has reached the end - if(pWork->outputPos >= 0x2000) - { - // Copy decompressed data into user buffer - copyBytes = 0x1000; - pWork->write_buf((char *)&pWork->out_buff[0x1000], ©Bytes, pWork->param); - - // Now copy the decompressed data to the first half of the buffer. - // This is needed because the decompression might reuse them as repetitions. - // Note that if the output buffer overflowed previously, the extra decompressed bytes - // are stored in "out_buff_overflow", and they will now be - // within decompressed part of the output buffer. - memmove(pWork->out_buff, &pWork->out_buff[0x1000], pWork->outputPos - 0x1000); - pWork->outputPos -= 0x1000; - } - } - - // Flush any remaining decompressed bytes - copyBytes = pWork->outputPos - 0x1000; - pWork->write_buf((char *)&pWork->out_buff[0x1000], ©Bytes, pWork->param); - return result; -} - - -//----------------------------------------------------------------------------- -// Main exploding function. - -unsigned int PKEXPORT 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; - - // 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 (CMP_BINARY or CMP_ASCII) - 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; - - memcpy(pWork->ChBitsAsc, ChBitsAsc, sizeof(pWork->ChBitsAsc)); - GenAscTabs(pWork); - } - - memcpy(pWork->LenBits, LenBits, sizeof(pWork->LenBits)); - GenDecodeTabs(pWork->LengthCodes, LenCode, LenBits, sizeof(LenBits)); - memcpy(pWork->ExLenBits, ExLenBits, sizeof(pWork->ExLenBits)); - memcpy(pWork->LenBase, LenBase, sizeof(pWork->LenBase)); - memcpy(pWork->DistBits, DistBits, sizeof(pWork->DistBits)); - GenDecodeTabs(pWork->DistPosCodes, DistCode, DistBits, sizeof(DistBits)); - if(Expand(pWork) != 0x306) - return CMP_NO_ERROR; - - return CMP_ABORT; -} diff --git a/src/util/mpq/huff.cpp b/src/util/mpq/huff.cpp deleted file mode 100644 index 1b81017..0000000 --- a/src/util/mpq/huff.cpp +++ /dev/null @@ -1,895 +0,0 @@ -/*****************************************************************************/ -/* huffman.cpp Copyright (c) Ladislav Zezula 1998-2003 */ -/*---------------------------------------------------------------------------*/ -/* This module contains Huffmann (de)compression methods */ -/* */ -/* Authors : Ladislav Zezula (ladik@zezula.net) */ -/* ShadowFlare (BlakFlare@hotmail.com) */ -/* */ -/*---------------------------------------------------------------------------*/ -/* Date Ver Who Comment */ -/* -------- ---- --- ------- */ -/* xx.xx.xx 1.00 Lad The first version of dcmp.cpp */ -/* 03.05.03 1.00 Lad Added compression methods */ -/* 19.11.03 1.01 Dan Big endian handling */ -/* 08.12.03 2.01 Dan High-memory handling (> 0x80000000) */ -/* 09.01.13 3.00 Lad Refactored, beautified, documented :-) */ -/*****************************************************************************/ - -#include -#include - -#include "huff.h" - -//----------------------------------------------------------------------------- -// Table of byte-to-weight values - -// Table for (de)compression. Every compression type has 258 entries -static unsigned char ByteToWeight_00[] = -{ - 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, - 0x00, 0x00 -}; - -// Data for compression type 0x01 -static unsigned char ByteToWeight_01[] = -{ - 0x54, 0x16, 0x16, 0x0D, 0x0C, 0x08, 0x06, 0x05, 0x06, 0x05, 0x06, 0x03, 0x04, 0x04, 0x03, 0x05, - 0x0E, 0x0B, 0x14, 0x13, 0x13, 0x09, 0x0B, 0x06, 0x05, 0x04, 0x03, 0x02, 0x03, 0x02, 0x02, 0x02, - 0x0D, 0x07, 0x09, 0x06, 0x06, 0x04, 0x03, 0x02, 0x04, 0x03, 0x03, 0x03, 0x03, 0x03, 0x02, 0x02, - 0x09, 0x06, 0x04, 0x04, 0x04, 0x04, 0x03, 0x02, 0x03, 0x02, 0x02, 0x02, 0x02, 0x03, 0x02, 0x04, - 0x08, 0x03, 0x04, 0x07, 0x09, 0x05, 0x03, 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x03, 0x02, 0x02, - 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x01, 0x02, 0x02, - 0x06, 0x0A, 0x08, 0x08, 0x06, 0x07, 0x04, 0x03, 0x04, 0x04, 0x02, 0x02, 0x04, 0x02, 0x03, 0x03, - 0x04, 0x03, 0x07, 0x07, 0x09, 0x06, 0x04, 0x03, 0x03, 0x02, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, - 0x0A, 0x02, 0x02, 0x03, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x06, 0x03, 0x05, 0x02, 0x03, - 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x03, 0x01, 0x01, 0x01, - 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x04, 0x04, 0x04, 0x07, 0x09, 0x08, 0x0C, 0x02, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x03, - 0x04, 0x01, 0x02, 0x04, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, - 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x06, 0x4B, - 0x00, 0x00 -}; - -// Data for compression type 0x02 -static unsigned char ByteToWeight_02[] = -{ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x27, 0x00, 0x00, 0x23, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xFF, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x06, 0x0E, 0x10, 0x04, - 0x06, 0x08, 0x05, 0x04, 0x04, 0x03, 0x03, 0x02, 0x02, 0x03, 0x03, 0x01, 0x01, 0x02, 0x01, 0x01, - 0x01, 0x04, 0x02, 0x04, 0x02, 0x02, 0x02, 0x01, 0x01, 0x04, 0x01, 0x01, 0x02, 0x03, 0x03, 0x02, - 0x03, 0x01, 0x03, 0x06, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x02, 0x01, 0x01, - 0x01, 0x29, 0x07, 0x16, 0x12, 0x40, 0x0A, 0x0A, 0x11, 0x25, 0x01, 0x03, 0x17, 0x10, 0x26, 0x2A, - 0x10, 0x01, 0x23, 0x23, 0x2F, 0x10, 0x06, 0x07, 0x02, 0x09, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00 -}; - -// Data for compression type 0x03 -static unsigned char ByteToWeight_03[] = -{ - 0xFF, 0x0B, 0x07, 0x05, 0x0B, 0x02, 0x02, 0x02, 0x06, 0x02, 0x02, 0x01, 0x04, 0x02, 0x01, 0x03, - 0x09, 0x01, 0x01, 0x01, 0x03, 0x04, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, - 0x05, 0x01, 0x01, 0x01, 0x0D, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x01, 0x01, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, - 0x0A, 0x04, 0x02, 0x01, 0x06, 0x03, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x01, 0x01, 0x01, - 0x05, 0x02, 0x03, 0x04, 0x03, 0x03, 0x03, 0x02, 0x01, 0x01, 0x01, 0x02, 0x01, 0x02, 0x03, 0x03, - 0x01, 0x03, 0x01, 0x01, 0x02, 0x05, 0x01, 0x01, 0x04, 0x03, 0x05, 0x01, 0x03, 0x01, 0x03, 0x03, - 0x02, 0x01, 0x04, 0x03, 0x0A, 0x06, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x01, 0x0A, 0x02, 0x05, 0x01, 0x01, 0x02, 0x07, 0x02, 0x17, 0x01, 0x05, 0x01, 0x01, - 0x0E, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x06, 0x02, 0x01, 0x04, 0x05, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x07, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x11, - 0x00, 0x00 -}; - -// Data for compression type 0x04 -static unsigned char ByteToWeight_04[] = -{ - 0xFF, 0xFB, 0x98, 0x9A, 0x84, 0x85, 0x63, 0x64, 0x3E, 0x3E, 0x22, 0x22, 0x13, 0x13, 0x18, 0x17, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00 -}; - -// Data for compression type 0x05 -static unsigned char ByteToWeight_05[] = -{ - 0xFF, 0xF1, 0x9D, 0x9E, 0x9A, 0x9B, 0x9A, 0x97, 0x93, 0x93, 0x8C, 0x8E, 0x86, 0x88, 0x80, 0x82, - 0x7C, 0x7C, 0x72, 0x73, 0x69, 0x6B, 0x5F, 0x60, 0x55, 0x56, 0x4A, 0x4B, 0x40, 0x41, 0x37, 0x37, - 0x2F, 0x2F, 0x27, 0x27, 0x21, 0x21, 0x1B, 0x1C, 0x17, 0x17, 0x13, 0x13, 0x10, 0x10, 0x0D, 0x0D, - 0x0B, 0x0B, 0x09, 0x09, 0x08, 0x08, 0x07, 0x07, 0x06, 0x05, 0x05, 0x04, 0x04, 0x04, 0x19, 0x18, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00 -}; - - // Data for compression type 0x06 -static unsigned char ByteToWeight_06[] = -{ - 0xC3, 0xCB, 0xF5, 0x41, 0xFF, 0x7B, 0xF7, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xBF, 0xCC, 0xF2, 0x40, 0xFD, 0x7C, 0xF7, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7A, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00 -}; - -// Data for compression type 0x07 -static unsigned char ByteToWeight_07[] = -{ - 0xC3, 0xD9, 0xEF, 0x3D, 0xF9, 0x7C, 0xE9, 0x1E, 0xFD, 0xAB, 0xF1, 0x2C, 0xFC, 0x5B, 0xFE, 0x17, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xBD, 0xD9, 0xEC, 0x3D, 0xF5, 0x7D, 0xE8, 0x1D, 0xFB, 0xAE, 0xF0, 0x2C, 0xFB, 0x5C, 0xFF, 0x18, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x70, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00 -}; - -// Data for compression type 0x08 -static unsigned char ByteToWeight_08[] = -{ - 0xBA, 0xC5, 0xDA, 0x33, 0xE3, 0x6D, 0xD8, 0x18, 0xE5, 0x94, 0xDA, 0x23, 0xDF, 0x4A, 0xD1, 0x10, - 0xEE, 0xAF, 0xE4, 0x2C, 0xEA, 0x5A, 0xDE, 0x15, 0xF4, 0x87, 0xE9, 0x21, 0xF6, 0x43, 0xFC, 0x12, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xB0, 0xC7, 0xD8, 0x33, 0xE3, 0x6B, 0xD6, 0x18, 0xE7, 0x95, 0xD8, 0x23, 0xDB, 0x49, 0xD0, 0x11, - 0xE9, 0xB2, 0xE2, 0x2B, 0xE8, 0x5C, 0xDD, 0x15, 0xF1, 0x87, 0xE7, 0x20, 0xF7, 0x44, 0xFF, 0x13, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x5F, 0x9E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00 -}; - -static unsigned char * WeightTables[0x09] = -{ - ByteToWeight_00, - ByteToWeight_01, - ByteToWeight_02, - ByteToWeight_03, - ByteToWeight_04, - ByteToWeight_05, - ByteToWeight_06, - ByteToWeight_07, - ByteToWeight_08 -}; - -//----------------------------------------------------------------------------- -// Debug/diagnostics - -#ifdef _DEBUG -void DumpHuffmannTree(THTreeItem * pItem) -{ - THTreeItem * pChildLo; // Item with the lower weight - THTreeItem * pChildHi; // Item with the higher weight - - // Get the lower-weight branch - pChildLo = pItem->pChildLo; - if(pChildLo != NULL) - { - // Get the higher-weight branch - pChildHi = pChildLo->pPrev; - - // Parse the lower-weight branch - DumpHuffmannTree(pChildHi); - DumpHuffmannTree(pChildLo); - } -} -#endif - -//----------------------------------------------------------------------------- -// TInputStream functions - -TInputStream::TInputStream(void * pvInBuffer, size_t cbInBuffer) -{ - pbInBufferEnd = (unsigned char *)pvInBuffer + cbInBuffer; - pbInBuffer = (unsigned char *)pvInBuffer; - BitBuffer = 0; - BitCount = 0; -} - -// Gets one bit from input stream -unsigned int TInputStream::Get1Bit() -{ - unsigned int OneBit = 0; - - // Ensure that the input stream is reloaded, if there are no bits left - if(BitCount == 0) - { - // Refill the bit buffer - BitBuffer = *pbInBuffer++; - BitCount = 8; - } - - // Copy the bit from bit buffer to the variable - OneBit = (BitBuffer & 0x01); - BitBuffer >>= 1; - BitCount--; - - return OneBit; -} - -// Gets the whole byte from the input stream. -unsigned int TInputStream::Get8Bits() -{ - unsigned int dwReloadByte = 0; - unsigned int dwOneByte = 0; - - // If there is not enough bits to get the value, - // we have to add 8 more bits from the input buffer - if(BitCount < 8) - { - dwReloadByte = *pbInBuffer++; - BitBuffer |= dwReloadByte << BitCount; - BitCount += 8; - } - - // Return the lowest 8 its - dwOneByte = (BitBuffer & 0xFF); - BitBuffer >>= 8; - BitCount -= 8; - return dwOneByte; -} - -// Gets 7 bits from the stream. DOES NOT remove the bits from input stream -bool TInputStream::Peek7Bits(unsigned int & Value) -{ - unsigned int Value8Bits = 0; - - // If there is not enough bits to get the value, - // we have to add 8 more bits from the input buffer - if(BitCount < 7) - { - // Load additional 8 bits. Be careful if we have no more data - if(pbInBuffer >= pbInBufferEnd) - return false; - Value8Bits = *pbInBuffer++; - - // Add these 8 bits to the bit buffer - BitBuffer |= Value8Bits << BitCount; - BitCount += 8; - } - - // Return 7 bits of data. DO NOT remove them from the input stream - Value = (BitBuffer & 0x7F); - return true; -} - -void TInputStream::SkipBits(unsigned int dwBitsToSkip) -{ - unsigned int dwReloadByte = 0; - - // If there is not enough bits in the buffer, - // we have to add 8 more bits from the input buffer - if(BitCount < dwBitsToSkip) - { - dwReloadByte = *pbInBuffer++; - BitBuffer |= dwReloadByte << BitCount; - BitCount += 8; - } - - // Skip the remaining bits - BitBuffer >>= dwBitsToSkip; - BitCount -= dwBitsToSkip; -} - -//----------------------------------------------------------------------------- -// TOutputStream functions - -TOutputStream::TOutputStream(void * pvOutBuffer, size_t cbOutLength) -{ - pbOutBufferEnd = (unsigned char *)pvOutBuffer + cbOutLength; - pbOutBuffer = (unsigned char *)pvOutBuffer; - BitBuffer = 0; - BitCount = 0; -} - -void TOutputStream::PutBits(unsigned int dwValue, unsigned int nBitCount) -{ - BitBuffer |= (dwValue << BitCount); - BitCount += nBitCount; - - // Flush completed bytes - while(BitCount >= 8) - { - if(pbOutBuffer < pbOutBufferEnd) - *pbOutBuffer++ = (unsigned char)BitBuffer; - - BitBuffer >>= 8; - BitCount -= 8; - } -} - -void TOutputStream::Flush() -{ - while(BitCount != 0) - { - if(pbOutBuffer < pbOutBufferEnd) - *pbOutBuffer++ = (unsigned char)BitBuffer; - - BitBuffer >>= 8; - BitCount -= ((BitCount > 8) ? 8 : BitCount); - } -} - -//----------------------------------------------------------------------------- -// Methods of the THTreeItem struct - -void THTreeItem::RemoveItem() -{ - if(pNext != NULL) - { - pPrev->pNext = pNext; - pNext->pPrev = pPrev; - pNext = pPrev = NULL; - } -} - -//----------------------------------------------------------------------------- -// THuffmannTree class functions - -THuffmannTree::THuffmannTree(bool bCompression) -{ - pFirst = pLast = LIST_HEAD(); - MinValidValue = 1; - ItemsUsed = 0; - bIsCmp0 = 0; - - memset(ItemsByByte, 0, sizeof(ItemsByByte)); - - // If we are going to decompress data, we need to invalidate all item links - // We do so by zeroing their ValidValue, so it becomes lower MinValidValue - if(bCompression == false) - { - memset(QuickLinks, 0, sizeof(QuickLinks)); - } -} - -THuffmannTree::~THuffmannTree() -{ - // Our Huffmann tree does not use any memory allocations, - // so we don't need to do eny code in the destructor -} - -void THuffmannTree::LinkTwoItems(THTreeItem * pItem1, THTreeItem * pItem2) -{ - pItem2->pNext = pItem1->pNext; - pItem2->pPrev = pItem1->pNext->pPrev; - pItem1->pNext->pPrev = pItem2; - pItem1->pNext = pItem2; -} - -// Inserts item into the tree (?) -void THuffmannTree::InsertItem(THTreeItem * pNewItem, TInsertPoint InsertPoint, THTreeItem * pInsertPoint) -{ - // Remove the item from the tree - pNewItem->RemoveItem(); - - if(pInsertPoint == NULL) - pInsertPoint = LIST_HEAD(); - - switch(InsertPoint) - { - case InsertAfter: - LinkTwoItems(pInsertPoint, pNewItem); - return; - - case InsertBefore: - pNewItem->pNext = pInsertPoint; // Set next item (or pointer to pointer to first item) - pNewItem->pPrev = pInsertPoint->pPrev; // Set prev item (or last item in the tree) - pInsertPoint->pPrev->pNext = pNewItem; - pInsertPoint->pPrev = pNewItem; // Set the next/last item - return; - } -} - -THTreeItem * THuffmannTree::FindHigherOrEqualItem(THTreeItem * pItem, unsigned int Weight) -{ - // Parse all existing items - if(pItem != NULL) - { - while(pItem != LIST_HEAD()) - { - if(pItem->Weight >= Weight) - return pItem; - - pItem = pItem->pPrev; - } - } - - // If not found, we just get the first item - return LIST_HEAD(); -} - -THTreeItem * THuffmannTree::CreateNewItem(unsigned int DecompressedValue, unsigned int Weight, TInsertPoint InsertPoint) -{ - THTreeItem * pNewItem = NULL; - - // Don't let the item buffer run out of space - if(ItemsUsed < HUFF_ITEM_COUNT) - { - // Allocate new item from the item pool - pNewItem = &ItemBuffer[ItemsUsed++]; - - // Insert this item to the top of the tree - InsertItem(pNewItem, InsertPoint, NULL); - - // Fill the rest of the item - pNewItem->DecompressedValue = DecompressedValue; - pNewItem->Weight = Weight; - pNewItem->pParent = NULL; - pNewItem->pChildLo = NULL; - } - - return pNewItem; -} - -unsigned int THuffmannTree::FixupItemPosByWeight(THTreeItem * pNewItem, unsigned int MaxWeight) -{ - THTreeItem * pHigherItem; - - if(pNewItem->Weight < MaxWeight) - { - // Find an item that has higher weight than this one - pHigherItem = FindHigherOrEqualItem(pLast, pNewItem->Weight); - - // Remove the item and put it to the new position - pNewItem->RemoveItem(); - LinkTwoItems(pHigherItem, pNewItem); - } - else - { - MaxWeight = pNewItem->Weight; - } - - // Return the (updated) maximum weight - return MaxWeight; -} - -// Builds Huffman tree. Called with the first 8 bits loaded from input stream -bool THuffmannTree::BuildTree(unsigned int CompressionType) -{ - THTreeItem * pNewItem; - THTreeItem * pChildLo; - THTreeItem * pChildHi; - unsigned char * WeightTable; - unsigned int MaxWeight; // [ESP+10] - The greatest character found in table - - // Clear all pointers in HTree item array - memset(ItemsByByte, 0, sizeof(ItemsByByte)); - MaxWeight = 0; - - // Ensure that the compression type is in range - if((CompressionType & 0x0F) > 0x08) - return false; - WeightTable = WeightTables[CompressionType & 0x0F]; - - // Build the linear list of entries that is sorted by byte weight - for(unsigned int i = 0; i < 0x100; i++) - { - // Skip all the bytes which are zero. - if(WeightTable[i] != 0) - { - // Create new tree item - ItemsByByte[i] = pNewItem = CreateNewItem(i, WeightTable[i], InsertAfter); - - // We need to put the item to the right place in the list - MaxWeight = FixupItemPosByWeight(pNewItem, MaxWeight); - } - } - - // Insert termination entries at the end of the list - ItemsByByte[0x100] = CreateNewItem(0x100, 1, InsertBefore); - ItemsByByte[0x101] = CreateNewItem(0x101, 1, InsertBefore); - - // Now we need to build the tree. We start at the last entry - // and go backwards to the first one - pChildLo = pLast; - - // Work as long as both children are valid - // pChildHi is child with higher weight, pChildLo is the one with lower weight - while(pChildLo != LIST_HEAD()) - { - // Also get and verify the higher-weight child - pChildHi = pChildLo->pPrev; - if(pChildHi == LIST_HEAD()) - break; - - // Create new parent item for the children - pNewItem = CreateNewItem(0, pChildHi->Weight + pChildLo->Weight, InsertAfter); - if(pNewItem == NULL) - return false; - - // Link both child items to their new parent - pChildLo->pParent = pNewItem; - pChildHi->pParent = pNewItem; - pNewItem->pChildLo = pChildLo; - - // Fixup the item's position by its weight - MaxWeight = FixupItemPosByWeight(pNewItem, MaxWeight); - - // Get the previous lower-weight child - pChildLo = pChildHi->pPrev; - } - - // Initialize the MinValidValue to 1, which invalidates all quick-link items - MinValidValue = 1; - return true; -} - -void THuffmannTree::IncWeightsAndRebalance(THTreeItem * pItem) -{ - THTreeItem * pHigherItem; // A previous item with greater or equal weight - THTreeItem * pChildHi; // The higher-weight child - THTreeItem * pChildLo; // The lower-weight child - THTreeItem * pParent; - - // Climb up the tree and increment weight of each tree item - for(; pItem != NULL; pItem = pItem->pParent) - { - // Increment the item's weight - pItem->Weight++; - - // Find a previous item with equal or greater weight, which is not equal to this item - pHigherItem = FindHigherOrEqualItem(pItem->pPrev, pItem->Weight); - pChildHi = pHigherItem->pNext; - - // If the item is not equal to the tree item, we need to rebalance the tree - if(pChildHi != pItem) - { - // Move the previous item to the RIGHT from the given item - pChildHi->RemoveItem(); - LinkTwoItems(pItem, pChildHi); - - // Move the given item AFTER the greater-weight tree item - pItem->RemoveItem(); - LinkTwoItems(pHigherItem, pItem); - - // We need to maintain the tree so that pChildHi->Weight is >= pChildLo->Weight. - // Rebalance the tree accordingly. - pChildLo = pChildHi->pParent->pChildLo; - pParent = pItem->pParent; - if(pParent->pChildLo == pItem) - pParent->pChildLo = pChildHi; - if(pChildLo == pChildHi) - pChildHi->pParent->pChildLo = pItem; - pParent = pItem->pParent; - pItem->pParent = pChildHi->pParent; - pChildHi->pParent = pParent; - - // Increment the global valid value. This invalidates all quick-link items. - MinValidValue++; - } - } -} - -bool THuffmannTree::InsertNewBranchAndRebalance(unsigned int Value1, unsigned int Value2) -{ - THTreeItem * pLastItem = pLast; - THTreeItem * pChildHi; - THTreeItem * pChildLo; - - // Create higher-weight child - pChildHi = CreateNewItem(Value1, pLastItem->Weight, InsertBefore); - if(pChildHi != NULL) - { - pChildHi->pParent = pLastItem; - ItemsByByte[Value1] = pChildHi; - - // Create lower-weight child - pChildLo = CreateNewItem(Value2, 0, InsertBefore); - if(pChildLo != NULL) - { - pChildLo->pParent = pLastItem; - pLastItem->pChildLo = pChildLo; - ItemsByByte[Value2] = pChildLo; - - IncWeightsAndRebalance(pChildLo); - return true; - } - } - - // No more space in the tree buffer - return false; -} - -void THuffmannTree::EncodeOneByte(TOutputStream * os, THTreeItem * pItem) -{ - THTreeItem * pParent = pItem->pParent; - unsigned int BitBuffer = 0; - unsigned int BitCount = 0; - - // Put 1's as long as there is parent - while(pParent != NULL) - { - // Fill the bit buffer - BitBuffer = (BitBuffer << 1) | ((pParent->pChildLo != pItem) ? 1 : 0); - BitCount++; - - // Move to the parent - pItem = pParent; - pParent = pParent->pParent; - } - - // Write the bits to the output stream - os->PutBits(BitBuffer, BitCount); -} - -unsigned int THuffmannTree::DecodeOneByte(TInputStream * is) -{ - THTreeItem * pItemLink = NULL; - THTreeItem * pItem; - unsigned int ItemLinkIndex; - unsigned int BitCount = 0; - bool bHasItemLinkIndex; - - // Try to retrieve quick link index - bHasItemLinkIndex = is->Peek7Bits(ItemLinkIndex); - - // Is the quick-link item valid? - if(bHasItemLinkIndex && QuickLinks[ItemLinkIndex].ValidValue > MinValidValue) - { - // If that item needs less than 7 bits, we can get decompressed value directly - if(QuickLinks[ItemLinkIndex].ValidBits <= 7) - { - is->SkipBits(QuickLinks[ItemLinkIndex].ValidBits); - return QuickLinks[ItemLinkIndex].DecompressedValue; - } - - // Otherwise we cannot get decompressed value directly - // but we can skip 7 levels of tree parsing - pItem = QuickLinks[ItemLinkIndex].pItem; - is->SkipBits(7); - } - else - { - // Just a sanity check - if(pFirst == LIST_HEAD()) - return 0x1FF; - - // We don't have the quick-link item, we need to parse the tree from its root - pItem = pFirst; - } - - // Step down the tree until we find a terminal item - while(pItem->pChildLo != NULL) - { - // If the next bit in the compressed stream is set, we get the higher-weight - // child. Otherwise, get the lower-weight child. - pItem = is->Get1Bit() ? pItem->pChildLo->pPrev : pItem->pChildLo; - BitCount++; - - // If the number of loaded bits reached 7, - // remember the current item for storing into quick-link item array - if(BitCount == 7) - pItemLink = pItem; - } - - // If we didn't get the item from the quick-link array, - // set the entry in it - if(bHasItemLinkIndex && QuickLinks[ItemLinkIndex].ValidValue < MinValidValue) - { - // If the current compressed byte was more than 7 bits, - // set a quick-link item with pointer to tree item - if(BitCount > 7) - { - QuickLinks[ItemLinkIndex].ValidValue = MinValidValue; - QuickLinks[ItemLinkIndex].ValidBits = BitCount; - QuickLinks[ItemLinkIndex].pItem = pItemLink; - } - else - { - // Limit the quick-decompress item to lower amount of bits - // Coverity fix 84457: (x >> 32) has undefined behavior - ItemLinkIndex = (BitCount != 0) ? ItemLinkIndex & (0xFFFFFFFF >> (32 - BitCount)) : 0; - while(ItemLinkIndex < LINK_ITEM_COUNT) - { - // Fill the quick-decompress item - QuickLinks[ItemLinkIndex].ValidValue = MinValidValue; - QuickLinks[ItemLinkIndex].ValidBits = BitCount; - QuickLinks[ItemLinkIndex].DecompressedValue = pItem->DecompressedValue; - - // Increment the index - ItemLinkIndex += (1 << BitCount); - } - } - } - - // Return the decompressed value from the found item - return pItem->DecompressedValue; -} - -unsigned int THuffmannTree::Compress(TOutputStream * os, void * pvInBuffer, int cbInBuffer, int CompressionType) -{ - unsigned char * pbInBufferEnd = (unsigned char *)pvInBuffer + cbInBuffer; - unsigned char * pbInBuffer = (unsigned char *)pvInBuffer; - unsigned char * pbOutBuff = os->pbOutBuffer; - unsigned char InputByte; - - if(!BuildTree(CompressionType)) - return 0; - bIsCmp0 = (CompressionType == 0); - - // Store the compression type into output buffer - os->PutBits(CompressionType, 8); - - // Process the entire input buffer - while(pbInBuffer < pbInBufferEnd) - { - // Get the (next) byte from the input buffer - InputByte = *pbInBuffer++; - - // Do we have an item for such input value? - if(ItemsByByte[InputByte] == NULL) - { - // Encode the relationship - EncodeOneByte(os, ItemsByByte[0x101]); - - // Store the loaded byte into output stream - os->PutBits(InputByte, 8); - - if(!InsertNewBranchAndRebalance(pLast->DecompressedValue, InputByte)) - return 0; - - if(bIsCmp0) - { - IncWeightsAndRebalance(ItemsByByte[InputByte]); - continue; - } - - IncWeightsAndRebalance(ItemsByByte[InputByte]); - } - else - { - EncodeOneByte(os, ItemsByByte[InputByte]); - } - - if(bIsCmp0) - { - IncWeightsAndRebalance(ItemsByByte[InputByte]); - } - } - - // Put the termination mark to the compressed stream - EncodeOneByte(os, ItemsByByte[0x100]); - - // Flush the remaining bits - os->Flush(); - return (unsigned int)(os->pbOutBuffer - pbOutBuff); -} - -// Decompression using Huffman tree (1500E450) -unsigned int THuffmannTree::Decompress(void * pvOutBuffer, unsigned int cbOutLength, TInputStream * is) -{ - unsigned char * pbOutBufferEnd = (unsigned char *)pvOutBuffer + cbOutLength; - unsigned char * pbOutBuffer = (unsigned char *)pvOutBuffer; - unsigned int DecompressedValue = 0; - unsigned int CompressionType = 0; - - // Test the output length. Must not be NULL. - if(cbOutLength == 0) - return 0; - - // Get the compression type from the input stream - CompressionType = is->Get8Bits(); - bIsCmp0 = (CompressionType == 0) ? 1 : 0; - - // Build the Huffman tree - if(!BuildTree(CompressionType)) - return 0; - - // Process the entire input buffer until end of the stream - while((DecompressedValue = DecodeOneByte(is)) != 0x100) - { - // Did an error occur? - if(DecompressedValue == 0x1FF) // An error occurred - return 0; - - // Huffman tree needs to be modified - if(DecompressedValue == 0x101) - { - // The decompressed byte is stored in the next 8 bits - DecompressedValue = is->Get8Bits(); - - if(!InsertNewBranchAndRebalance(pLast->DecompressedValue, DecompressedValue)) - return 0; - - if(bIsCmp0 == 0) - IncWeightsAndRebalance(ItemsByByte[DecompressedValue]); - } - - // Store the byte to the output stream - if(pbOutBuffer >= pbOutBufferEnd) - break; - *pbOutBuffer++ = (unsigned char)DecompressedValue; - - if(bIsCmp0) - { - IncWeightsAndRebalance(ItemsByByte[DecompressedValue]); - } - } - - return (unsigned int)(pbOutBuffer - (unsigned char *)pvOutBuffer); -} - diff --git a/src/util/mpq/huff.h b/src/util/mpq/huff.h deleted file mode 100644 index cf1ca4c..0000000 --- a/src/util/mpq/huff.h +++ /dev/null @@ -1,143 +0,0 @@ -/*****************************************************************************/ -/* huffman.h Copyright (c) Ladislav Zezula 2003 */ -/*---------------------------------------------------------------------------*/ -/* Description : */ -/*---------------------------------------------------------------------------*/ -/* Date Ver Who Comment */ -/* -------- ---- --- ------- */ -/* xx.xx.xx 1.00 Lad The first version of huffman.h */ -/* 03.05.03 2.00 Lad Added compression */ -/* 08.12.03 2.01 Dan High-memory handling (> 0x80000000) */ -/*****************************************************************************/ - -#ifndef __HUFFMAN_H__ -#define __HUFFMAN_H__ - -//----------------------------------------------------------------------------- -// Defines - -#define HUFF_ITEM_COUNT 0x203 // Number of items in the item pool -#define LINK_ITEM_COUNT 0x80 // Maximum number of quick-link items - -//----------------------------------------------------------------------------- -// Structures and classes - -// Input stream for Huffmann decompression -class TInputStream -{ - public: - - TInputStream(void * pvInBuffer, size_t cbInBuffer); - unsigned int Get1Bit(); - unsigned int Get8Bits(); - bool Peek7Bits(unsigned int & Value); - void SkipBits(unsigned int BitCount); - - unsigned char * pbInBufferEnd; // End position in the the input buffer - unsigned char * pbInBuffer; // Current position in the the input buffer - unsigned int BitBuffer; // Input bit buffer - unsigned int BitCount; // Number of bits remaining in 'dwBitBuff' -}; - - -// Output stream for Huffmann compression -class TOutputStream -{ - public: - - TOutputStream(void * pvOutBuffer, size_t cbOutLength); - void PutBits(unsigned int dwValue, unsigned int nBitCount); - void Flush(); - - unsigned char * pbOutBufferEnd; // End position in the output buffer - unsigned char * pbOutBuffer; // Current position in the output buffer - unsigned int BitBuffer; // Bit buffer - unsigned int BitCount; // Number of bits in the bit buffer -}; - -// A virtual tree item that represents the head of the item list -#define LIST_HEAD() ((THTreeItem *)(&pFirst)) - -enum TInsertPoint -{ - InsertAfter = 1, - InsertBefore = 2 -}; - -// Huffmann tree item -struct THTreeItem -{ - THTreeItem() { pPrev = pNext = NULL; DecompressedValue = 0; Weight = 0; pParent = pChildLo = NULL; } -// ~THTreeItem() { RemoveItem(); } - - void RemoveItem(); -// void RemoveEntry(); - - THTreeItem * pNext; // Pointer to lower-weight tree item - THTreeItem * pPrev; // Pointer to higher-weight item - unsigned int DecompressedValue; // 08 - Decompressed byte value (also index in the array) - unsigned int Weight; // 0C - Weight - THTreeItem * pParent; // 10 - Pointer to parent item (NULL if none) - THTreeItem * pChildLo; // 14 - Pointer to the child with lower-weight child ("left child") -}; - - -// Structure used for quick navigating in the huffmann tree. -// Allows skipping up to 7 bits in the compressed stream, thus -// decompressing a bit faster. Sometimes it can even get the decompressed -// byte directly. -struct TQuickLink -{ - unsigned int ValidValue; // If greater than THuffmannTree::MinValidValue, the entry is valid - unsigned int ValidBits; // Number of bits that are valid for this item link - union - { - THTreeItem * pItem; // Pointer to the item within the Huffmann tree - unsigned int DecompressedValue; // Value for direct decompression - }; -}; - - -// Structure for Huffman tree (Size 0x3674 bytes). Because I'm not expert -// for the decompression, I do not know actually if the class is really a Hufmann -// tree. If someone knows the decompression details, please let me know -class THuffmannTree -{ - public: - - THuffmannTree(bool bCompression); - ~THuffmannTree(); - - void LinkTwoItems(THTreeItem * pItem1, THTreeItem * pItem2); - void InsertItem(THTreeItem * item, TInsertPoint InsertPoint, THTreeItem * item2); - - THTreeItem * FindHigherOrEqualItem(THTreeItem * pItem, unsigned int Weight); - THTreeItem * CreateNewItem(unsigned int DecompressedValue, unsigned int Weight, TInsertPoint InsertPoint); - - unsigned int FixupItemPosByWeight(THTreeItem * pItem, unsigned int MaxWeight); - bool BuildTree(unsigned int CompressionType); - - void IncWeightsAndRebalance(THTreeItem * pItem); - bool InsertNewBranchAndRebalance(unsigned int Value1, unsigned int Value2); - - void EncodeOneByte(TOutputStream * os, THTreeItem * pItem); - unsigned int DecodeOneByte(TInputStream * is); - - unsigned int Compress(TOutputStream * os, void * pvInBuffer, int cbInBuffer, int nCmpType); - unsigned int Decompress(void * pvOutBuffer, unsigned int cbOutLength, TInputStream * is); - - THTreeItem ItemBuffer[HUFF_ITEM_COUNT]; // Buffer for tree items. No memory allocation is needed - unsigned int ItemsUsed; // Number of tree items used from ItemBuffer - - // Head of the linear item list - THTreeItem * pFirst; // Pointer to the highest weight item - THTreeItem * pLast; // Pointer to the lowest weight item - - THTreeItem * ItemsByByte[0x102]; // Array of item pointers, one for each possible byte value - TQuickLink QuickLinks[LINK_ITEM_COUNT]; // Array of quick-link items - - unsigned int MinValidValue; // A minimum value of TQDecompress::ValidValue to be considered valid - unsigned int bIsCmp0; // 1 if compression type 0 -}; - -#endif // __HUFFMAN_H__ diff --git a/src/util/mpq/pklib.h b/src/util/mpq/pklib.h deleted file mode 100644 index 95c7b3b..0000000 --- a/src/util/mpq/pklib.h +++ /dev/null @@ -1,160 +0,0 @@ -/*****************************************************************************/ -/* pklib.h Copyright (c) Ladislav Zezula 2003 */ -/*---------------------------------------------------------------------------*/ -/* Header file for PKWARE Data Compression Library */ -/*---------------------------------------------------------------------------*/ -/* Date Ver Who Comment */ -/* -------- ---- --- ------- */ -/* 31.03.03 1.00 Lad Created */ -/*****************************************************************************/ - -#ifndef __PKLIB_H__ -#define __PKLIB_H__ - -#pragma once - -//----------------------------------------------------------------------------- -// Defines - -#define CMP_BINARY 0 // Binary compression -#define CMP_ASCII 1 // Ascii compression - -#define CMP_NO_ERROR 0 -#define CMP_INVALID_DICTSIZE 1 -#define CMP_INVALID_MODE 2 -#define CMP_BAD_DATA 3 -#define CMP_ABORT 4 - -#define CMP_IMPLODE_DICT_SIZE1 1024 // Dictionary size of 1024 -#define CMP_IMPLODE_DICT_SIZE2 2048 // Dictionary size of 2048 -#define CMP_IMPLODE_DICT_SIZE3 4096 // Dictionary size of 4096 - -//----------------------------------------------------------------------------- -// Define calling convention - -#ifndef PKEXPORT -#ifdef WIN32 -#define PKEXPORT __cdecl // Use for normal __cdecl calling -#else -#define PKEXPORT -#endif -#endif - -//----------------------------------------------------------------------------- -// Internal structures - -// Compression structure -typedef struct -{ - unsigned int distance; // 0000: Backward distance of the currently found repetition, decreased by 1 - unsigned int out_bytes; // 0004: # bytes available in out_buff - unsigned int out_bits; // 0008: # of bits available in the last out byte - unsigned int dsize_bits; // 000C: Number of bits needed for dictionary size. 4 = 0x400, 5 = 0x800, 6 = 0x1000 - unsigned int dsize_mask; // 0010: Bit mask for dictionary. 0x0F = 0x400, 0x1F = 0x800, 0x3F = 0x1000 - unsigned int ctype; // 0014: Compression type (CMP_ASCII or CMP_BINARY) - unsigned int dsize_bytes; // 0018: Dictionary size in bytes - unsigned char dist_bits[0x40]; // 001C: Distance bits - unsigned char dist_codes[0x40]; // 005C: Distance codes - unsigned char nChBits[0x306]; // 009C: Table of literal bit lengths to be put to the output stream - unsigned short nChCodes[0x306]; // 03A2: Table of literal codes to be put to the output stream - unsigned short offs09AE; // 09AE: - - void * param; // 09B0: User parameter - unsigned int (*read_buf)(char *buf, unsigned int *size, void *param); // 9B4 - void (*write_buf)(char *buf, unsigned int *size, void *param); // 9B8 - - unsigned short offs09BC[0x204]; // 09BC: - unsigned long offs0DC4; // 0DC4: - unsigned short phash_to_index[0x900]; // 0DC8: Array of indexes (one for each PAIR_HASH) to the "pair_hash_offsets" table - unsigned short phash_to_index_end; // 1FC8: End marker for "phash_to_index" table - char out_buff[0x802]; // 1FCA: Compressed data - unsigned char work_buff[0x2204]; // 27CC: Work buffer - // + DICT_OFFSET => Dictionary - // + UNCMP_OFFSET => Uncompressed data - unsigned short phash_offs[0x2204]; // 49D0: Table of offsets for each PAIR_HASH -} TCmpStruct; - -#define CMP_BUFFER_SIZE sizeof(TCmpStruct) // Size of compression structure. - // Defined as 36312 in pkware header file - - -// Decompression structure -typedef struct -{ - unsigned long offs0000; // 0000 - unsigned long ctype; // 0004: Compression type (CMP_BINARY or CMP_ASCII) - unsigned long outputPos; // 0008: Position in output buffer - unsigned long dsize_bits; // 000C: Dict size (4, 5, 6 for 0x400, 0x800, 0x1000) - unsigned long dsize_mask; // 0010: Dict size bitmask (0x0F, 0x1F, 0x3F for 0x400, 0x800, 0x1000) - unsigned long bit_buff; // 0014: 16-bit buffer for processing input data - unsigned long extra_bits; // 0018: Number of extra (above 8) bits in bit buffer - unsigned int in_pos; // 001C: Position in in_buff - unsigned long in_bytes; // 0020: Number of bytes in input buffer - void * param; // 0024: Custom parameter - unsigned int (*read_buf)(char *buf, unsigned int *size, void *param); // Pointer to function that reads data from the input stream - void (*write_buf)(char *buf, unsigned int *size, void *param);// Pointer to function that writes data to the output stream - - unsigned char out_buff[0x2204]; // 0030: Output circle buffer. - // 0x0000 - 0x0FFF: Previous uncompressed data, kept for repetitions - // 0x1000 - 0x1FFF: Currently decompressed data - // 0x2000 - 0x2203: Reserve space for the longest possible repetition - unsigned char in_buff[0x800]; // 2234: Buffer for data to be decompressed - unsigned char DistPosCodes[0x100]; // 2A34: Table of distance position codes - unsigned char LengthCodes[0x100]; // 2B34: Table of length codes - unsigned char offs2C34[0x100]; // 2C34: Buffer for - unsigned char offs2D34[0x100]; // 2D34: Buffer for - unsigned char offs2E34[0x80]; // 2E34: Buffer for - unsigned char offs2EB4[0x100]; // 2EB4: Buffer for - unsigned char ChBitsAsc[0x100]; // 2FB4: Buffer for - unsigned char DistBits[0x40]; // 30B4: Numbers of bytes to skip copied block length - unsigned char LenBits[0x10]; // 30F4: Numbers of bits for skip copied block length - unsigned char ExLenBits[0x10]; // 3104: Number of valid bits for copied block - unsigned short LenBase[0x10]; // 3114: Buffer for -} TDcmpStruct; - -#define EXP_BUFFER_SIZE sizeof(TDcmpStruct) // Size of decompression structure - // Defined as 12596 in pkware headers - -//----------------------------------------------------------------------------- -// Tables (in explode.c) - -extern const unsigned char DistBits[0x40]; -extern const unsigned char DistCode[0x40]; -extern const unsigned char ExLenBits[0x10]; -extern const unsigned short LenBase[0x10]; -extern const unsigned char LenBits[0x10]; -extern const unsigned char LenCode[0x10]; -extern const unsigned char ChBitsAsc[0x100]; -extern const unsigned short ChCodeAsc[0x100]; - -//----------------------------------------------------------------------------- -// Public functions - -#ifdef __cplusplus - extern "C" { -#endif - -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); - - -unsigned int PKEXPORT 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); - -// The original name "crc32" was changed to "crc32_pklib" due -// to compatibility with zlib -unsigned long PKEXPORT crc32_pklib(char *buffer, unsigned int *size, unsigned long *old_crc); - -#ifdef __cplusplus - } // End of 'extern "C"' declaration -#endif - -#endif // __PKLIB_H__ diff --git a/src/util/mpq/sparse.cpp b/src/util/mpq/sparse.cpp deleted file mode 100644 index 6d1b621..0000000 --- a/src/util/mpq/sparse.cpp +++ /dev/null @@ -1,282 +0,0 @@ -/*****************************************************************************/ -/* huffman.cpp Copyright (c) Ladislav Zezula 1998-2003 */ -/*---------------------------------------------------------------------------*/ -/* This module contains Huffmann (de)compression methods */ -/* */ -/* Authors : Ladislav Zezula (ladik.zezula.net) */ -/* ShadowFlare (BlakFlare@hotmail.com) */ -/* */ -/*---------------------------------------------------------------------------*/ -/* Date Ver Who Comment */ -/* -------- ---- --- ------- */ -/* xx.xx.xx 1.00 Lad The first version of dcmp.cpp */ -/* 03.05.03 1.00 Lad Added compression methods */ -/* 19.11.03 1.01 Dan Big endian handling */ -/* 08.12.03 2.01 Dan High-memory handling (> 0x80000000) */ -/*****************************************************************************/ - -#include -#include - -#include "sparse.h" - -//----------------------------------------------------------------------------- -// Public functions - -void CompressSparse(void * pvOutBuffer, int * pcbOutBuffer, void * pvInBuffer, int cbInBuffer) -{ - unsigned char * pbOutBufferEnd = (unsigned char *)pvOutBuffer + *pcbOutBuffer; - unsigned char * pbInBufferEnd = (unsigned char *)pvInBuffer + cbInBuffer; - unsigned char * pbLastNonZero = (unsigned char *)pvInBuffer; - unsigned char * pbOutBuffer0 = (unsigned char *)pvOutBuffer; - unsigned char * pbInBuffPtr = (unsigned char *)pvInBuffer; - unsigned char * pbOutBuffer = (unsigned char *)pvOutBuffer; - unsigned char * pbInBuffer = (unsigned char *)pvInBuffer; - size_t NumberOfNonZeros; - size_t NumberOfZeros; - - // There must be at least 4 bytes of free space in the output buffer now - if((pbInBuffer + 4) >= pbInBufferEnd) - return; - - // Put the original data length (in little endian) - *pbOutBuffer++ = (unsigned char)(cbInBuffer >> 0x18); - *pbOutBuffer++ = (unsigned char)(cbInBuffer >> 0x10); - *pbOutBuffer++ = (unsigned char)(cbInBuffer >> 0x08); - *pbOutBuffer++ = (unsigned char)(cbInBuffer >> 0x00); - - // If there is at least 3 bytes in the input buffer, do this loop - while(pbInBuffer < (pbInBufferEnd - 3)) - { - // Reset the zero count and frontal pointer - pbLastNonZero = pbInBuffer; - pbInBuffPtr = pbInBuffer; - NumberOfZeros = 0; - - if(pbInBuffPtr < pbInBufferEnd) - { - do - { - // Count number of zeros - if(*pbInBuffPtr == 0) - { - NumberOfZeros++; - } - else - { - // Were there at least 3 zeros before? If yes, we need to flush the data - if(NumberOfZeros >= 3) - break; - pbLastNonZero = pbInBuffPtr + 1; - NumberOfZeros = 0; - } - } - while(++pbInBuffPtr < pbInBufferEnd); - } - - // Get number of nonzeros that we found so far and flush them - NumberOfNonZeros = pbLastNonZero - pbInBuffer; - if(NumberOfNonZeros != 0) - { - // Process blocks that are longer than 0x81 nonzero bytes - while(NumberOfNonZeros > 0x81) - { - // Verify if we still have enough space in output buffer - if((pbOutBuffer + 0x81) >= pbOutBufferEnd) - return; - - // Put marker that means "0x80 of nonzeros" - *pbOutBuffer++ = 0xFF; - memcpy(pbOutBuffer, pbInBuffer, 0x80); - - // Adjust counter of nonzeros and both pointers - NumberOfNonZeros -= 0x80; - pbOutBuffer += 0x80; - pbInBuffer += 0x80; - } - - // BUGBUG: The following code will be triggered if the NumberOfNonZeros - // was 0x81 before. It will copy just one byte. This seems like a bug to me, - // but since I want StormLib to be exact like Blizzard code is, I will keep - // it that way here - if(NumberOfNonZeros > 0x80) - { - // Verify if we still have enough space in output buffer - if((pbOutBuffer + 2) >= pbOutBufferEnd) - return; - - // Put marker that means "1 nonzero byte" - *pbOutBuffer++ = 0x80; - memcpy(pbOutBuffer, pbInBuffer, 1); - - // Adjust counter of nonzeros and both pointers - NumberOfNonZeros--; - pbOutBuffer++; - pbInBuffer++; - } - - // If there is 1 nonzero or more, put the block - if(NumberOfNonZeros >= 0x01) - { - // Verify if we still have enough space in output buffer - if((pbOutBuffer + NumberOfNonZeros + 1) >= pbOutBufferEnd) - return; - - // Put marker that means "Several nonzero bytes" - *pbOutBuffer++ = (unsigned char)(0x80 | (NumberOfNonZeros - 1)); - memcpy(pbOutBuffer, pbInBuffer, NumberOfNonZeros); - - // Adjust pointers - pbOutBuffer += NumberOfNonZeros; - pbInBuffer += NumberOfNonZeros; - } - } - - // Now flush all zero bytes - while(NumberOfZeros > 0x85) - { - // Do we have at least 2 bytes in the output buffer ? - if((pbOutBuffer + 1) >= pbOutBufferEnd) - return; - - // Put marker that means "0x82 zeros" - *pbOutBuffer++ = 0x7F; - - // Adjust zero counter and input pointer - NumberOfZeros -= 0x82; - pbInBuffer += 0x82; - } - - // If we got more than 0x82 zeros, flush 3 of them now - if(NumberOfZeros > 0x82) - { - // Do we have at least 2 bytes in the output buffer ? - if((pbOutBuffer + 1) >= pbOutBufferEnd) - return; - - // Put marker that means "0x03 zeros" - *pbOutBuffer++ = 0; - - // Adjust zero counter and input pointer - NumberOfZeros -= 0x03; - pbInBuffer += 0x03; - } - - // Is there at least three zeros ? - if(NumberOfZeros >= 3) - { - // Do we have at least 2 bytes in the output buffer ? - if((pbOutBuffer + 1) >= pbOutBufferEnd) - return; - - // Put marker that means "Several zeros" - *pbOutBuffer++ = (unsigned char)(NumberOfZeros - 3); - - // Adjust pointer - pbInBuffer += NumberOfZeros; - } - } - - // Flush last three bytes - if(pbInBuffer < pbInBufferEnd) - { - pbInBuffPtr = pbInBuffer; - - for(;;) - { - if(*pbInBuffPtr++ != 0) - { - // Get number of bytes remaining - NumberOfNonZeros = (pbInBufferEnd - pbInBuffer); - - // Not enough space in the output buffer ==> exit - if((pbOutBuffer + NumberOfNonZeros + 1) >= pbOutBufferEnd) - return; - - // Terminate with a marker that means "0x80 of nonzeros" - *pbOutBuffer++ = 0xFF; - memcpy(pbOutBuffer, pbInBuffer, NumberOfNonZeros); - - // Adjust pointer - pbOutBuffer += NumberOfNonZeros; - break; - } - else - { - // Is there are more chars in the input buffer - if(pbInBuffPtr < pbInBufferEnd) - continue; - - // If the compression will not compress it by even 1 byte, do nothing - if((pbOutBuffer + 1) >= pbOutBufferEnd) - return; - - // Terminate with a chunk that means "0x82 of zeros" - *pbOutBuffer++ = 0x7F; - break; - } - } - } - - // Out the length of the output buffer - *pcbOutBuffer = (int)(pbOutBuffer - pbOutBuffer0); -} - -int DecompressSparse(void * pvOutBuffer, int * pcbOutBuffer, void * pvInBuffer, int cbInBuffer) -{ - unsigned char * pbInBufferEnd = (unsigned char *)pvInBuffer + cbInBuffer; - unsigned char * pbOutBuffer = (unsigned char *)pvOutBuffer; - unsigned char * pbInBuffer = (unsigned char *)pvInBuffer; - unsigned int cbChunkSize; - unsigned int cbOutBuffer = 0; - unsigned int OneByte; - - // Don't decompress anything that is shorter than 5 bytes - if(cbInBuffer < 5) - return 0; - - // Get the 32-bits from the input stream - OneByte = *pbInBuffer++; - cbOutBuffer |= (OneByte << 0x18); - OneByte = *pbInBuffer++; - cbOutBuffer |= (OneByte << 0x10); - OneByte = *pbInBuffer++; - cbOutBuffer |= (OneByte << 0x08); - OneByte = *pbInBuffer++; - cbOutBuffer |= (OneByte << 0x00); - - // Verify the size of the stream against the output buffer size - if(cbOutBuffer > (unsigned int)*pcbOutBuffer) - return 0; - - // Put the output size to the buffer - *pcbOutBuffer = cbOutBuffer; - - // Process the input buffer - while(pbInBuffer < pbInBufferEnd) - { - // Get (next) byte from the stream - OneByte = *pbInBuffer++; - - // If highest bit, it means that that normal data follow - if(OneByte & 0x80) - { - cbChunkSize = (OneByte & 0x7F) + 1; - cbChunkSize = (cbChunkSize < cbOutBuffer) ? cbChunkSize : cbOutBuffer; - memcpy(pbOutBuffer, pbInBuffer, cbChunkSize); - pbInBuffer += cbChunkSize; - } - else - { - cbChunkSize = (OneByte & 0x7F) + 3; - cbChunkSize = (cbChunkSize < cbOutBuffer) ? cbChunkSize : cbOutBuffer; - memset(pbOutBuffer, 0, cbChunkSize); - } - - // Increment output buffer pointer - pbOutBuffer += cbChunkSize; - cbOutBuffer -= cbChunkSize; - } - - return 1; -} diff --git a/src/util/mpq/sparse.h b/src/util/mpq/sparse.h deleted file mode 100644 index 12f62b5..0000000 --- a/src/util/mpq/sparse.h +++ /dev/null @@ -1,17 +0,0 @@ -/*****************************************************************************/ -/* sparse.h Copyright (c) Ladislav Zezula 2010 */ -/*---------------------------------------------------------------------------*/ -/* implementation of Sparse compression, used in Starcraft II */ -/*---------------------------------------------------------------------------*/ -/* Date Ver Who Comment */ -/* -------- ---- --- ------- */ -/* 05.03.10 1.00 Lad The first version of sparse.h */ -/*****************************************************************************/ - -#ifndef __SPARSE_H__ -#define __SPARSE_H__ - -void CompressSparse(void * pvOutBuffer, int * pcbOutBuffer, void * pvInBuffer, int cbInBuffer); -int DecompressSparse(void * pvOutBuffer, int * pcbOutBuffer, void * pvInBuffer, int cbInBuffer); - -#endif // __SPARSE_H__