示例#1
0
        public bool Load(Stream stream)
        {
            var serializer = GetSerializer();

            if (serializer != null)
            {
                if (Type == FileType.Xml)
                {
                    if (serializer is INomadXmlFileSerializer)
                    {
                        throw new InvalidOperationException("Can't load XML data from a stream; serializer has external dependencies");
                    }

                    // make sure we have an XML serializer
                    if (serializer.Type != FileType.Xml)
                    {
                        serializer = new NomadXmlSerializer();
                    }
                }

                Root = serializer.Deserialize(stream);
                return(true);
            }

            // couldn't deserialize data
            return(false);
        }
示例#2
0
        public bool Save(Stream stream)
        {
            var serializer = GetSerializer();

            if (serializer != null)
            {
                if (Type == FileType.Xml)
                {
                    if (serializer is INomadXmlFileSerializer)
                    {
                        throw new InvalidOperationException("Can't save XML data to a stream; serializer has external dependencies");
                    }

                    // make sure we have an XML serializer
                    if (serializer.Type != FileType.Xml)
                    {
                        serializer = new NomadXmlSerializer();
                    }
                }

                serializer.Serialize(stream, Root);
                return(true);
            }

            Debug.WriteLine("Attempted to serialize to a stream but no serializer was present.");
            return(false);
        }
示例#3
0
        public void LoadXml(string filename)
        {
            var srl = new NomadXmlSerializer();

            NomadObject root = null;

            using (var fs = File.Open(filename, FileMode.Open))
            {
                root = srl.Deserialize(fs);
            }

            Version   = int.Parse(root.GetAttributeValue("Version"));
            MoveCount = int.Parse(root.GetAttributeValue("Count"));

            var resources = new List <MoveResourceData>();
            var infos     = new List <MoveResourceInfo>();

            var size = 0;

            foreach (var child in root.Children)
            {
                var resource = new MoveResourceData();
                resource.Deserialize(child);

                resources.Add(resource);

                var info = resource.GetInfo();
                infos.Add(info);

                size += info.Size;
            }

            var buffer = new byte[size];
            var offset = 0;

            for (int i = 0; i < resources.Count; i++)
            {
                var resource = resources[i];
                var info     = infos[i];

                foreach (var param in resource.AllParams)
                {
                    var globalParam = AllParams.First((p) => p.Name == param.Name);

                    globalParam.Values.AddRange(param.Values);

                    foreach (var fixup in param.Fixups)
                    {
                        var fixupInfo = new FixupInfo(fixup.Hash, fixup.Offset + offset);
                        globalParam.Fixups.Add(fixupInfo);
                    }
                }

                Buffer.BlockCopy(resource.MoveData, 0, buffer, offset, info.Size);
                offset += info.Size;
            }

            PerMoveResourceInfo.Infos = infos;
            MoveData = buffer;
        }
示例#4
0
        public void SaveXml(string filename)
        {
            var rootDir = Path.GetDirectoryName(filename);

            var xml  = new XDocument();
            var root = new XElement("FCXMapData");

            root.SetAttributeValue("Version", Version);

            var srl = new NomadXmlSerializer();

            if (IsUserMap)
            {
                srl.CreateXmlElement(MetaData, root);
                srl.CreateXmlElement(ConfigData, root);
            }
            else
            {
                if (UID != Guid.Empty)
                {
                    root.SetAttributeValue("UID", UID);
                }
            }

            using (var bs = new BinaryStream(MapData))
            {
                var arc = new FCXMapArchive();
                arc.Deserialize(bs);

                var data = arc.Data.Unpack();
                var hdr  = arc.Header.Unpack();
                var desc = arc.Descriptor.Unpack();

                File.WriteAllBytes(Path.Combine(rootDir, Path.ChangeExtension(filename, ".dat")), data);
                File.WriteAllBytes(Path.Combine(rootDir, Path.ChangeExtension(filename, ".fat")), hdr);
                File.WriteAllBytes(Path.Combine(rootDir, Path.ChangeExtension(filename, ".fat.xml")), desc);
            }

            xml.Add(root);
            xml.SaveFormatted(filename, true);
        }
