From 0b1c59d993548a5e60bd0edcccc64b591db0e332 Mon Sep 17 00:00:00 2001 From: dexy Date: Wed, 7 Aug 2024 10:48:13 +1000 Subject: [PATCH] Support PSO string arrays in XML --- .../GameFiles/MetaTypes/MetaXml.cs | 53 ++++++++++++++++++- .../GameFiles/MetaTypes/PsoTypes.cs | 8 ++- CodeWalker.Core/GameFiles/MetaTypes/XmlPso.cs | 49 ++++++++++++++++- 3 files changed, 104 insertions(+), 6 deletions(-) diff --git a/CodeWalker.Core/GameFiles/MetaTypes/MetaXml.cs b/CodeWalker.Core/GameFiles/MetaTypes/MetaXml.cs index 87d2c38..e16c2f6 100644 --- a/CodeWalker.Core/GameFiles/MetaTypes/MetaXml.cs +++ b/CodeWalker.Core/GameFiles/MetaTypes/MetaXml.cs @@ -1333,12 +1333,13 @@ namespace CodeWalker.GameFiles } break; case PsoDataType.String: - switch (entry.Unk_5h) + switch (arrEntry.Unk_5h) { default: ErrorXml(sb, indent, ename + ": Unexpected String array subtype: " + entry.Unk_5h.ToString()); break; - case 0: //hash array... + case 7: //hash array... + case 8: if (embedded) { } var arrHash = MetaTypes.ConvertData(data, eoffset); @@ -1346,6 +1347,32 @@ namespace CodeWalker.GameFiles var hashArr = PsoTypes.GetHashArray(cont.Pso, arrHash); WriteItemArray(sb, hashArr, indent, ename, "Hash", HashString); break; + case 2: //string array (array of pointers) + var arrStrs = MetaTypes.ConvertData(data, eoffset); + arrStrs.SwapEnd(); + var strPtrArr = PsoTypes.GetItemArrayRaw(cont.Pso, arrStrs); + var strs = (strPtrArr != null) ? new string[strPtrArr.Length] : null; + var cnt = strPtrArr?.Length ?? 0; + for (int i = 0; i < cnt; i++) + { + strPtrArr[i].SwapEnd(); + strs[i] = PsoTypes.GetString(cont.Pso, strPtrArr[i]); + } + WriteStringItemArray(sb, strs, indent, ename); + break; + case 3: //char array array (array of CharPointer) + var arrChars = MetaTypes.ConvertData(data, eoffset); + arrChars.SwapEnd(); + var charPtrArr = PsoTypes.GetItemArrayRaw(cont.Pso, arrChars);//namehash 200 + var strs2 = (charPtrArr != null) ? new string[charPtrArr.Length] : null; + var cnt2 = charPtrArr?.Length ?? 0; + for (int i = 0; i < cnt2; i++) + { + charPtrArr[i].SwapEnd(); + strs2[i] = PsoTypes.GetString(cont.Pso, charPtrArr[i]); + } + WriteStringItemArray(sb, strs2, indent, ename); + break; } break; case PsoDataType.Float2: @@ -2076,6 +2103,28 @@ namespace CodeWalker.GameFiles SelfClosingTag(sb, ind, name); } } + public static void WriteStringItemArray(StringBuilder sb, string[] arr, int ind, string name) + { + var aCount = arr?.Length ?? 0; + var arrTag = name;// + " itemType=\"Hash\""; + var aind = ind + 1; + if (aCount > 0) + { + OpenTag(sb, ind, arrTag); + for (int n = 0; n < aCount; n++) + { + Indent(sb, aind); + sb.Append(""); + sb.Append(arr[n]);//TODO: escape this??! + sb.AppendLine(""); + } + CloseTag(sb, ind, name); + } + else + { + SelfClosingTag(sb, ind, arrTag); + } + } public static string FormatHash(MetaHash h) //for use with WriteItemArray { diff --git a/CodeWalker.Core/GameFiles/MetaTypes/PsoTypes.cs b/CodeWalker.Core/GameFiles/MetaTypes/PsoTypes.cs index 8ea0cd3..3aff9d4 100644 --- a/CodeWalker.Core/GameFiles/MetaTypes/PsoTypes.cs +++ b/CodeWalker.Core/GameFiles/MetaTypes/PsoTypes.cs @@ -15883,7 +15883,7 @@ namespace CodeWalker.GameFiles if ((arr.Count1 > 0) && (arr.Pointer > 0)) { var entry = pso.DataMapSection.Entries[arr.PointerDataIndex]; - return ConvertDataArrayRaw(pso.DataSection.Data, entry.Offset, arr.Count1); + return ConvertDataArrayRaw(pso.DataSection.Data, entry.Offset + (int)arr.PointerDataOffset, arr.Count1); } return null; } @@ -15892,7 +15892,7 @@ namespace CodeWalker.GameFiles if ((arr.Count1 > 0) && (arr.Pointer > 0)) { var entry = pso.DataMapSection.Entries[arr.PointerDataIndex]; - var res = ConvertDataArrayRaw(pso.DataSection.Data, entry.Offset, arr.Count1); + var res = ConvertDataArrayRaw(pso.DataSection.Data, entry.Offset + (int)arr.PointerDataOffset, arr.Count1); if (res != null) { for (int i = 0; i < res.Length; i++) @@ -16116,6 +16116,10 @@ namespace CodeWalker.GameFiles //{ } var length = ptr.Count1; + if (ptr.Count2 != 0) + { + length = Math.Min(ptr.Count1, ptr.Count2); + } var lastbyte = offset + length; if (lastbyte >= block.Length) { return null; } diff --git a/CodeWalker.Core/GameFiles/MetaTypes/XmlPso.cs b/CodeWalker.Core/GameFiles/MetaTypes/XmlPso.cs index 6ed6e3a..4292761 100644 --- a/CodeWalker.Core/GameFiles/MetaTypes/XmlPso.cs +++ b/CodeWalker.Core/GameFiles/MetaTypes/XmlPso.cs @@ -613,12 +613,13 @@ namespace CodeWalker.GameFiles case PsoDataType.String: { - switch (entry.Unk_5h) + switch (arrEntry.Unk_5h) { default: //ErrorXml(sb, indent, ename + ": Unexpected String array subtype: " + entry.Unk_5h.ToString()); break; - case 0: //hash array... + case 7: //hash array... + case 8: var hashes = TraverseHashArrayRaw(node); if (embedded) { @@ -630,6 +631,39 @@ namespace CodeWalker.GameFiles results.Hashes[offset] = pb.AddHashArrayPtr(hashes); } break; + case 2: //string array (array of pointers) + var strs = TraverseStringArrayRaw(node); + var cnt = strs?.Length ?? 0; + var ptrs = (cnt > 0) ? new DataBlockPointer[strs.Length] : null; + for (int i = 0; i < cnt; i++) + { + var str = strs[i]; + if (string.IsNullOrEmpty(str)) continue; + var bptr = pb.AddString(str); + var ptr = new DataBlockPointer(bptr.BlockID, bptr.Offset); + ptr.SwapEnd(); + ptrs[i] = ptr; + } + var aptr = (cnt > 0) ? pb.AddItemArray((MetaName)MetaTypeName.PsoPOINTER, ptrs) : new PsoBuilderPointer(); + results.Structures[offset] = (cnt > 0) ? new Array_Structure(aptr.Pointer, aptr.Length) : new Array_Structure(); + break; + case 3: //char array array (array of CharPointer) + var strs2 = TraverseStringArrayRaw(node); + var cnt2 = strs2?.Length ?? 0; + var ptrs2 = (cnt2 > 0) ? new CharPointer[strs2.Length] : null; + for (int i = 0; i < cnt2; i++) + { + var str = strs2[i]; + if (string.IsNullOrEmpty(str)) continue; + var bptr = pb.AddString(str); + var ptr = new CharPointer(bptr.Pointer, str.Length); + ptr.Count1 += 1; + ptr.SwapEnd(); + ptrs2[i] = ptr; + } + var aptr2 = (cnt2 > 0) ? pb.AddItemArray((MetaName)200, ptrs2) : new PsoBuilderPointer(); + results.Structures[offset] = (cnt2 > 0) ? new Array_Structure(aptr2.Pointer, aptr2.Length) : new Array_Structure(); + break; } @@ -1039,6 +1073,17 @@ namespace CodeWalker.GameFiles return items.ToArray(); } + private static string[] TraverseStringArrayRaw(XmlNode node) + { + var items = new List(); + + foreach (XmlNode cnode in node.ChildNodes) + { + items.Add(cnode.InnerText); + } + + return items.ToArray(); + }