diff --git a/CodeWalker.Core/GameFiles/FileTypes/CacheDatFile.cs b/CodeWalker.Core/GameFiles/FileTypes/CacheDatFile.cs index 6c211b4..66fa91a 100644 --- a/CodeWalker.Core/GameFiles/FileTypes/CacheDatFile.cs +++ b/CodeWalker.Core/GameFiles/FileTypes/CacheDatFile.cs @@ -2,10 +2,12 @@ using System; using System.Collections.Generic; using System.ComponentModel; +using System.Globalization; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; +using System.Xml; namespace CodeWalker.GameFiles { @@ -202,12 +204,102 @@ namespace CodeWalker.GameFiles } - - public void LoadXml(string xml) + public byte[] Save() { + MemoryStream s = new MemoryStream(); + DataWriter w = new DataWriter(s, Endianess.LittleEndian); + + w.Write("[VERSION]\n" + Version + "\n"); + while (w.Position < 100) w.Write((byte)0); + + WriteString(w, "\n"); + if (FileDates != null) + { + foreach (var d in FileDates) + { + WriteString(w, d.ToCacheFileString()); + WriteString(w, "\n"); + } + } + WriteString(w, "\n"); + WriteString(w, "\nfwMapDataStore\n"); + var modlen = (AllMapNodes?.Length ?? 0) * 64; + //if (AllMapNodes != null) + //{ + // foreach (var n in AllMapNodes) + // { + // if (n.Unk4 == 0xFE) + // { + // modlen += 96; + // } + // } + //} + w.Write(modlen); + if (AllMapNodes != null) + { + foreach (var n in AllMapNodes) + { + n.Write(w); + } + } + WriteString(w, "\n"); + WriteString(w, "\nCInteriorProxy\n"); + w.Write((AllCInteriorProxies?.Length ?? 0) * 104); + if (AllCInteriorProxies != null) + { + foreach (var p in AllCInteriorProxies) + { + p.Write(w); + } + } + WriteString(w, "\n"); + WriteString(w, "\nBoundsStore\n"); + w.Write((AllBoundsStoreItems?.Length ?? 0) * 32); + if (AllBoundsStoreItems != null) + { + foreach (var b in AllBoundsStoreItems) + { + b.Write(w); + } + } + WriteString(w, "\n"); + + + var buf = new byte[s.Length]; + s.Position = 0; + s.Read(buf, 0, buf.Length); + return buf; } - public string GetXml() + private void WriteString(DataWriter w, string s) + { + for (int i = 0; i < s.Length; i++) + { + w.Write((byte)s[i]); + } + } + + + public void WriteXml(StringBuilder sb, int indent) + { + CacheDatXml.ValueTag(sb, indent, "Version", Version); + CacheDatXml.WriteItemArray(sb, FileDates, indent, "FileDates"); + CacheDatXml.WriteItemArray(sb, AllMapNodes, indent, "MapDataStore"); + CacheDatXml.WriteItemArray(sb, AllCInteriorProxies, indent, "InteriorProxies"); + CacheDatXml.WriteItemArray(sb, AllBoundsStoreItems, indent, "BoundsStore"); + } + public void ReadXml(XmlNode node) + { + Version = Xml.GetChildStringAttribute(node, "Version"); + FileDates = XmlMeta.ReadItemArray(node, "FileDates"); + AllMapNodes = XmlMeta.ReadItemArray(node, "MapDataStore"); + AllCInteriorProxies = XmlMeta.ReadItemArray(node, "InteriorProxies"); + AllBoundsStoreItems = XmlMeta.ReadItemArray(node, "BoundsStore"); + } + + + + public string GetXmlOLD() { StringBuilder sb = new StringBuilder(); sb.AppendLine(MetaXmlBase.XmlHeader); @@ -252,8 +344,7 @@ namespace CodeWalker.GameFiles sb.AppendLine(string.Format(" ", FloatUtil.GetVector3XmlString(intprox.BBMin))); sb.AppendLine(string.Format(" ", FloatUtil.GetVector3XmlString(intprox.BBMax))); sb.AppendLine(string.Format(" ", intprox.Unk01, intprox.Unk03)); - sb.AppendLine(string.Format(" ", intprox.Unk11, intprox.Unk12, intprox.Unk13, intprox.Unk14)); - sb.AppendLine(string.Format(" ", intprox.Unk15, intprox.Unk16, intprox.Unk17, intprox.Unk18)); + sb.AppendLine(string.Format(" ", intprox.Unk11, intprox.Unk12, intprox.Unk13, intprox.Unk14)); sb.AppendLine(" "); } } @@ -287,12 +378,14 @@ namespace CodeWalker.GameFiles } } - [TypeConverter(typeof(ExpandableObjectConverter))] public class CacheFileDate + [TypeConverter(typeof(ExpandableObjectConverter))] public class CacheFileDate : IMetaXmlItem { public MetaHash FileName { get; set; } //"resource_surrogate:/%s.rpf" public DateTime TimeStamp { get; set; } public uint FileID { get; set; } + public CacheFileDate() + { } public CacheFileDate(string line) { string[] parts = line.Split(' '); @@ -311,19 +404,34 @@ namespace CodeWalker.GameFiles return FileName.Hash.ToString() + " " + TimeStamp.ToFileTimeUtc().ToString() + " " + FileID.ToString(); } + public void WriteXml(StringBuilder sb, int indent) + { + CacheDatXml.StringTag(sb, indent, "fileName", CacheDatXml.HashString(FileName)); + CacheDatXml.ValueTag(sb, indent, "timeStamp", TimeStamp.ToFileTimeUtc().ToString()); + CacheDatXml.ValueTag(sb, indent, "fileID", FileID.ToString()); + } + public void ReadXml(XmlNode node) + { + FileName = XmlMeta.GetHash(Xml.GetChildInnerText(node, "fileName")); + TimeStamp = DateTime.FromFileTimeUtc((long)Xml.GetChildULongAttribute(node, "timeStamp")); + FileID = Xml.GetChildUIntAttribute(node, "fileID"); + } + public override string ToString() { return FileName.ToString() + ", " + TimeStamp.ToString() + ", " + FileID.ToString(); } } - [TypeConverter(typeof(ExpandableObjectConverter))] public class BoundsStoreItem + [TypeConverter(typeof(ExpandableObjectConverter))] public class BoundsStoreItem : IMetaXmlItem { public MetaHash Name { get; set; } public Vector3 Min { get; set; } public Vector3 Max { get; set; } public uint Layer { get; set; } + public BoundsStoreItem() + { } public BoundsStoreItem(Bounds b) { Name = 0; @@ -339,6 +447,29 @@ namespace CodeWalker.GameFiles Layer = br.ReadUInt32(); } + public void Write(DataWriter w) + { + w.Write(Name); + w.Write(Min); + w.Write(Max); + w.Write(Layer); + } + + public void WriteXml(StringBuilder sb, int indent) + { + CacheDatXml.StringTag(sb, indent, "name", CacheDatXml.HashString(Name)); + CacheDatXml.SelfClosingTag(sb, indent, "bbMin " + FloatUtil.GetVector3XmlString(Min)); + CacheDatXml.SelfClosingTag(sb, indent, "bbMax " + FloatUtil.GetVector3XmlString(Max)); + CacheDatXml.ValueTag(sb, indent, "layer", Layer.ToString()); + } + public void ReadXml(XmlNode node) + { + Name = XmlMeta.GetHash(Xml.GetChildInnerText(node, "name")); + Min = Xml.GetChildVector3Attributes(node, "bbMin"); + Max = Xml.GetChildVector3Attributes(node, "bbMax"); + Layer = Xml.GetChildUIntAttribute(node, "layer"); + } + public override string ToString() { return Name.ToString() + ", " + @@ -346,10 +477,9 @@ namespace CodeWalker.GameFiles Max.ToString() + ", " + Layer.ToString(); } - } - [TypeConverter(typeof(ExpandableObjectConverter))] public class CInteriorProxy + [TypeConverter(typeof(ExpandableObjectConverter))] public class CInteriorProxy : IMetaXmlItem { public uint Unk01 { get; set; } public uint Unk02 { get; set; } @@ -360,15 +490,13 @@ namespace CodeWalker.GameFiles public Quaternion Orientation { get; set; } public Vector3 BBMin { get; set; } public Vector3 BBMax { get; set; } - public float Unk11 { get; set; } - public uint Unk12 { get; set; } - public float Unk13 { get; set; } - public uint Unk14 { get; set; } - public float Unk15 { get; set; } - public uint Unk16 { get; set; } - public uint Unk17 { get; set; } - public uint Unk18 { get; set; } + public ulong Unk11 { get; set; }//possibly file offsets..? + public ulong Unk12 { get; set; }//possibly file offsets..? + public ulong Unk13 { get; set; }//possibly file offsets..? + public ulong Unk14 { get; set; }//possibly file offsets..? + public CInteriorProxy() + { } public CInteriorProxy(BinaryReader br) { Unk01 = br.ReadUInt32(); @@ -380,15 +508,10 @@ namespace CodeWalker.GameFiles Orientation = new Quaternion(br.ReadSingle(), br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); BBMin = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); BBMax = new Vector3(br.ReadSingle(), br.ReadSingle(), br.ReadSingle()); - Unk11 = br.ReadSingle(); - Unk12 = br.ReadUInt32(); - Unk13 = br.ReadSingle(); - Unk14 = br.ReadUInt32(); - Unk15 = br.ReadSingle(); - Unk16 = br.ReadUInt32(); - Unk17 = br.ReadUInt32();//could be float - Unk18 = br.ReadUInt32(); - + Unk11 = br.ReadUInt64(); + Unk12 = br.ReadUInt64(); + Unk13 = br.ReadUInt64(); + Unk14 = br.ReadUInt64(); //(unk14-unk13)=~ 5500000 switch (Unk01) @@ -418,6 +541,8 @@ namespace CodeWalker.GameFiles case 12: //ch1_roadsdint_tun1 case 100: //hei_int_mph_carrierhang3 case 47: //xm_x17dlc_int_base_ent + case 120: + case 119: break; default: break; @@ -450,56 +575,140 @@ namespace CodeWalker.GameFiles case 17: //hei_gta_milo_bedrm case 14: //hei_gta_milo_bridge case 48: //apa_mpapa_yacht + case 43: break; default: break; } - - if ((Unk12 == 0) || (Unk12 > 0xFFFFFF)) - { } - + switch (Unk11) + { + case 5390106048: + case 50578352072311817: + case 140699061757388: + case 738537932908210: + case 65651138218412653: + case 19678574933270533: + case 67944777457713148: + case 42661052301639680: + case 64551944402634707: + case 6851324394453320: + case 5376209604: + case 7160325822942775: + case 140695211737544: + case 5379565000: + case 12610731652297560: + case 0: + case 5836226042334228: + break; + default: + break; + } + switch (Unk12) + { + case 5394258664: + case 1788295895209: + case 2301144275160: + case 2301144295745: + case 2301144271926: + case 2293121037876: + case 2301144284982: + case 2301144280511: + case 2301144292239: + case 2301144276247: + case 2297948090320: + case 2301144281267: + case 2301144273909: + case 2301144274429: + case 2301144278131: + case 2301144276931: + case 2301144285912: + case 2301144279392: + case 2301144278900: + case 2301144280746: + case 2301144276750: + case 2301144279385: + case 794564824: + case 794585409: + case 3426812900: + case 3363906997: + case 2488666884898: + case 1551090123535: + case 3581544739: + case 2697016884: + case 2697019190: + case 2697014452: + case 2697013894: + case 2697026447: + case 2697010756: + case 2697012560: + case 2697010345: + case 2697015248: + case 2697009368: + case 2697014442: + case 2697008117: + case 2697008069: + case 2697018851: + case 2697012339: + case 2697010263: + case 2697019078: + case 2697013518: + case 2697013308: + case 2697013108: + case 2079647991056: + case 2333569996536: + case 3433367119: + case 2293344373240: + case 1527735255327: + case 1581974815172: + case 2067312412743: + case 2240565805648: + break; + default: + break; + } + switch (Unk13) + { + case 5416947112: + case 140699301996180: + case 140699066065044: + case 5381321844: + case 5385188756: + case 5385376164: + case 140696605328676: + case 140701349594068: + case 5387902360: + case 5380079992: + case 140695959352556: + case 140695215813968: + case 5383741744: + case 140697989613796: + case 140701810993260: + case 140701892506988: + case 140701188531008: + break; + default: + break; + } switch (Unk14) - { - case 1: - case 0: - case 580: - case 355: //sm_smugdlc_int_01 - case 579: //xm_x17dlc_int_01 - break; - default: - break; - } - switch (Unk16) - { - case 1: - case 32758: //0x7FF6 - break; - default: - break; - } - switch (Unk17) //could be a float..! { case 9: - break; - case 0x415CBC04: //13.7959f - case 0x7B81AC94: - case 0x40FE3224: //7.94362f v_gun - case 0x41515774: //13.0839f v_gun - case 0x414E7B34: //12.9051f bkr_biker_dlc_int_03 - case 0x41389C14: //11.5381f imp_impexp_int_01 - case 0x4177B664: //15.482f gr_grdlc_int_01 - case 0xCE0404F4: // sm_smugdlc_int_01 - break; - default: - //string str = JenkIndex.GetString(Unk17); - break; - } - switch(Unk18) - { - case 0: - case 1: - case 32758: //0x7FF6 + case 140699307584676: + case 140699071655044: + case 5386712196: + case 5390629684: + case 5390817140: + case 140696610778260: + case 140701355067892: + case 5393331812: + case 5385368100: + case 140695964849172: + case 140695221335892: + case 5389196308: + case 140697995052276: + case 140701816510228: + case 140701898076100: + case 140701194017116: break; default: break; @@ -507,6 +716,57 @@ namespace CodeWalker.GameFiles } + public void Write(DataWriter w) + { + w.Write(Unk01); + w.Write(Unk02); + w.Write(Unk03); + w.Write(Name); + w.Write(Parent); + w.Write(Position); + w.Write(Orientation.ToVector4()); + w.Write(BBMin); + w.Write(BBMax); + w.Write(Unk11); + w.Write(Unk12); + w.Write(Unk13); + w.Write(Unk14); + } + + public void WriteXml(StringBuilder sb, int indent) + { + CacheDatXml.StringTag(sb, indent, "name", CacheDatXml.HashString(Name)); + CacheDatXml.StringTag(sb, indent, "parent", CacheDatXml.HashString(Parent)); + CacheDatXml.SelfClosingTag(sb, indent, "position " + FloatUtil.GetVector3XmlString(Position)); + CacheDatXml.SelfClosingTag(sb, indent, "rotation " + FloatUtil.GetVector4XmlString(Orientation.ToVector4())); + CacheDatXml.SelfClosingTag(sb, indent, "bbMin " + FloatUtil.GetVector3XmlString(BBMin)); + CacheDatXml.SelfClosingTag(sb, indent, "bbMax " + FloatUtil.GetVector3XmlString(BBMax)); + CacheDatXml.ValueTag(sb, indent, "unk01", Unk01.ToString()); + CacheDatXml.ValueTag(sb, indent, "unk02", Unk02.ToString()); + CacheDatXml.ValueTag(sb, indent, "unk03", Unk03.ToString()); + CacheDatXml.ValueTag(sb, indent, "unk11", Unk11.ToString()); + CacheDatXml.ValueTag(sb, indent, "unk12", Unk12.ToString()); + CacheDatXml.ValueTag(sb, indent, "unk13", Unk13.ToString()); + CacheDatXml.ValueTag(sb, indent, "unk14", Unk14.ToString()); + } + public void ReadXml(XmlNode node) + { + Name = XmlMeta.GetHash(Xml.GetChildInnerText(node, "name")); + Parent = XmlMeta.GetHash(Xml.GetChildInnerText(node, "parent")); + Position = Xml.GetChildVector3Attributes(node, "position"); + Orientation = Xml.GetChildVector4Attributes(node, "rotation").ToQuaternion(); + BBMin = Xml.GetChildVector3Attributes(node, "bbMin"); + BBMax = Xml.GetChildVector3Attributes(node, "bbMax"); + Unk01 = Xml.GetChildUIntAttribute(node, "unk01"); + Unk02 = Xml.GetChildUIntAttribute(node, "unk02"); + Unk03 = Xml.GetChildUIntAttribute(node, "unk03"); + Unk11 = Xml.GetChildULongAttribute(node, "unk11"); + Unk12 = Xml.GetChildULongAttribute(node, "unk12"); + Unk13 = Xml.GetChildULongAttribute(node, "unk13"); + Unk14 = Xml.GetChildULongAttribute(node, "unk14"); + } + + public override string ToString() { return Unk01.ToString() + ", " + @@ -521,15 +781,11 @@ namespace CodeWalker.GameFiles Unk11.ToString() + ", " + Unk12.ToString() + ", " + Unk13.ToString() + ", " + - Unk14.ToString() + ", " + - Unk15.ToString() + ", " + - Unk16.ToString() + ", " + - Unk17.ToString() + ", " + - Unk18.ToString(); + Unk14.ToString(); } } - [TypeConverter(typeof(ExpandableObjectConverter))] public class MapDataStoreNode + [TypeConverter(typeof(ExpandableObjectConverter))] public class MapDataStoreNode : IMetaXmlItem { public MetaHash Name { get; set; } public MetaHash ParentName { get; set; } @@ -551,6 +807,8 @@ namespace CodeWalker.GameFiles public CInteriorProxy[] InteriorProxies { get; set; } private List InteriorProxyList; + public MapDataStoreNode() + { } public MapDataStoreNode(YmapFile ymap) { Name = ymap._CMapData.name; @@ -584,11 +842,65 @@ namespace CodeWalker.GameFiles if (Unk4 != 0) { } //no hits here now.. - if (Unk4 == 0xFE) - { - //this seems to never be hit anymore... - UnkExtra = new MapDataStoreNodeExtra(br); - } + //if (Unk4 == 0xFE) + //{ + // //this seems to never be hit anymore... + // UnkExtra = new MapDataStoreNodeExtra(br); + //} + } + + public void Write(DataWriter w) + { + w.Write(Name); + w.Write(ParentName); + w.Write(ContentFlags); + w.Write(streamingExtentsMin); + w.Write(streamingExtentsMax); + w.Write(entitiesExtentsMin); + w.Write(entitiesExtentsMax); + w.Write(Unk1); + w.Write(Unk2); + w.Write(Unk3); + w.Write(Unk4); + + //if (Unk4 == 0xFE) + //{ + // if (UnkExtra == null) + // { + // UnkExtra = new MapDataStoreNodeExtra(); + // } + // UnkExtra.Write(w); + //} + } + + + public void WriteXml(StringBuilder sb, int indent) + { + CacheDatXml.StringTag(sb, indent, "name", CacheDatXml.HashString(Name)); + CacheDatXml.StringTag(sb, indent, "parent", CacheDatXml.HashString(ParentName)); + CacheDatXml.ValueTag(sb, indent, "contentFlags", ContentFlags.ToString()); + CacheDatXml.SelfClosingTag(sb, indent, "streamingExtentsMin " + FloatUtil.GetVector3XmlString(streamingExtentsMin)); + CacheDatXml.SelfClosingTag(sb, indent, "streamingExtentsMax " + FloatUtil.GetVector3XmlString(streamingExtentsMax)); + CacheDatXml.SelfClosingTag(sb, indent, "entitiesExtentsMin " + FloatUtil.GetVector3XmlString(entitiesExtentsMin)); + CacheDatXml.SelfClosingTag(sb, indent, "entitiesExtentsMax " + FloatUtil.GetVector3XmlString(entitiesExtentsMax)); + CacheDatXml.ValueTag(sb, indent, "unk1", Unk1.ToString()); + CacheDatXml.ValueTag(sb, indent, "unk2", Unk2.ToString()); + CacheDatXml.ValueTag(sb, indent, "unk3", Unk3.ToString()); + CacheDatXml.ValueTag(sb, indent, "unk4", Unk4.ToString()); + } + public void ReadXml(XmlNode node) + { + Name = XmlMeta.GetHash(Xml.GetChildInnerText(node, "name")); + ParentName = XmlMeta.GetHash(Xml.GetChildInnerText(node, "parent")); + ContentFlags = Xml.GetChildUIntAttribute(node, "contentFlags"); + streamingExtentsMin = Xml.GetChildVector3Attributes(node, "streamingExtentsMin"); + streamingExtentsMax = Xml.GetChildVector3Attributes(node, "streamingExtentsMax"); + entitiesExtentsMin = Xml.GetChildVector3Attributes(node, "entitiesExtentsMin"); + entitiesExtentsMax = Xml.GetChildVector3Attributes(node, "entitiesExtentsMax"); + Unk1 = (byte)Xml.GetChildUIntAttribute(node, "unk1"); + Unk2 = (byte)Xml.GetChildUIntAttribute(node, "unk2"); + Unk3 = (byte)Xml.GetChildUIntAttribute(node, "unk3"); + Unk4 = (byte)Xml.GetChildUIntAttribute(node, "unk4"); } @@ -667,6 +979,8 @@ namespace CodeWalker.GameFiles } } + public MapDataStoreNodeExtra() + { } public MapDataStoreNodeExtra(BinaryReader br) { Unk01 = br.ReadUInt32(); @@ -687,6 +1001,23 @@ namespace CodeWalker.GameFiles } + public void Write(DataWriter w) + { + w.Write(Unk01); + var alen = Unk02?.Length ?? 0; + for (int i = 0; i < 60; i++) + { + w.Write((i < alen) ? Unk02[i] : (byte)0); + } + w.Write(Unk03); + w.Write(Unk04); + w.Write(Unk05); + w.Write(Unk06); + w.Write(Unk07); + w.Write(Unk08); + w.Write(Unk09); + w.Write(Unk10); + } public override string ToString() { @@ -696,4 +1027,50 @@ namespace CodeWalker.GameFiles + public class CacheDatXml : MetaXmlBase + { + + public static string GetXml(CacheDatFile cdf) + { + StringBuilder sb = new StringBuilder(); + sb.AppendLine(XmlHeader); + + if (cdf != null) + { + var name = "CacheFile"; + + OpenTag(sb, 0, name); + + cdf.WriteXml(sb, 1); + + CloseTag(sb, 0, name); + } + + return sb.ToString(); + } + + + } + + + public class XmlCacheDat + { + + public static CacheDatFile GetCacheDat(string xml) + { + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xml); + return GetCacheDat(doc); + } + + public static CacheDatFile GetCacheDat(XmlDocument doc) + { + CacheDatFile cdf = new CacheDatFile(); + cdf.ReadXml(doc.DocumentElement); + return cdf; + } + + + } + } diff --git a/CodeWalker.Core/GameFiles/GameFileCache.cs b/CodeWalker.Core/GameFiles/GameFileCache.cs index 1d33e4c..75132b3 100644 --- a/CodeWalker.Core/GameFiles/GameFileCache.cs +++ b/CodeWalker.Core/GameFiles/GameFileCache.cs @@ -219,6 +219,7 @@ namespace CodeWalker.GameFiles //TestMrfs(); //TestPlacements(); //TestDrawables(); + //TestCacheFiles(); //TestHeightmaps(); //TestWatermaps(); //GetShadersXml(); @@ -4954,6 +4955,49 @@ namespace CodeWalker.GameFiles UpdateStatus((DateTime.Now - starttime).ToString() + " elapsed, " + drawablecount.ToString() + " drawables, " + errs.Count.ToString() + " errors."); } + public void TestCacheFiles() + { + foreach (RpfFile file in AllRpfs) + { + foreach (RpfEntry entry in file.AllEntries) + { + try + { + if (entry.NameLower.EndsWith("cache_y.dat"))// || entry.NameLower.EndsWith("cache_y_bank.dat")) + { + UpdateStatus(string.Format(entry.Path)); + var cdfile = RpfMan.GetFile(entry); + if (cdfile != null) + { + var odata = entry.File.ExtractFile(entry as RpfFileEntry); + //var ndata = cdfile.Save(); + + var xml = CacheDatXml.GetXml(cdfile); + var cdf2 = XmlCacheDat.GetCacheDat(xml); + var ndata = cdf2.Save(); + + if (ndata.Length == odata.Length) + { + for (int i = 0; i < ndata.Length; i++) + { + if (ndata[i] != odata[i]) + { break; } + } + } + else + { } + } + else + { } + } + } + catch (Exception ex) + { + UpdateStatus("Error! " + ex.ToString()); + } + } + } + } public void TestHeightmaps() { var errorfiles = new List(); diff --git a/CodeWalker.Core/GameFiles/MetaTypes/MetaXml.cs b/CodeWalker.Core/GameFiles/MetaTypes/MetaXml.cs index a2ee470..47926c2 100644 --- a/CodeWalker.Core/GameFiles/MetaTypes/MetaXml.cs +++ b/CodeWalker.Core/GameFiles/MetaTypes/MetaXml.cs @@ -284,7 +284,7 @@ namespace CodeWalker.GameFiles { var fn = (cdf?.FileEntry?.Name) ?? ""; filename = fn + ".xml"; - return cdf.GetXml(); + return CacheDatXml.GetXml(cdf); } public static string GetXml(HeightmapFile hmf, out string filename, string outputfolder) { diff --git a/CodeWalker.Core/GameFiles/MetaTypes/XmlMeta.cs b/CodeWalker.Core/GameFiles/MetaTypes/XmlMeta.cs index 8a86b80..ae4cfd4 100644 --- a/CodeWalker.Core/GameFiles/MetaTypes/XmlMeta.cs +++ b/CodeWalker.Core/GameFiles/MetaTypes/XmlMeta.cs @@ -168,7 +168,9 @@ namespace CodeWalker.GameFiles } public static byte[] GetCacheFileData(XmlDocument doc) { - return null; //TODO!!! + var cdf = XmlCacheDat.GetCacheDat(doc); + if (cdf == null) return null; + return cdf.Save(); } public static byte[] GetHeightmapData(XmlDocument doc) { diff --git a/CodeWalker.Core/Utils/Xml.cs b/CodeWalker.Core/Utils/Xml.cs index ca0dbc0..556e81a 100644 --- a/CodeWalker.Core/Utils/Xml.cs +++ b/CodeWalker.Core/Utils/Xml.cs @@ -144,6 +144,22 @@ namespace CodeWalker } return i; } + public static ulong GetChildULongAttribute(XmlNode node, string name, string attribute = "value") + { + if (node == null) return 0; + string val = node.SelectSingleNode(name)?.Attributes[attribute]?.InnerText; + ulong i; + if (val?.StartsWith("0x") ?? false) + { + var subs = val.Substring(2); + i = Convert.ToUInt64(subs, 16); + } + else + { + ulong.TryParse(val, out i); + } + return i; + } public static float GetChildFloatAttribute(XmlNode node, string name, string attribute = "value") { if (node == null) return 0; diff --git a/CodeWalker/Forms/MetaForm.cs b/CodeWalker/Forms/MetaForm.cs index 59e2b2a..2f6a059 100644 --- a/CodeWalker/Forms/MetaForm.cs +++ b/CodeWalker/Forms/MetaForm.cs @@ -349,7 +349,7 @@ namespace CodeWalker.Forms public void LoadMeta(CacheDatFile cachedat) { var fn = ((cachedat?.FileEntry?.Name) ?? "") + ".xml"; - Xml = cachedat.GetXml(); + Xml = MetaXml.GetXml(cachedat, out fn, ""); FileName = fn; RawPropertyGrid.SelectedObject = cachedat; rpfFileEntry = cachedat?.FileEntry;