示例#5
0
        public static ResourceFile Open(string filename, bool load = true)
        {
            var type  = FileType.Binary;
            var flags = FileTypeFlags.None;

            var ext = Path.GetExtension(filename);

            switch (ext)
            {
            case ".rml":
                flags |= FileTypeFlags.Rml;
                break;

            case ".xml":
                type = FileType.Xml;
                break;
            }

            var isRml = flags.HasFlag(FileTypeFlags.Rml);
            var isXml = (type == FileType.Xml || isRml) && Utils.IsXmlFile(filename);

            INomadSerializer serializer = null;
            var valid = true;

            ResourceFilter filter = null;

            if (isXml)
            {
                serializer = new NomadXmlSerializer();

                var xml = Utils.LoadXmlFile(filename);

                filter = GetFilter(xml.Root);

                if (filter != null)
                {
                    // is there a serializer that requires external dependencies?
                    var xmlSerializer = GetSerializer(filter) as INomadXmlFileSerializer;

                    if (xmlSerializer != null)
                    {
                        serializer = xmlSerializer;
                    }
                }
            }
            else
            {
                if (NomadFactory.GetBinaryInfo(filename, out NomadFileInfo info))
                {
                    serializer = NomadFactory.GetSerializer(info);
                    filter     = GetFilter(info);
                }

                // make sure it's not an empty file
                valid = info.IsValid;
            }

            ResourceFile result = null;

            if (valid)
            {
                result = new ResourceFile()
                {
                    Type             = type,
                    CustomSerializer = serializer,
                    CustomFilter     = filter,
                };

                if (load)
                {
                    result.Load(filename);
                }
            }

            return(result);
        }
