Advertisement
Guest User

cod aw compression algorithm

a guest
Nov 6th, 2014
1,663
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.44 KB | None | 0 0
  1. template <typename Callback>
  2. void compressed_block_iterate(const uint8_t *source_data, uint64_t source_size, Callback callback)
  3. {
  4.     uint64_t position = 0xc;
  5.     while (position < source_size)
  6.     {
  7.         uint32_t compressed_size = *reinterpret_cast<const uint32_t*>(source_data + position);
  8.         position += sizeof(uint32_t);
  9.         uint32_t uncompressed_size = *reinterpret_cast<const uint32_t*> (source_data + position);
  10.         position += sizeof(uint32_t);
  11.         const uint8_t *block_data = source_data + position;
  12.         position += compressed_size;
  13.         if (position >= source_size)
  14.             break;
  15.         position = (position + 3) & ~3; //make alignment
  16.         callback(block_data, compressed_size, uncompressed_size);
  17.     }
  18. }
  19.  
  20. uint64_t calculate_uncompressed_size(const uint8_t *source_data, uint64_t source_size)
  21. {
  22.     uint64_t result = 0;
  23.     compressed_block_iterate(source_data, source_size, [&](const uint8_t *block_data, uint64_t compressed_size, uint64_t uncompressed_size)
  24.     {
  25.         result += uncompressed_size;
  26.     });
  27.     return result;
  28. }
  29. void decompress_block(const uint8_t *source_data, uint64_t source_size,
  30.     uint8_t *destination_data, uint64_t destination_size)
  31. {
  32.     uint64_t source_position = 0;
  33.     uint64_t destination_position = 0;
  34.  
  35.     while (source_position < source_size)
  36.     {
  37.         uint8_t comp_byte = source_data[source_position++];
  38.         uint32_t data_length = (comp_byte >> 4) & 0xf;
  39.         uint32_t repeat_count = (comp_byte & 0xf);
  40.  
  41.         if (data_length == 0x0f)
  42.         {
  43.             while (true)
  44.             {
  45.                 uint8_t data_length_byte = source_data[source_position++];
  46.                 data_length += data_length_byte;
  47.                 if (data_length_byte != 0xff)
  48.                     break;
  49.             }
  50.         }
  51.  
  52.         while (data_length--)
  53.         {
  54.             destination_data[destination_position++] = source_data[source_position++];
  55.         }
  56.  
  57.         if (source_position >= source_size)
  58.         {
  59.             break;
  60.         }
  61.  
  62.         uint32_t repeat_offset = *reinterpret_cast<const uint16_t*>(source_data + source_position);
  63.         source_position += sizeof(uint16_t);
  64.  
  65.         uint64_t global_repeat_offset = destination_position - repeat_offset;
  66.  
  67.         if (repeat_count == 0x0f)
  68.         {
  69.             while (true)
  70.             {
  71.                 uint8_t repeat_count_byte = source_data[source_position++];
  72.                 repeat_count += repeat_count_byte;
  73.                 if (repeat_count_byte != 0xff)
  74.                     break;
  75.             }
  76.         }
  77.         for (uint32_t i = 0; i < repeat_count + 4; i++)
  78.         {
  79.             destination_data[destination_position++] = destination_data[global_repeat_offset + i];
  80.         }
  81.     }
  82. }
  83. std::unique_ptr<uint8_t[]> decompress_data(const uint8_t *source_data,
  84.     uint64_t source_size, uint64_t &result_size)
  85. {
  86.     result_size = calculate_uncompressed_size(source_data, source_size);
  87.     std::unique_ptr<uint8_t[]> result_data = std::make_unique<uint8_t[]>(result_size);
  88.     uint64_t destination_position = 0;
  89.  
  90.     compressed_block_iterate(source_data, source_size, [&](const uint8_t *block_data, uint64_t compressed_size, uint64_t uncompressed_size)
  91.     {
  92.         decompress_block(block_data, compressed_size,
  93.             result_data.get() + destination_position, uncompressed_size);
  94.         destination_position += uncompressed_size;
  95.     });
  96.     return result_data;
  97. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement