他人の空似自作物置場

touhouSE.zip/touhouSE_src/dx_archive_v4.cpp

#include "stdafx.h"

namespace TouhouSE {

namespace DX_ARCHIVE_V4 {

namespace endian = boost::spirit::endian;
using namespace TouhouSE::DX_ARCHIVE;

class HeaderV4 {
public:
   endian::ulittle8_t signature[2];
   endian::ulittle16_t version;
   endian::ulittle32_t footer_size;
   endian::ulittle32_t header_size;
   endian::ulittle32_t file_name_table_address;
   endian::ulittle32_t file_data_table_offset;
   endian::ulittle32_t directory_data_table_offset;
   endian::ulittle32_t codepage;

   static constexpr unsigned int getVersion() {
      return 4;
   }
   static bool readKey(const unsigned char * const in, const unsigned long long int file_size, std::array<unsigned char, 12> &key) {
      *reinterpret_cast<unsigned int *>(&key[0]) = *reinterpret_cast<const unsigned int *>(&in[0]) ^ 0x00045844;
      *reinterpret_cast<unsigned int *>(&key[8]) = *reinterpret_cast<const unsigned int *>(&in[8]) ^ 0x0000001C;
      const unsigned int file_name_table_address = *reinterpret_cast<const unsigned int *>(&in[12]) ^ *reinterpret_cast<const unsigned int *>(&key[0]);
      if (file_name_table_address > file_size) {
         return false;
      }
      const unsigned int footer_size = static_cast<unsigned int>(file_size) - file_name_table_address;
      *reinterpret_cast<unsigned int *>(&key[4]) = *reinterpret_cast<const unsigned int *>(&in[4]) ^ footer_size;
      return true;
   }
};

class DirectoryDataV4 {
public:
   endian::ulittle32_t directory_data_offset;
   endian::ulittle32_t parent_directory_offset;
   endian::ulittle32_t file_count;
   endian::ulittle32_t file_data_offset;

   static constexpr unsigned int getSize() {
      return 16;
   }
   template<typename HeaderT>
   static constexpr unsigned long long int getCryptKeyOffset(const Header<HeaderT> &header, const unsigned long long int read_size) {
      return header.file_name_table_address + header.directory_data_table_offset + read_size;
   }
};

class FileDataV4 {
public:
   endian::ulittle32_t name_offset;
   endian::ulittle32_t flag;
   endian::ulittle64_t create_time;
   endian::ulittle64_t last_access_time;
   endian::ulittle64_t last_update_time;
   endian::ulittle32_t body_offset;
   endian::ulittle32_t body_size;
   endian::ulittle32_t body_compress_size;

   template<typename HeaderT>
   static constexpr unsigned long long int getCryptKeyOffset(const Header<HeaderT> &header, const unsigned long long int read_size) {
      return header.file_name_table_address + header.file_data_table_offset + read_size;
   }
};

class FilenameV4 {
public:
   template<typename HeaderT>
   static constexpr unsigned long long int getCryptKeyOffset(const Header<HeaderT> &header, const unsigned long long int read_size) {
      return header.file_name_table_address + read_size;
   }
};

class FileBodyV4 {
public:
   static constexpr unsigned long long int getCryptKeyOffset(const FileRecord &file) {
      return file.addr;
   }
};

typedef Owner<HeaderV4, DirectoryDataV4, FileDataV4, FilenameV4, FileBodyV4> DAT_EXTRACTOR;
ADD_DAT_EXTRACTOR(DAT_EXTRACTOR);

} // DX_ARCHIVE_V4

} // ToudouSE