示例#6
0
        public void SaveXml(string filename)
        {
            var xml  = new XDocument();
            var root = new XElement("CombinedMoveFile");

            root.SetAttributeValue("Version", 1);
            root.SetAttributeValue("Count", MoveCount);

            var srl = new NomadXmlSerializer();

            //foreach (var child in Root.Children)
            //    srl.CreateXmlElement(child, root);

            var fixups = new List <(int offset, int hash, string param)>();

            foreach (var param in AllParams)
            {
                foreach (var fixup in param.Fixups)
                {
                    fixups.Add((fixup.Offset, fixup.Hash, param.Name));
                }
            }

            fixups = fixups.OrderBy((e) => e.offset).ToList();

            var resources = new List <MoveResourceData>();
            var offset    = 0;

            foreach (var info in PerMoveResourceInfo.Infos)
            {
                var hash  = BitConverter.ToInt32(MoveData, offset);
                var bound = (offset + info.Size);

                var resource = new MoveResourceData();
                var hashes   = new List <int>();

                foreach (var fixup in fixups.Where((e) => e.offset > offset))
                {
                    if (fixup.offset > bound)
                    {
                        break;
                    }

                    var param       = resource.AllParams.First((m) => m.Name == fixup.param);
                    var globalParam = AllParams.First((m) => m.Name == fixup.param);

                    var fixupInfo = new FixupInfo(fixup.hash, fixup.offset - offset);

                    param.Fixups.Add(fixupInfo);

                    // add value once
                    if (!hashes.Contains(fixup.hash))
                    {
                        hashes.Add(fixup.hash);

                        foreach (var value in globalParam.Values)
                        {
                            var hashAttr = value.GetAttribute("hash");
                            var hashData = hashAttr.Data;

                            int paramHash = 0;

                            // HACKS!!!!!
                            if (hashData.Size < 4)
                            {
                                if (hashData.Size == 1)
                                {
                                    paramHash = (sbyte)hashData.Buffer[0];
                                }
                                else
                                {
                                    paramHash = Utils.UnpackData(hashAttr, BitConverter.ToInt16);
                                }
                            }
                            else
                            {
                                paramHash = Utils.UnpackData(hashAttr, BitConverter.ToInt32);
                            }

                            if (paramHash == fixup.hash)
                            {
                                param.Values.Add(value);
                                break;
                            }
                        }
                    }
                }

                var buffer = new byte[info.Size];

                Buffer.BlockCopy(MoveData, offset, buffer, 0, info.Size);

                resource.RootNodeId = info.RootNodeId;
                resource.MoveData   = buffer;

                resources.Add(resource);

                offset += info.Size;
            }

            foreach (var resource in resources)
            {
                srl.CreateXmlElement(resource.ToObject(), root);
            }

#if PATCH_FIXUP_TAGS
            var buffer = new byte[MoveData.Length];

            Buffer.BlockCopy(MoveData, 0, buffer, 0, buffer.Length);

            foreach (var param in AllParams)
            {
                if (param.Tag == "xxxx")
                {
                    continue;
                }

                MagicNumber mgx = param.Tag;

                var tag = BitConverter.GetBytes((int)mgx);

                foreach (var fixup in param.Fixups)
                {
                    Buffer.BlockCopy(tag, 0, buffer, fixup.Offset, tag.Length);
                }
            }

            File.WriteAllBytes(Path.ChangeExtension(filename, ".tags.bin"), buffer);
#endif
#if DUMP_FIXUP_LOG_INFO
            var dbg = new List <(int offset, string name, int old, int hash)>();
            var sb  = new StringBuilder();

            foreach (var param in AllParams)
            {
                var idx = 0;

                foreach (var fixup in param.Fixups)
                {
                    var orig = BitConverter.ToInt32(MoveData, fixup.Offset);

                    dbg.Add((fixup.Offset, $"{param.Name} fixup {idx++}", orig, fixup.Hash));
                }
            }

            var fixups = dbg.OrderBy((e) => e.offset).ToList();

            var infoOffset = 0;
            var infoIndex  = 0;

            var rootDir = Path.GetDirectoryName(filename);
            var outDir  = Path.Combine(rootDir, "movedata_files");

            if (!Directory.Exists(outDir))
            {
                Directory.CreateDirectory(outDir);
            }

            foreach (var info in PerMoveResourceInfo.Infos)
            {
                var hash = BitConverter.ToInt32(MoveData, infoOffset);

                var unk_04 = BitConverter.ToInt32(MoveData, infoOffset + 4);

                var unk_08 = MoveData[infoOffset + 8];
                var unk_09 = MoveData[infoOffset + 9];
                var unk_0a = MoveData[infoOffset + 10];
                var unk_0b = MoveData[infoOffset + 11];

                sb.AppendLine($"MoveData({hash:X8})[{infoIndex++}] @ {infoOffset:X8}");
                sb.AppendLine($"  Unk_04: {unk_04}");
                sb.AppendLine($"  Unk_08: ({unk_08}, {unk_09}, {unk_0a}, {unk_0b})");
                sb.AppendLine($"  RootNodeId: {info.RootNodeId:X8}");

                var upperBound = (infoOffset + info.Size);

                var fixupOffset = infoOffset;

                foreach (var fixup in fixups.Where((e) => e.offset < upperBound))
                {
                    if (fixup.offset < infoOffset)
                    {
                        continue;
                    }

                    sb.AppendLine($" - {fixup.offset - infoOffset:X8}: {fixup.old:X8} -> {fixup.hash:X8} ; {fixup.name}");
                }

                var buffer = new byte[info.Size];

                Buffer.BlockCopy(MoveData, infoOffset, buffer, 0, info.Size);
                File.WriteAllBytes(Path.Combine(outDir, $"{unk_08}_{unk_09}_{unk_0a}_{unk_0b}#{hash:X8}.bin"), buffer);

                infoOffset += info.Size;
            }

            //var dbgTxt = String.Join("\r\n", dbg.OrderBy((e) => e.offset).Select((e) => $"{e.offset:X8}: {e.old:X8} -> {e.hash:X8} ; {e.name}"));
            //sb.Append(dbgTxt);

            File.WriteAllBytes(Path.ChangeExtension(filename, ".data.bin"), MoveData);
            File.WriteAllText(Path.ChangeExtension(filename, ".debug.log"), sb.ToString());
#endif
            xml.Add(root);
            xml.SaveFormatted(filename, true);
        }