Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.Text;
- namespace TSAExtract
- {
- class Entry
- {
- public string name;
- public int offset;
- public int size;
- }
- abstract class Parser
- {
- protected BinaryReader inFile;
- protected BinaryWriter outFile;
- protected string dirName;
- protected string filename;
- protected List<Entry> entries = new List<Entry>();
- public Parser(string path, string dirName)
- {
- inFile = new BinaryReader(File.OpenRead(path));
- this.dirName = dirName;
- this.filename = Path.GetFileNameWithoutExtension(path);
- }
- public void write_entries(int numFiles)
- {
- for (int i = 0; i < numFiles; i++)
- {
- create_file(entries[i].name);
- Console.WriteLine("Writing '{0}', size: {1}", entries[i].name, entries[i].size);
- write_data(entries[i]);
- outFile.Close();
- }
- }
- public abstract void create_file(string filename);
- public abstract void write_data(Entry e);
- public abstract long parse_file();
- }
- class HayateParser : Parser
- {
- // only applies to original + hayate; doesn't work for kurenai
- private byte[] table = new byte[] {
- 0x49, 0xF2, 0xD0, 0x20, 0x37, 0x5E, 0x77, 0x3E, 0x3C, 0xFB, 0x3E, 0x21,
- 0x33, 0xE9, 0xF2, 0x96, 0xD0, 0xE6, 0x89, 0x8E, 0x27, 0xD7, 0x3C, 0x45,
- 0x77, 0xDD, 0x32, 0x6B, 0x06, 0x78, 0xE1, 0x87, 0xBC, 0x10, 0xBB, 0x04,
- 0xE5, 0x7F, 0x63, 0x98, 0xB0, 0xEB, 0x78, 0x04, 0x58, 0x01, 0xA9, 0x51,
- 0xA6, 0xE8, 0xAD, 0x92, 0x8E, 0x87, 0x49, 0x4A, 0x3E, 0x64, 0x81, 0x7E,
- 0xC7, 0x37, 0xA3, 0x93, 0xC4, 0x8B, 0x3E, 0x01, 0x1F, 0xFA, 0x46, 0x79,
- 0x5D, 0xD4, 0x5F, 0x09, 0x99, 0x4E, 0xAA, 0xDC, 0x00, 0x89, 0xF5, 0x9B,
- 0x89, 0x89, 0x3C, 0x99, 0x43, 0xE2, 0xD5, 0xBF, 0xCC, 0xC7, 0x31, 0xFA,
- 0xFC, 0xB2, 0x16, 0x02, 0xC2, 0x57, 0xB0, 0xC7, 0xAA, 0x1E, 0x67, 0x7B,
- 0xAE, 0x40, 0x4E, 0x4F, 0x32, 0x69, 0xA9, 0x77, 0xD1, 0x52, 0xD0, 0x1B,
- 0xE7, 0xD0, 0xE8, 0x1F, 0xE6, 0xC8, 0x4C, 0x99, 0x73, 0x72, 0x93, 0x36,
- 0xE2, 0xFB, 0x8A, 0xEF, 0x75, 0xCE, 0x92, 0x6B, 0x89, 0x29, 0xBE, 0x48,
- 0x07, 0xC7, 0x22, 0x39, 0xD2, 0xBC, 0x96, 0xBC, 0x05, 0xC6, 0x8A, 0xCD,
- 0x22, 0xBC, 0x8B, 0x4C, 0xAE, 0xE1, 0x1B, 0x90, 0x45, 0x35, 0x8D, 0xE0,
- 0x10, 0x14, 0x7B, 0x2E, 0x4C, 0xBC, 0x7D, 0x66, 0xBD, 0x8C, 0x4E, 0x33,
- 0x2D, 0x09, 0x73, 0x71, 0xE4, 0x07, 0x9E, 0xC1, 0x3B, 0x8D, 0x57, 0xF6,
- 0xA5, 0x37, 0x23, 0x49, 0xE4, 0x33, 0x4A, 0x8E, 0xBD, 0xBF, 0x4F, 0xD9,
- 0x4F, 0x95, 0x5E, 0x4E, 0x87, 0x41, 0xAE, 0x01, 0xB6, 0x56, 0xA0, 0xAE,
- 0xC6, 0xF2, 0x1B, 0xB5, 0x24, 0x85, 0xEE, 0xFE, 0xC3, 0x4D, 0x3B, 0xDA,
- 0xF0, 0x0B, 0x22, 0x70, 0x38, 0x45, 0x50, 0x4C, 0x9E, 0x30, 0x88, 0xA9,
- 0x8A, 0x12, 0x5B, 0xFC, 0xF5, 0xAE, 0x2A, 0xEC, 0xDD, 0x11, 0x0D, 0xA6,
- 0x81, 0x54, 0xE2, 0x00 };
- private byte key;
- private byte datakey;
- private long crc;
- public HayateParser(string path, string dirName) : base(path, dirName) { }
- private byte[] readBytes(int n, byte xorkey, int offset)
- {
- byte[] temp = inFile.ReadBytes(n);
- for (int i = 0; i < temp.Length; i++)
- {
- temp[i] ^= xorkey;
- temp[i] ^= table[offset & 0xFF];
- offset += 1;
- }
- return temp;
- }
- private int readInt(byte key, int offset)
- {
- byte[] temp = readBytes(4, key, offset);
- return BitConverter.ToInt32(temp, 0);
- }
- private string read_string(int n, byte key, int offset)
- {
- return Encoding.UTF8.GetString(readBytes(n, key, offset)).TrimEnd("\0".ToCharArray());
- }
- public void read_entries(int numFiles)
- {
- Entry e;
- for (int i = 0; i < numFiles; i++)
- {
- e = new Entry();
- e.name = read_string(260, key, 0);
- e.size = readInt(key, 4);
- e.offset = readInt(key, 8);
- entries.Add(e);
- }
- }
- public override void create_file(string filename)
- {
- string outPath = Path.Combine(dirName, filename);
- outFile = new BinaryWriter(File.OpenWrite(outPath));
- }
- public override void write_data(Entry e)
- {
- inFile.BaseStream.Seek(e.offset, SeekOrigin.Begin);
- outFile.Write(readBytes(e.size, datakey, 0));
- }
- public override long parse_file()
- {
- int numFiles;
- key = (byte)(inFile.ReadByte() ^ 0x92);
- crc = readInt(key, 0);
- datakey = (byte)((crc % 0xFF) & 0xFF);
- numFiles = readInt(key, 0);
- Console.WriteLine("{0:x} header key, {1:X} xor datakey", key, datakey);
- Console.WriteLine("{0} files stored in archive", numFiles);
- read_entries(numFiles);
- write_entries(numFiles);
- return crc;
- }
- }
- class NormalParser : Parser
- {
- public NormalParser(string path, string dirName) : base(path, dirName) { }
- public string read_name(int n)
- {
- return Encoding.UTF8.GetString(inFile.ReadBytes(n)).TrimEnd("\0".ToCharArray());
- }
- public void read_entries(int numFiles)
- {
- Entry e;
- for (int i = 0; i < numFiles; i++)
- {
- e = new Entry();
- e.name = read_name(260);
- e.size = inFile.ReadInt32();
- e.offset = inFile.ReadInt32();
- entries.Add(e);
- }
- }
- public override void create_file(string filename)
- {
- string fileDirs = Path.GetDirectoryName(filename);
- string outDir = Path.Combine(dirName, fileDirs);
- string outPath = Path.Combine(dirName, filename);
- Directory.CreateDirectory(outDir);
- outFile = new BinaryWriter(File.OpenWrite(outPath));
- }
- public override void write_data(Entry e)
- {
- inFile.BaseStream.Seek(e.offset, SeekOrigin.Begin);
- outFile.Write(inFile.ReadBytes(e.size));
- }
- public override long parse_file()
- {
- int numFiles = inFile.ReadInt32();
- read_entries(numFiles);
- write_entries(numFiles);
- return 0;
- }
- }
- class TSA_Extract
- {
- private static Dictionary<string, long> keys = new Dictionary<string, long>();
- private static string keyFileDir = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
- private static string keyFilePath = Path.Combine(keyFileDir, "keys.txt");
- private static string[] normal_table = new string[] {
- "Texture.gpk", "Sound.gpk", "Mesh.gpk"};
- // original and hayate follow this table
- private static string[] hayate_table = new string[] {
- "Alice.gpk", "ArcadeBgm.gpk", "Aya.gpk", "BattleBgm.gpk", "Bgm.gpk",
- "CharaSharing.gpk", "Cirno.gpk", "Load.gpk", "Marisa.gpk",
- "Reimu.gpk", "Reisen.gpk", "Sakuya.gpk", "Sanae.gpk", "Scene.gpk",
- "SE.gpk", "Stage01.gpk", "Stage02.gpk", "Stage03.gpk", "Stage04.gpk",
- "Stage05.gpk", "Stage06.gpk", "Stage07.gpk", "Stage08.gpk", "Stage09.gpk",
- "Stage13.gpk", "Stage14.gpk", "Stage19.gpk", "StageSharing.gpk", "Suwako.gpk",
- "Utsuho.gpk", "Youmu.gpk"};
- private static string[] kurenai_table = new string[] {
- "Flandre.gpk", "Kogasa.gpk", "Koishi.gpk", "Mokou.gpk", "Nue.gpk",
- "Reisen.gpk", "Suika.gpk", "Tenshi.gpk",};
- static void load_keys()
- {
- string line;
- string[] data;
- Console.WriteLine(keyFileDir);
- if (!File.Exists(keyFilePath))
- {
- // create it
- new StreamWriter(keyFilePath).Close();
- }
- else
- {
- StreamReader keyFile = new StreamReader(keyFilePath);
- line = keyFile.ReadLine();
- while (line != null)
- {
- Console.WriteLine(line);
- data = line.Split(' ');
- keys[data[0]] = int.Parse(data[1]);
- line = keyFile.ReadLine();
- }
- keyFile.Close();
- }
- }
- static void write_keys()
- {
- StreamWriter keyFile = new StreamWriter(keyFilePath);
- List<string> list = new List<string>(keys.Keys);
- foreach (KeyValuePair<string, long> kvp in keys)
- {
- keyFile.WriteLine("{0} {1}", kvp.Key, kvp.Value);
- }
- keyFile.Close();
- }
- static bool in_table(string[] table, string name)
- {
- return Array.Exists(table, delegate(string s) { return s.Equals(name); });
- }
- static Parser get_parser(string abspath, string name)
- {
- string dirpath = Path.GetDirectoryName(abspath);
- Console.WriteLine(dirpath);
- if (in_table(normal_table, name))
- {
- Directory.CreateDirectory(dirpath);
- return new NormalParser(abspath, dirpath);
- }
- else if (in_table(hayate_table, name))
- {
- dirpath = Path.Combine(dirpath, Path.GetFileNameWithoutExtension(name));
- Directory.CreateDirectory(dirpath);
- return new HayateParser(abspath, dirpath);
- }
- else if (in_table(kurenai_table, name))
- {
- return null;
- }
- else
- return null;
- }
- static void Main(string[] args)
- {
- string ext;
- string path;
- string filename;
- long crc;
- load_keys();
- for (int i = 0; i < args.Length; i++)
- {
- path = Path.GetFullPath(args[i]);
- filename = Path.GetFileName(path);
- ext = Path.GetExtension(args[i]).ToLower();
- Parser parser = get_parser(path, filename);
- if (parser != null)
- {
- Console.WriteLine("Parsing: {0}", filename);
- crc = parser.parse_file();
- // add new key to our list of crc's
- if (crc > 0)
- keys[Path.GetFileNameWithoutExtension(filename)] = crc;
- // update the key file
- write_keys();
- }
- else
- Console.WriteLine("Invalid file: {0}", filename);
- }
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement