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); }
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); }
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; }
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); }
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); }
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); }