Example #1
0
        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());
            }
        }
Example #2
0
        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);
        }