Advertisement
xTsukihime

Untitled

Jun 10th, 2012
424
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 11.18 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Text;
  5.  
  6. namespace TSAExtract
  7. {
  8.     class Entry
  9.     {
  10.         public string name;
  11.         public int offset;
  12.         public int size;
  13.     }
  14.  
  15.     abstract class Parser
  16.     {
  17.         protected BinaryReader inFile;
  18.         protected BinaryWriter outFile;
  19.         protected string dirName;
  20.         protected string filename;
  21.         protected List<Entry> entries = new List<Entry>();
  22.  
  23.         public Parser(string path, string dirName)
  24.         {
  25.             inFile = new BinaryReader(File.OpenRead(path));
  26.             this.dirName = dirName;
  27.             this.filename = Path.GetFileNameWithoutExtension(path);
  28.         }
  29.  
  30.         public void write_entries(int numFiles)
  31.         {
  32.             for (int i = 0; i < numFiles; i++)
  33.             {
  34.                 create_file(entries[i].name);
  35.                 Console.WriteLine("Writing '{0}', size: {1}", entries[i].name, entries[i].size);
  36.                 write_data(entries[i]);
  37.                 outFile.Close();
  38.             }
  39.         }
  40.  
  41.         public abstract void create_file(string filename);
  42.  
  43.         public abstract void write_data(Entry e);
  44.  
  45.         public abstract long parse_file();
  46.     }
  47.  
  48.     class HayateParser : Parser
  49.     {
  50.         // only applies to original + hayate; doesn't work for kurenai
  51.         private byte[] table = new byte[] {
  52.             0x49, 0xF2, 0xD0, 0x20, 0x37, 0x5E, 0x77, 0x3E, 0x3C, 0xFB, 0x3E, 0x21,
  53.             0x33, 0xE9, 0xF2, 0x96, 0xD0, 0xE6, 0x89, 0x8E, 0x27, 0xD7, 0x3C, 0x45,
  54.             0x77, 0xDD, 0x32, 0x6B, 0x06, 0x78, 0xE1, 0x87, 0xBC, 0x10, 0xBB, 0x04,
  55.             0xE5, 0x7F, 0x63, 0x98, 0xB0, 0xEB, 0x78, 0x04, 0x58, 0x01, 0xA9, 0x51,
  56.             0xA6, 0xE8, 0xAD, 0x92, 0x8E, 0x87, 0x49, 0x4A, 0x3E, 0x64, 0x81, 0x7E,
  57.             0xC7, 0x37, 0xA3, 0x93, 0xC4, 0x8B, 0x3E, 0x01, 0x1F, 0xFA, 0x46, 0x79,
  58.             0x5D, 0xD4, 0x5F, 0x09, 0x99, 0x4E, 0xAA, 0xDC, 0x00, 0x89, 0xF5, 0x9B,
  59.             0x89, 0x89, 0x3C, 0x99, 0x43, 0xE2, 0xD5, 0xBF, 0xCC, 0xC7, 0x31, 0xFA,
  60.             0xFC, 0xB2, 0x16, 0x02, 0xC2, 0x57, 0xB0, 0xC7, 0xAA, 0x1E, 0x67, 0x7B,
  61.             0xAE, 0x40, 0x4E, 0x4F, 0x32, 0x69, 0xA9, 0x77, 0xD1, 0x52, 0xD0, 0x1B,
  62.             0xE7, 0xD0, 0xE8, 0x1F, 0xE6, 0xC8, 0x4C, 0x99, 0x73, 0x72, 0x93, 0x36,
  63.             0xE2, 0xFB, 0x8A, 0xEF, 0x75, 0xCE, 0x92, 0x6B, 0x89, 0x29, 0xBE, 0x48,
  64.             0x07, 0xC7, 0x22, 0x39, 0xD2, 0xBC, 0x96, 0xBC, 0x05, 0xC6, 0x8A, 0xCD,
  65.             0x22, 0xBC, 0x8B, 0x4C, 0xAE, 0xE1, 0x1B, 0x90, 0x45, 0x35, 0x8D, 0xE0,
  66.             0x10, 0x14, 0x7B, 0x2E, 0x4C, 0xBC, 0x7D, 0x66, 0xBD, 0x8C, 0x4E, 0x33,
  67.             0x2D, 0x09, 0x73, 0x71, 0xE4, 0x07, 0x9E, 0xC1, 0x3B, 0x8D, 0x57, 0xF6,
  68.             0xA5, 0x37, 0x23, 0x49, 0xE4, 0x33, 0x4A, 0x8E, 0xBD, 0xBF, 0x4F, 0xD9,
  69.             0x4F, 0x95, 0x5E, 0x4E, 0x87, 0x41, 0xAE, 0x01, 0xB6, 0x56, 0xA0, 0xAE,
  70.             0xC6, 0xF2, 0x1B, 0xB5, 0x24, 0x85, 0xEE, 0xFE, 0xC3, 0x4D, 0x3B, 0xDA,
  71.             0xF0, 0x0B, 0x22, 0x70, 0x38, 0x45, 0x50, 0x4C, 0x9E, 0x30, 0x88, 0xA9,
  72.             0x8A, 0x12, 0x5B, 0xFC, 0xF5, 0xAE, 0x2A, 0xEC, 0xDD, 0x11, 0x0D, 0xA6,
  73.             0x81, 0x54, 0xE2, 0x00 };
  74.  
  75.         private byte key;
  76.         private byte datakey;
  77.         private long crc;
  78.  
  79.         public HayateParser(string path, string dirName) : base(path, dirName) { }
  80.  
  81.         private byte[] readBytes(int n, byte xorkey, int offset)
  82.         {
  83.             byte[] temp = inFile.ReadBytes(n);
  84.             for (int i = 0; i < temp.Length; i++)
  85.             {
  86.                 temp[i] ^= xorkey;
  87.                 temp[i] ^= table[offset & 0xFF];
  88.                 offset += 1;
  89.             }
  90.             return temp;
  91.         }
  92.  
  93.         private int readInt(byte key, int offset)
  94.         {
  95.             byte[] temp = readBytes(4, key, offset);
  96.             return BitConverter.ToInt32(temp, 0);
  97.         }
  98.  
  99.         private string read_string(int n, byte key, int offset)
  100.         {
  101.             return Encoding.UTF8.GetString(readBytes(n, key, offset)).TrimEnd("\0".ToCharArray());
  102.         }
  103.  
  104.         public void read_entries(int numFiles)
  105.         {
  106.             Entry e;
  107.             for (int i = 0; i < numFiles; i++)
  108.             {
  109.                 e = new Entry();
  110.                 e.name = read_string(260, key, 0);
  111.                 e.size = readInt(key, 4);
  112.                 e.offset = readInt(key, 8);
  113.                 entries.Add(e);
  114.             }
  115.         }
  116.  
  117.         public override void create_file(string filename)
  118.         {
  119.             string outPath = Path.Combine(dirName, filename);
  120.             outFile = new BinaryWriter(File.OpenWrite(outPath));
  121.         }
  122.  
  123.         public override void write_data(Entry e)
  124.         {
  125.             inFile.BaseStream.Seek(e.offset, SeekOrigin.Begin);
  126.             outFile.Write(readBytes(e.size, datakey, 0));
  127.         }
  128.  
  129.         public override long parse_file()
  130.         {
  131.             int numFiles;
  132.             key = (byte)(inFile.ReadByte() ^ 0x92);
  133.             crc = readInt(key, 0);
  134.             datakey = (byte)((crc % 0xFF) & 0xFF);
  135.             numFiles = readInt(key, 0);
  136.             Console.WriteLine("{0:x} header key, {1:X} xor datakey", key, datakey);
  137.             Console.WriteLine("{0} files stored in archive", numFiles);
  138.             read_entries(numFiles);
  139.             write_entries(numFiles);
  140.             return crc;
  141.         }
  142.     }
  143.  
  144.     class NormalParser : Parser
  145.     {
  146.         public NormalParser(string path, string dirName) : base(path, dirName) { }
  147.  
  148.         public string read_name(int n)
  149.         {
  150.             return Encoding.UTF8.GetString(inFile.ReadBytes(n)).TrimEnd("\0".ToCharArray());
  151.         }
  152.  
  153.         public void read_entries(int numFiles)
  154.         {
  155.             Entry e;
  156.             for (int i = 0; i < numFiles; i++)
  157.             {
  158.                 e = new Entry();
  159.                 e.name = read_name(260);
  160.                 e.size = inFile.ReadInt32();
  161.                 e.offset = inFile.ReadInt32();
  162.                 entries.Add(e);
  163.             }
  164.         }
  165.  
  166.         public override void create_file(string filename)
  167.         {
  168.             string fileDirs = Path.GetDirectoryName(filename);
  169.             string outDir = Path.Combine(dirName, fileDirs);
  170.             string outPath = Path.Combine(dirName, filename);
  171.             Directory.CreateDirectory(outDir);
  172.             outFile = new BinaryWriter(File.OpenWrite(outPath));
  173.         }
  174.  
  175.         public override void write_data(Entry e)
  176.         {
  177.             inFile.BaseStream.Seek(e.offset, SeekOrigin.Begin);
  178.             outFile.Write(inFile.ReadBytes(e.size));
  179.         }
  180.  
  181.         public override long parse_file()
  182.         {
  183.             int numFiles = inFile.ReadInt32();
  184.             read_entries(numFiles);
  185.             write_entries(numFiles);
  186.             return 0;
  187.         }
  188.     }
  189.  
  190.     class TSA_Extract
  191.     {
  192.         private static Dictionary<string, long> keys = new Dictionary<string, long>();
  193.         private static string keyFileDir = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
  194.         private static string keyFilePath = Path.Combine(keyFileDir, "keys.txt");
  195.         private static string[] normal_table = new string[] {
  196.             "Texture.gpk", "Sound.gpk", "Mesh.gpk"};
  197.  
  198.         // original and hayate follow this table
  199.         private static string[] hayate_table = new string[] {
  200.             "Alice.gpk", "ArcadeBgm.gpk", "Aya.gpk", "BattleBgm.gpk", "Bgm.gpk",
  201.             "CharaSharing.gpk", "Cirno.gpk", "Load.gpk", "Marisa.gpk",
  202.             "Reimu.gpk", "Reisen.gpk", "Sakuya.gpk", "Sanae.gpk", "Scene.gpk",
  203.             "SE.gpk", "Stage01.gpk", "Stage02.gpk", "Stage03.gpk", "Stage04.gpk",
  204.             "Stage05.gpk", "Stage06.gpk", "Stage07.gpk", "Stage08.gpk", "Stage09.gpk",
  205.             "Stage13.gpk", "Stage14.gpk", "Stage19.gpk", "StageSharing.gpk", "Suwako.gpk",
  206.             "Utsuho.gpk", "Youmu.gpk"};
  207.         private static string[] kurenai_table = new string[] {
  208.             "Flandre.gpk", "Kogasa.gpk", "Koishi.gpk", "Mokou.gpk", "Nue.gpk",
  209.             "Reisen.gpk", "Suika.gpk", "Tenshi.gpk",};
  210.  
  211.         static void load_keys()
  212.         {
  213.             string line;
  214.             string[] data;
  215.             Console.WriteLine(keyFileDir);
  216.             if (!File.Exists(keyFilePath))
  217.             {
  218.                 // create it
  219.                 new StreamWriter(keyFilePath).Close();
  220.             }
  221.             else
  222.             {
  223.                 StreamReader keyFile = new StreamReader(keyFilePath);
  224.                 line = keyFile.ReadLine();
  225.  
  226.                 while (line != null)
  227.                 {
  228.                     Console.WriteLine(line);
  229.                     data = line.Split(' ');
  230.                     keys[data[0]] = int.Parse(data[1]);
  231.                     line = keyFile.ReadLine();
  232.                 }
  233.                 keyFile.Close();
  234.             }
  235.         }
  236.  
  237.         static void write_keys()
  238.         {
  239.             StreamWriter keyFile = new StreamWriter(keyFilePath);
  240.             List<string> list = new List<string>(keys.Keys);
  241.             foreach (KeyValuePair<string, long> kvp in keys)
  242.             {
  243.                 keyFile.WriteLine("{0} {1}", kvp.Key, kvp.Value);
  244.             }
  245.             keyFile.Close();
  246.         }
  247.  
  248.         static bool in_table(string[] table, string name)
  249.         {
  250.             return Array.Exists(table, delegate(string s) { return s.Equals(name); });
  251.         }
  252.  
  253.         static Parser get_parser(string abspath, string name)
  254.         {
  255.             string dirpath = Path.GetDirectoryName(abspath);
  256.             Console.WriteLine(dirpath);
  257.             if (in_table(normal_table, name))
  258.             {
  259.                 Directory.CreateDirectory(dirpath);
  260.                 return new NormalParser(abspath, dirpath);
  261.             }
  262.             else if (in_table(hayate_table, name))
  263.             {
  264.                 dirpath = Path.Combine(dirpath, Path.GetFileNameWithoutExtension(name));
  265.                 Directory.CreateDirectory(dirpath);
  266.                 return new HayateParser(abspath, dirpath);
  267.             }
  268.             else if (in_table(kurenai_table, name))
  269.             {
  270.                 return null;
  271.             }
  272.             else
  273.                 return null;
  274.         }
  275.  
  276.         static void Main(string[] args)
  277.         {
  278.             string ext;
  279.             string path;
  280.             string filename;
  281.             long crc;
  282.  
  283.             load_keys();
  284.  
  285.             for (int i = 0; i < args.Length; i++)
  286.             {
  287.                 path = Path.GetFullPath(args[i]);
  288.                 filename = Path.GetFileName(path);
  289.                 ext = Path.GetExtension(args[i]).ToLower();
  290.                 Parser parser = get_parser(path, filename);
  291.                 if (parser != null)
  292.                 {
  293.                     Console.WriteLine("Parsing: {0}", filename);
  294.                     crc = parser.parse_file();
  295.                     // add new key to our list of crc's
  296.                     if (crc > 0)
  297.                         keys[Path.GetFileNameWithoutExtension(filename)] = crc;
  298.  
  299.  
  300.                     // update the key file
  301.                     write_keys();
  302.                 }
  303.                 else
  304.                     Console.WriteLine("Invalid file: {0}", filename);
  305.             }
  306.         }
  307.     }
  308. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement