static void Dump(string FileName, EndianBinary.Endian Endian) { string OutFile = Path.GetFileNameWithoutExtension(FileName) + ".txt"; StringBuilder Output = new StringBuilder(); FileStream Input = new FileStream(FileName, FileMode.Open); EndianBinaryReader Reader = new EndianBinaryReader(Input, Endian); Section Lang = ParseSection(Reader); if (Lang.Signature != "LANG") { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("Invalid file!"); Console.ResetColor(); } Input.Seek(ParsePack(Reader, Lang)[0].Offset, SeekOrigin.Begin); Section Category = ParseSection(Reader); Input.Seek(ParsePack(Reader, Category)[0].Offset, SeekOrigin.Begin); Section String = ParseSection(Reader); List <PackEntry> StringPack = ParsePack(Reader, String); foreach (PackEntry Entry in StringPack) { Input.Seek(Entry.Offset, SeekOrigin.Begin); byte[] Buffer = new byte[Entry.Length - 2]; Reader.Read(Buffer, 0, Buffer.Length); Output.Append(UTF16.GetString(Buffer, Endian)); Output.AppendLine(null); Output.AppendLine(null); } File.WriteAllText(OutFile, Output.ToString().TrimEnd()); Reader.Close(); Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("Dumped " + Path.GetFileName(FileName) + "!"); Console.ResetColor(); }
static void Create(string FileName, EndianBinary.Endian Endian) { string OutFile = Path.GetFileNameWithoutExtension(FileName) + ".lang"; FileStream Output = new FileStream(OutFile, FileMode.Create); EndianBinaryWriter Writer = new EndianBinaryWriter(Output, Endian); /* * Seção String */ MemoryStream String = new MemoryStream(); EndianBinaryWriter StringWriter = new EndianBinaryWriter(String, Endian); string[] Texts = File.ReadAllText(FileName).Split(new string[] { Environment.NewLine + Environment.NewLine }, StringSplitOptions.None); List <byte[]> Buffers = new List <byte[]>(); foreach (string Text in Texts) { Buffers.Add(UTF16.GetBytes(Text, Endian)); } MemoryStream TextBlock = new MemoryStream(); foreach (byte[] Buffer in Buffers) { TextBlock.Write(Buffer, 0, Buffer.Length); TextBlock.WriteByte(0); TextBlock.WriteByte(0); //0x00 00 Null Terminator while ((TextBlock.Position & 0xf) != 0) { TextBlock.WriteByte(0); //Alinha } } StringWriter.Write(Encoding.ASCII.GetBytes("STRPACK")); StringWriter.Write(0); StringWriter.WriteLE((uint)(0x10000 | (Endian == EndianBinary.Endian.Little ? 0 : 0xff))); StringWriter.Write((uint)0x30); StringWriter.Write((uint)(0x60 + Align(Texts.Length * 4) * 2 + TextBlock.Length)); //Tamanho da seção StringWriter.Write((uint)Texts.Length); //Total de ponteiros StringWriter.Write((uint)Texts.Length); //Total de tamanhos StringWriter.Write((uint)0); //Alinha em 16 bytes StringWriter.Write((uint)0x60); //Offset relativo de inicio dos ponteiros StringWriter.Write(0x60 + Align(Texts.Length * 4)); //Offset relativo de inicio dos tamanhos StringWriter.Write((ulong)0); //Alinha em 16 bytes StringWriter.Write(Encoding.ASCII.GetBytes("string_pack")); while ((String.Position & 0xf) != 0) { String.WriteByte(0); } StringWriter.Write((uint)1); //Número de seções StringWriter.Write((uint)0x30); //Offset dos dados StringWriter.Write((ulong)0); //Alinha em 16 bytes StringWriter.Write((uint)0x54); //??? String.Seek(0xc, SeekOrigin.Current); uint DataOffset = 0x60 + Align(Texts.Length * 4) * 2; foreach (byte[] Buffer in Buffers) { StringWriter.Write(DataOffset); DataOffset += Align(Buffer.Length + 2); } while ((String.Position & 0xf) != 0) { String.WriteByte(0); } foreach (byte[] Buffer in Buffers) { StringWriter.Write((uint)Buffer.Length + 2); } while ((String.Position & 0xf) != 0) { String.WriteByte(0); } StringWriter.Write(TextBlock.ToArray()); TextBlock.Close(); /* * Seção Category */ MemoryStream Category = new MemoryStream(); EndianBinaryWriter CategoryWriter = new EndianBinaryWriter(Category, Endian); CategoryWriter.Write(Encoding.ASCII.GetBytes("CTGPACK")); CategoryWriter.Write(0); CategoryWriter.WriteLE((uint)(0x10000 | (Endian == EndianBinary.Endian.Little ? 0 : 0xff))); CategoryWriter.Write((uint)0x30); CategoryWriter.Write((uint)String.Length + 0x80); //Tamanho da seção CategoryWriter.Write((uint)1); //Total de ponteiros CategoryWriter.Write((uint)1); //Total de tamanhos CategoryWriter.Write((uint)0); //Alinha em 16 bytes CategoryWriter.Write((uint)0x60); //Offset relativo de inicio dos ponteiros CategoryWriter.Write((uint)0x70); //Offset relativo de inicio dos tamanhos CategoryWriter.Write((ulong)0); //Alinha em 16 bytes CategoryWriter.Write(Encoding.ASCII.GetBytes("category_pack")); while ((Category.Position & 0xf) != 0) { Category.WriteByte(0); } CategoryWriter.Write((uint)1); //Número de seções CategoryWriter.Write((uint)0x30); //Offset dos dados CategoryWriter.Write((ulong)0); //Alinha em 16 bytes Category.Seek(0xc, SeekOrigin.Current); if (Endian == EndianBinary.Endian.Little) { CategoryWriter.Write(0x18fc2c); //??? } else { CategoryWriter.Write((uint)0); } CategoryWriter.Write((uint)0x80); //Offset relativo onde se inicia a outra seção Category.Seek(0xc, SeekOrigin.Current); CategoryWriter.Write((uint)String.Length); //Tamanho da outra seção Category.Seek(0xc, SeekOrigin.Current); CategoryWriter.Write(String.ToArray()); String.Close(); /* * Seção Lang */ Writer.Write(Encoding.ASCII.GetBytes("LANG")); Writer.Write((uint)0); Writer.WriteLE((uint)(0x10000 | (Endian == EndianBinary.Endian.Little ? 0 : 0xff))); Writer.Write((uint)0x30); Writer.Write((uint)Category.Length + 0x80); //Tamanho da seção Writer.Write((uint)1); //Total de ponteiros Writer.Write((uint)1); //Total de tamanhos Writer.Write((uint)0); //Alinha em 16 bytes Writer.Write((uint)0x60); //Offset relativo de inicio dos ponteiros Writer.Write((uint)0x70); //Offset relativo de inicio dos tamanhos Writer.Write((ulong)0); //Alinha em 16 bytes Writer.Write(Encoding.ASCII.GetBytes("language_pack")); while ((Output.Position & 0xf) != 0) { Output.WriteByte(0); } Writer.Write((uint)1); //Número de seções Writer.Write((uint)0x30); //Offset dos dados Writer.Write((ulong)0); //Alinha em 16 bytes Output.Seek(0x10, SeekOrigin.Current); Writer.Write((uint)0x80); //Offset relativo onde se inicia a outra seção Output.Seek(0xc, SeekOrigin.Current); Writer.Write((uint)Category.Length); //Tamanho da outra seção Output.Seek(0xc, SeekOrigin.Current); Writer.Write(Category.ToArray()); Category.Close(); Output.Close(); Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("Created " + Path.GetFileName(OutFile) + "!"); Console.ResetColor(); }