他人の空似自作物置場

touhouSE.zip/touhouSE_src/DxArchive.cpp


#include "stdafx.h"

namespace TouhouSE {

namespace DX_ARCHIVE {

void decrypt(const unsigned int size, const unsigned long long int addr, const std::array<unsigned char, 12> &key, unsigned char * const buf) {
   unsigned int table_index = addr % key.size();
   for (unsigned int i = 0; i < size; i++) {
      buf[i] ^= key[table_index];
      table_index = (table_index + 1) % key.size();
   }
}

bool decompress(const std::vector<unsigned char> &in, std::vector<unsigned char> &out) {
   if (in.size() < 9) {
      return false;
   }
   const unsigned int out_size = *reinterpret_cast<const unsigned int *>(&in[0]);
   const unsigned int in_size = *reinterpret_cast<const unsigned int *>(&in[4]);
   if (in_size != in.size()) {
      return false;
   }
   out.resize(out_size);
   const unsigned char compress_flag = in[8];
   for (unsigned int i = 9, out_index = 0; true;) {
      if (in.size() <= i) {
         if (i != in.size() || out_index != out.size()) {
            return false;
         }
         break;
      }
      if (in[i] != compress_flag) {
         if (out.size() <= out_index) {
            return false;
         }
         out[out_index] = in[i];
         i++;
         out_index++;
         continue;
      }
      if (in.size() <= i + 1) {
         return false;
      }
      if (in[i + 1] == compress_flag) {
         if (out.size() <= out_index) {
            return false;
         }
         out[out_index] = in[i];
         i += 2;
         out_index++;
         continue;
      }
      if (in.size() <= i + 2) {
         return false;
      }
      const unsigned char temp = (in[i + 1] > compress_flag ? in[i + 1] - 1 : in[i + 1]);
      const unsigned int index_size = (temp & 0x03) + 1;
      const bool is_ex_length = ((temp & 0x04) != 0);
      const unsigned int len = (is_ex_length ? in[i + 2] << 5 : 0) + (temp >> 3) + 4;
      if (is_ex_length) {
         i += 3;
      } else {
         i += 2;
      }
      const unsigned int index = 1 + (
         index_size == 1 ?
         in[i]
         :
         (index_size == 2 ?
            *reinterpret_cast<const unsigned short *>(&in[i])
            :
            *reinterpret_cast<const unsigned int *>(&in[i]) & 0x00FFFFFF
            )
         );
      i += index_size;
      if (out_index < index) {
         return false;
      }
      for (unsigned int j = 0; j < len; j++) {
         out[out_index] = out[out_index - index];
         out_index++;
      }
   }
   return true;
}

} // DX_ARCHIVE

} // ToudouSE