Support PSO string arrays in XML

This commit is contained in:
dexy 2024-08-07 10:48:13 +10:00
parent a8dc98f87c
commit 0b1c59d993
3 changed files with 104 additions and 6 deletions

View File

@ -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<Array_uint>(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<Array_Structure>(data, eoffset);
arrStrs.SwapEnd();
var strPtrArr = PsoTypes.GetItemArrayRaw<DataBlockPointer>(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<Array_Structure>(data, eoffset);
arrChars.SwapEnd();
var charPtrArr = PsoTypes.GetItemArrayRaw<CharPointer>(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("<Item>");
sb.Append(arr[n]);//TODO: escape this??!
sb.AppendLine("</Item>");
}
CloseTag(sb, ind, name);
}
else
{
SelfClosingTag(sb, ind, arrTag);
}
}
public static string FormatHash(MetaHash h) //for use with WriteItemArray
{

View File

@ -15883,7 +15883,7 @@ namespace CodeWalker.GameFiles
if ((arr.Count1 > 0) && (arr.Pointer > 0))
{
var entry = pso.DataMapSection.Entries[arr.PointerDataIndex];
return ConvertDataArrayRaw<T>(pso.DataSection.Data, entry.Offset, arr.Count1);
return ConvertDataArrayRaw<T>(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<T>(pso.DataSection.Data, entry.Offset, arr.Count1);
var res = ConvertDataArrayRaw<T>(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; }

View File

@ -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<string>();
foreach (XmlNode cnode in node.ChildNodes)
{
items.Add(cnode.InnerText);
}
return items.ToArray();
}