public static async Task <string> XmbToXmlAsync(byte[] data) { using (var fileStream = new MemoryStream(data, false)) { XMBFile xmb = await XMBFile.LoadXMBFile(fileStream); using StringWriter sw = new CustomEncodingStringWriter(Encoding.UTF8); using XmlTextWriter textWriter = new XmlTextWriter(sw); textWriter.Formatting = Formatting.Indented; xmb.file.Save(textWriter); return(sw.ToString()); } }
public static async Task <XMBFile> LoadXMBFile(Stream input) { XMBFile xmb = new XMBFile(); xmb.file = new XmlDocument(); var reader = new BinaryReader(input, Encoding.Default, true); reader.Read(xmb.decompressedHeader = new char[2], 0, 2); if (new string(xmb.decompressedHeader) != "X1") { throw new Exception("'X1' not detected - Not a valid XML file!"); } xmb.dataLength = reader.ReadUInt32(); reader.Read(xmb.unknown1 = new char[2], 0, 2); if (new string(xmb.unknown1) != "XR") { throw new Exception("'XR' not detected - Not a valid XML file!"); } xmb.unknown2 = reader.ReadUInt32(); xmb.version = reader.ReadUInt32(); if (xmb.unknown2 != 4) { throw new Exception("'4' not detected - Not a valid XML file!"); } if (xmb.version != 8) { throw new Exception("Not a valid Age of Empires 3 XML file!"); } xmb.numElements = reader.ReadUInt32(); // Now that we know how many elements there are we can read through // them and create them in our XMBFile object. List <string> elements = new List <string>(); for (int i = 0; i < xmb.numElements; i++) { int elementLength = reader.ReadInt32(); elements.Add(Encoding.Unicode.GetString(reader.ReadBytes(elementLength * 2))); } // Now do the same for attributes xmb.numAttributes = reader.ReadUInt32(); List <string> attributes = new List <string>(); for (int i = 0; i < xmb.numAttributes; i++) { int attributeLength = reader.ReadInt32(); attributes.Add(Encoding.Unicode.GetString(reader.ReadBytes(attributeLength * 2))); } // Now parse the root element... await Task.Run(() => { XmlElement root = xmb.parseNode(ref reader, elements, attributes); if (root != null) { xmb.file.AppendChild(root); } }); return(xmb); }