public static void Decode(string arg) { LocalizedTexts texts; using (var stream = new FileStream(arg, FileMode.Open, FileAccess.Read, FileShare.Read)) using (var reader = new BinaryReader(stream)) { if (arg.ToLower().EndsWith(".item")) { stream.Position = 0x3C; } else { stream.Position = 4; var metadataLength = reader.ReadInt32(); if ((metadataLength & 7) != 0) { Console.WriteLine("WARNING: The first offset doesn't seem to be valid."); } stream.Position = ((metadataLength >> 3) << 3) - 4; } stream.Position = reader.ReadInt32(); var numStrings = reader.ReadInt32(); if (numStrings <= 0) { throw new NoStringException(); } texts = new LocalizedTexts(numStrings); var numPointers = reader.ReadInt32(); var stringPointers = new StringPointer[numStrings]; for (var i = 0; i < numStrings; i++) { stringPointers[i] = new StringPointer(reader); } var pointerPointers = new LanguagePointer[numPointers]; for (var i = 0; i < numPointers; i++) { pointerPointers[i] = new LanguagePointer(reader); } var baseOffset = stream.Position; foreach (var stringPointer in stringPointers) { var text = new LocalizedText(stringPointer.Count); for (var i = 0; i < stringPointer.Count; i++) { var pointer = pointerPointers[stringPointer.Index + i]; stream.Position = baseOffset + pointer.Offset; text.Add(pointer.LanguageID, ReadString(reader)); } texts.Add(text); } } File.WriteAllText(arg + ".xml", texts.ToString()); }
public static void Encode(string arg) { var texts = new LocalizedTexts(XDocument.Load(arg).Element("strings")); var stringPointers = new StringPointer[texts.Count]; var pointerPointers = new List <LanguagePointer>(texts.Count); var stringOffsets = new Dictionary <string, int>(); int pointerIndex = 0, offset = 0; for (var i = 0; i < texts.Count; i++) { stringPointers[i].Index = pointerIndex; pointerIndex += stringPointers[i].Count = texts[i].Count; foreach (var pair in texts[i]) { if (!stringOffsets.ContainsKey(pair.Value)) { pointerPointers.Add(new LanguagePointer(pair.Key, offset)); stringOffsets.Add(pair.Value, offset); offset += Encoding.UTF8.GetByteCount(pair.Value) + 1; } else { pointerPointers.Add(new LanguagePointer(pair.Key, stringOffsets[pair.Value])); } } } using (var stream = new FileStream(arg.Remove(arg.Length - 4), FileMode.Open, FileAccess.ReadWrite, FileShare.Read)) { var reader = new BinaryReader(stream); var writer = new BinaryWriter(stream); int offsetOffset; byte[] oldBytes; var isItem = arg.ToLower().EndsWith(".item.xml"); if (isItem) { stream.Position = 0x40; var extraBytesCount = reader.ReadInt32(); stream.Position = reader.ReadInt32(); oldBytes = reader.ReadBytes(extraBytesCount + 3); offsetOffset = 0x3C; } else { stream.Position = 4; var metadataLength = reader.ReadInt32(); if ((metadataLength & 7) != 0) { Console.WriteLine("WARNING: The first offset doesn't seem to be valid."); } offsetOffset = ((metadataLength >> 3) << 3) - 4; oldBytes = new byte[0]; } stream.Position = offsetOffset; var tableOffset = stream.Position = reader.ReadInt32(); writer.Write(texts.Count); writer.Write(pointerPointers.Count); foreach (var pointer in stringPointers) { writer.Write(pointer.Index); writer.Write(pointer.Count); } foreach (var pointer in pointerPointers) { writer.Write(pointer.LanguageID); writer.Write(pointer.Offset); } foreach (var pair in stringOffsets.OrderBy(p => p.Value)) { writer.Write(Encoding.UTF8.GetBytes(pair.Key)); writer.Write((byte)0); } var oldBytesOffset = (int)stream.Position; writer.Write(oldBytes); writer.Flush(); if (stream.Position < stream.Length) { stream.SetLength(stream.Position); } stream.Position = offsetOffset - 4; writer.Write((int)(stream.Length - tableOffset - oldBytes.LongLength)); if (!isItem) { return; } stream.Position += 8; writer.Write(oldBytesOffset); } }