public byte[] ExtractResource(TAHEntry entry) { //data読み込み長さ //-4はdata書き出し長さ格納領域 (UInt32) を減じている UInt32 input_length = entry.length - 4; //data読み込みバッファ byte[] data_input = new byte[input_length]; UInt32 output_length; reader.BaseStream.Position = entry.offset; //data書き出し長さ output_length = reader.ReadUInt32(); data_input = reader.ReadBytes((int)input_length); //-- data読み込み(復号前)完了! -- //data書き出しバッファ byte[] data_output = new byte[output_length]; TAHCryption.crypt(ref data_input, input_length, output_length); Decompression.infrate(ref data_input, input_length, ref data_output, output_length); //-- data復号完了! -- return(data_output); }
/* TAH Procedures*/ public void extract_TAH_directory() { Entries = null; UInt32 arc_size = (UInt32)reader.BaseStream.Length; byte[] magic = reader.ReadBytes(4); if (magic[0] != (byte)'T' || magic[1] != (byte)'A' || magic[2] != (byte)'H' || magic[3] != (byte)'2') { throw new Exception("File is not TAH"); } Header tah_header; tah_header.index_entry_count = reader.ReadUInt32(); tah_header.version = reader.ReadUInt32(); tah_header.reserved = reader.ReadUInt32(); UInt32 index_buffer_size = tah_header.index_entry_count * 8; //sizeof(index_entry) == 8 Entries = new TAHEntry[tah_header.index_entry_count]; for (int i = 0; i < tah_header.index_entry_count; i++) { Entries[i] = new TAHEntry(); Entries[i].hash_code = reader.ReadUInt32(); Entries[i].offset = reader.ReadUInt32(); } UInt32 output_length = reader.ReadUInt32(); //entry情報の読み出し長さ UInt32 input_length = Entries[0].offset - /*sizeof(Header)*/ 16 - index_buffer_size; //entry情報の読み出しバッファ byte[] data_input = new byte[input_length]; data_input = reader.ReadBytes((int)input_length); //-- entry情報の読み込み完了! -- byte[] output_data = new byte[output_length]; TAHCryption.crypt(ref data_input, input_length, output_length); Decompression.infrate(ref data_input, input_length, ref output_data, output_length); //-- entry情報の復号完了! -- build_TAHEntries(output_data, arc_size); }
public void build_TAHEntries(byte[] str_file_path, UInt32 arc_size) { using (BinaryReader br = new BinaryReader(new MemoryStream(str_file_path))) { try { string path = ""; while (true) { string name = br.ReadCString(); if (name.EndsWith("/")) { path = name; } else { string file_name = path + name; TAHEntry ent = FindTAHEntryByHash(CalcHash(file_name)); if (ent != null) { ent.file_name = file_name; } } } } catch (EndOfStreamException) { } } ext_file_list external_files; build_ext_file_list(out external_files); for (UInt32 i = 0; i < Entries.Length; i++) { //file_nameが見つからなかった場合 if (Entries[i].file_name == null) { //names.txt を検索 int pos = -1; if (external_files.files != null) { pos = Array.BinarySearch(external_files.hashkeys, Entries[i].hash_name); } if (pos < 0) // not found { //ファイル名は <hash>にする Entries[i].file_name = string.Format("{0:X8}", Entries[i].hash_name); //file_nameが見つからなかったflag on Entries[i].flag ^= 0x1; } else { Entries[i].file_name = external_files.files[pos]; } } } for (UInt32 i = 0; i < Entries.Length - 1; i++) { //data読み込み長さを設定 //読み込み長さは現在entryオフセットと次のentryオフセットとの差である Entries[i].length = Entries[i + 1].offset - Entries[i].offset; } //最終entry data読み込み長さを設定 Entries[Entries.Length - 1].length = arc_size - Entries[Entries.Length - 1].offset; }