mirror of
https://mirror.ghproxy.com/https://github.com/dexyfex/CodeWalker
synced 2024-11-29 02:12:54 +08:00
XML to PSO conversion (experimental)
This commit is contained in:
parent
34a29a5faa
commit
7c31cfb6ee
@ -84,9 +84,11 @@
|
|||||||
<Compile Include="GameFiles\MetaTypes\MetaTypes.cs" />
|
<Compile Include="GameFiles\MetaTypes\MetaTypes.cs" />
|
||||||
<Compile Include="GameFiles\MetaTypes\MetaXml.cs" />
|
<Compile Include="GameFiles\MetaTypes\MetaXml.cs" />
|
||||||
<Compile Include="GameFiles\MetaTypes\Pso.cs" />
|
<Compile Include="GameFiles\MetaTypes\Pso.cs" />
|
||||||
|
<Compile Include="GameFiles\MetaTypes\PsoBuilder.cs" />
|
||||||
<Compile Include="GameFiles\MetaTypes\PsoTypes.cs" />
|
<Compile Include="GameFiles\MetaTypes\PsoTypes.cs" />
|
||||||
<Compile Include="GameFiles\MetaTypes\Rbf.cs" />
|
<Compile Include="GameFiles\MetaTypes\Rbf.cs" />
|
||||||
<Compile Include="GameFiles\MetaTypes\XmlMeta.cs" />
|
<Compile Include="GameFiles\MetaTypes\XmlMeta.cs" />
|
||||||
|
<Compile Include="GameFiles\MetaTypes\XmlPso.cs" />
|
||||||
<Compile Include="GameFiles\Resources\Bounds.cs" />
|
<Compile Include="GameFiles\Resources\Bounds.cs" />
|
||||||
<Compile Include="GameFiles\Resources\Clip.cs" />
|
<Compile Include="GameFiles\Resources\Clip.cs" />
|
||||||
<Compile Include="GameFiles\Resources\Drawable.cs" />
|
<Compile Include="GameFiles\Resources\Drawable.cs" />
|
||||||
|
@ -2212,16 +2212,27 @@ namespace CodeWalker.GameFiles
|
|||||||
|
|
||||||
var exceptions = new List<Exception>();
|
var exceptions = new List<Exception>();
|
||||||
var allpsos = new List<string>();
|
var allpsos = new List<string>();
|
||||||
|
var diffpsos = new List<string>();
|
||||||
|
|
||||||
foreach (RpfFile file in AllRpfs)
|
foreach (RpfFile file in AllRpfs)
|
||||||
{
|
{
|
||||||
foreach (RpfEntry entry in file.AllEntries)
|
foreach (RpfEntry entry in file.AllEntries)
|
||||||
{
|
{
|
||||||
|
#if !DEBUG
|
||||||
try
|
try
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
var n = entry.NameLower;
|
var n = entry.NameLower;
|
||||||
|
if (!(n.EndsWith(".pso") ||
|
||||||
|
n.EndsWith(".ymt") ||
|
||||||
|
n.EndsWith(".ymf") ||
|
||||||
|
n.EndsWith(".ymap") ||
|
||||||
|
n.EndsWith(".ytyp") ||
|
||||||
|
n.EndsWith(".cut")))
|
||||||
|
continue; //PSO files seem to only have these extensions
|
||||||
|
|
||||||
var fentry = entry as RpfFileEntry;
|
var fentry = entry as RpfFileEntry;
|
||||||
var data = entry.File.ExtractFile(fentry); //kind of slow, but sure to catch all PSO files
|
var data = entry.File.ExtractFile(fentry);
|
||||||
if (data != null)
|
if (data != null)
|
||||||
{
|
{
|
||||||
using (MemoryStream ms = new MemoryStream(data))
|
using (MemoryStream ms = new MemoryStream(data))
|
||||||
@ -2236,19 +2247,43 @@ namespace CodeWalker.GameFiles
|
|||||||
allpsos.Add(fentry.Path);
|
allpsos.Add(fentry.Path);
|
||||||
|
|
||||||
PsoTypes.EnsurePsoTypes(pso);
|
PsoTypes.EnsurePsoTypes(pso);
|
||||||
|
|
||||||
|
var xml = PsoXml.GetXml(pso);
|
||||||
|
if (!string.IsNullOrEmpty(xml))
|
||||||
|
{ }
|
||||||
|
|
||||||
|
var xdoc = new XmlDocument();
|
||||||
|
xdoc.LoadXml(xml);
|
||||||
|
var pso2 = XmlPso.GetPso(xdoc);
|
||||||
|
var pso2b = pso2.Save();
|
||||||
|
|
||||||
|
var pso3 = new PsoFile();
|
||||||
|
pso3.Load(pso2b);
|
||||||
|
var xml3 = PsoXml.GetXml(pso3);
|
||||||
|
|
||||||
|
if (xml.Length != xml3.Length)
|
||||||
|
{ }
|
||||||
|
if (xml != xml3)
|
||||||
|
{
|
||||||
|
diffpsos.Add(fentry.Path);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#if !DEBUG
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
UpdateStatus("Error! " + ex.ToString());
|
UpdateStatus("Error! " + ex.ToString());
|
||||||
exceptions.Add(ex);
|
exceptions.Add(ex);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
string allpsopaths = string.Join("\r\n", allpsos);
|
string allpsopaths = string.Join("\r\n", allpsos);
|
||||||
|
string diffpsopaths = string.Join("\r\n", diffpsos);
|
||||||
|
|
||||||
string str = PsoTypes.GetTypesInitString();
|
string str = PsoTypes.GetTypesInitString();
|
||||||
if (!string.IsNullOrEmpty(str))
|
if (!string.IsNullOrEmpty(str))
|
||||||
|
@ -621,9 +621,9 @@ namespace CodeWalker.GameFiles
|
|||||||
public ushort Count2 { get; set; }
|
public ushort Count2 { get; set; }
|
||||||
public uint Unk1 { get; set; }
|
public uint Unk1 { get; set; }
|
||||||
|
|
||||||
public uint PointerDataId { get { return (Pointer & 0xFFF); } }
|
public uint PointerDataId { get { return (Pointer & 0xFFF); } set { Pointer = (Pointer & 0xFFFFF000) + (value & 0xFFF); } }
|
||||||
public uint PointerDataIndex { get { return (Pointer & 0xFFF) - 1; } }
|
public uint PointerDataIndex { get { return (Pointer & 0xFFF) - 1; } set { PointerDataId = value + 1; } }
|
||||||
public uint PointerDataOffset { get { return ((Pointer >> 12) & 0xFFFFF); } }
|
public uint PointerDataOffset { get { return ((Pointer >> 12) & 0xFFFFF); } set { Pointer = (Pointer & 0xFFF) + ((value << 12) & 0xFFFFF000); } }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -2007,6 +2007,10 @@ namespace CodeWalker.GameFiles
|
|||||||
{
|
{
|
||||||
return (ushort)(((x & 0xFF00) >> 8) | ((x & 0x00FF) << 8));
|
return (ushort)(((x & 0xFF00) >> 8) | ((x & 0x00FF) << 8));
|
||||||
}
|
}
|
||||||
|
public static short SwapBytes(short x)
|
||||||
|
{
|
||||||
|
return (short)SwapBytes((ushort)x);
|
||||||
|
}
|
||||||
public static uint SwapBytes(uint x)
|
public static uint SwapBytes(uint x)
|
||||||
{
|
{
|
||||||
// swap adjacent 16-bit blocks
|
// swap adjacent 16-bit blocks
|
||||||
|
@ -5,6 +5,7 @@ using System.IO;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using System.Xml;
|
||||||
|
|
||||||
namespace CodeWalker.GameFiles
|
namespace CodeWalker.GameFiles
|
||||||
{
|
{
|
||||||
@ -640,6 +641,10 @@ namespace CodeWalker.GameFiles
|
|||||||
|
|
||||||
var structInfo = cont.GetStructureInfo(structName);
|
var structInfo = cont.GetStructureInfo(structName);
|
||||||
if (structInfo == null)
|
if (structInfo == null)
|
||||||
|
{
|
||||||
|
structInfo = PsoTypes.GetStructureInfo(structName);//fallback to builtin...
|
||||||
|
}
|
||||||
|
if (structInfo == null)
|
||||||
{
|
{
|
||||||
ErrorXml(sb, indent, "Couldn't find structure info " + name + "!");
|
ErrorXml(sb, indent, "Couldn't find structure info " + name + "!");
|
||||||
return;
|
return;
|
||||||
@ -708,7 +713,10 @@ namespace CodeWalker.GameFiles
|
|||||||
case 0: //int enum
|
case 0: //int enum
|
||||||
var intEVal = MetaTypes.SwapBytes(BitConverter.ToInt32(data, eoffset));
|
var intEVal = MetaTypes.SwapBytes(BitConverter.ToInt32(data, eoffset));
|
||||||
var intE = enumInfo.FindEntry(intEVal);
|
var intE = enumInfo.FindEntry(intEVal);
|
||||||
StringTag(sb, cind, ename, HashString(intE?.EntryNameHash ?? 0));
|
var intH = HashString(intE?.EntryNameHash ?? 0);
|
||||||
|
if (string.IsNullOrEmpty(intH))
|
||||||
|
{ }
|
||||||
|
StringTag(sb, cind, ename, intH);
|
||||||
break;
|
break;
|
||||||
case 2: //byte enum
|
case 2: //byte enum
|
||||||
var byteEVal = data[eoffset];
|
var byteEVal = data[eoffset];
|
||||||
@ -718,9 +726,9 @@ namespace CodeWalker.GameFiles
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case PsoDataType.Flags:
|
case PsoDataType.Flags:
|
||||||
uint fCount = (entry.ReferenceKey >> 16) & 0x0000FFFF;
|
//uint fCount = (entry.ReferenceKey >> 16) & 0x0000FFFF;
|
||||||
uint fEntry = (entry.ReferenceKey & 0xFFFF);
|
uint fEntry = (entry.ReferenceKey & 0xFFF);
|
||||||
var fEnt = structInfo.GetEntry((int)fEntry);
|
var fEnt = (fEntry != 0xFFF) ? structInfo.GetEntry((int)fEntry) : null;
|
||||||
PsoEnumInfo flagsInfo = null;
|
PsoEnumInfo flagsInfo = null;
|
||||||
if ((fEnt != null) && (fEnt.EntryNameHash == MetaName.ARRAYINFO))
|
if ((fEnt != null) && (fEnt.EntryNameHash == MetaName.ARRAYINFO))
|
||||||
{
|
{
|
||||||
@ -728,7 +736,9 @@ namespace CodeWalker.GameFiles
|
|||||||
}
|
}
|
||||||
if (flagsInfo == null)
|
if (flagsInfo == null)
|
||||||
{
|
{
|
||||||
flagsInfo = cont.GetEnumInfo(entry.EntryNameHash);
|
if (fEntry != 0xFFF)
|
||||||
|
{ }
|
||||||
|
//flagsInfo = cont.GetEnumInfo(entry.EntryNameHash);
|
||||||
}
|
}
|
||||||
uint? flagsVal = null;
|
uint? flagsVal = null;
|
||||||
switch (entry.Unk_5h)
|
switch (entry.Unk_5h)
|
||||||
@ -805,13 +815,14 @@ namespace CodeWalker.GameFiles
|
|||||||
default:
|
default:
|
||||||
ErrorXml(sb, cind, ename + ": Unexpected Integer subtype: " + entry.Unk_5h.ToString());
|
ErrorXml(sb, cind, ename + ": Unexpected Integer subtype: " + entry.Unk_5h.ToString());
|
||||||
break;
|
break;
|
||||||
case 0: //signed int
|
case 0: //signed int (? flags?)
|
||||||
var int6aVal = MetaTypes.SwapBytes(BitConverter.ToInt32(data, eoffset));
|
var int6aVal = MetaTypes.SwapBytes(BitConverter.ToInt32(data, eoffset));
|
||||||
ValueTag(sb, cind, ename, int6aVal.ToString());
|
ValueTag(sb, cind, ename, int6aVal.ToString());
|
||||||
break;
|
break;
|
||||||
case 1: //unsigned int
|
case 1: //unsigned int
|
||||||
var int6bVal = MetaTypes.SwapBytes(BitConverter.ToUInt32(data, eoffset));
|
var int6bVal = MetaTypes.SwapBytes(BitConverter.ToUInt32(data, eoffset));
|
||||||
ValueTag(sb, cind, ename, "0x" + int6bVal.ToString("X").PadLeft(8, '0'));
|
ValueTag(sb, cind, ename, int6bVal.ToString());
|
||||||
|
//ValueTag(sb, cind, ename, "0x" + int6bVal.ToString("X").PadLeft(8, '0'));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -833,16 +844,16 @@ namespace CodeWalker.GameFiles
|
|||||||
ValueTag(sb, cind, ename, short4Val.ToString());
|
ValueTag(sb, cind, ename, short4Val.ToString());
|
||||||
break;
|
break;
|
||||||
case PsoDataType.HFloat://half float?
|
case PsoDataType.HFloat://half float?
|
||||||
var short1EVal = MetaTypes.SwapBytes(BitConverter.ToUInt16(data, eoffset));
|
var short1EVal = MetaTypes.SwapBytes(BitConverter.ToInt16(data, eoffset));
|
||||||
ValueTag(sb, cind, ename, short1EVal.ToString());
|
ValueTag(sb, cind, ename, short1EVal.ToString());
|
||||||
break;
|
break;
|
||||||
case PsoDataType.String:
|
case PsoDataType.String:
|
||||||
var str0 = GetStringValue(cont.Pso, entry, data, eoffset);
|
var str0 = XmlEscape(GetStringValue(cont.Pso, entry, data, eoffset));
|
||||||
if (str0 == null)
|
//if (str0 == null)
|
||||||
{
|
//{
|
||||||
ErrorXml(sb, cind, ename + ": Unexpected String subtype: " + entry.Unk_5h.ToString());
|
// ErrorXml(sb, cind, ename + ": Unexpected String subtype: " + entry.Unk_5h.ToString());
|
||||||
}
|
//}
|
||||||
else
|
//else
|
||||||
{
|
{
|
||||||
StringTag(sb, cind, ename, str0);
|
StringTag(sb, cind, ename, str0);
|
||||||
}
|
}
|
||||||
@ -909,8 +920,13 @@ namespace CodeWalker.GameFiles
|
|||||||
var boffset = offset + block.Offset;
|
var boffset = offset + block.Offset;
|
||||||
var eoffset = boffset + entry.DataOffset;
|
var eoffset = boffset + entry.DataOffset;
|
||||||
var aOffset = offset + entry.DataOffset;
|
var aOffset = offset + entry.DataOffset;
|
||||||
|
var abOffset = aOffset + block.Offset;
|
||||||
var aBlockId = blockId;
|
var aBlockId = blockId;
|
||||||
uint aCount = (entry.ReferenceKey >> 16) & 0x0000FFFF;
|
uint aCount = (entry.ReferenceKey >> 16) & 0x0000FFFF;
|
||||||
|
Array_Structure arrStruc = new Array_Structure();
|
||||||
|
arrStruc.PointerDataId = (uint)aBlockId;
|
||||||
|
arrStruc.PointerDataOffset = (uint)aOffset;
|
||||||
|
arrStruc.Count1 = arrStruc.Count2 = (ushort)aCount;
|
||||||
var aind = indent + 1;
|
var aind = indent + 1;
|
||||||
string arrTag = ename;
|
string arrTag = ename;
|
||||||
PsoStructureEntryInfo arrEntry = estruct.GetEntry((int)(entry.ReferenceKey & 0xFFFF));
|
PsoStructureEntryInfo arrEntry = estruct.GetEntry((int)(entry.ReferenceKey & 0xFFFF));
|
||||||
@ -922,17 +938,24 @@ namespace CodeWalker.GameFiles
|
|||||||
|
|
||||||
var data = cont.Pso.DataSection.Data;
|
var data = cont.Pso.DataSection.Data;
|
||||||
|
|
||||||
|
bool embedded = true;
|
||||||
switch (entry.Unk_5h)
|
switch (entry.Unk_5h)
|
||||||
{
|
{
|
||||||
default:
|
default:
|
||||||
ErrorXml(sb, indent, ename + ": WIP! Unsupported Array subtype: " + entry.Unk_5h.ToString());
|
ErrorXml(sb, indent, ename + ": WIP! Unsupported Array subtype: " + entry.Unk_5h.ToString());
|
||||||
break;
|
break;
|
||||||
case 0: //Array_Structure
|
case 0: //Array_Structure
|
||||||
var arrStruc = MetaTypes.ConvertData<Array_Structure>(data, eoffset);
|
arrStruc = MetaTypes.ConvertData<Array_Structure>(data, eoffset);
|
||||||
arrStruc.SwapEnd();
|
arrStruc.SwapEnd();
|
||||||
aBlockId = (int)arrStruc.PointerDataId;
|
aBlockId = (int)arrStruc.PointerDataId;
|
||||||
aOffset = (int)arrStruc.PointerDataOffset;
|
aOffset = (int)arrStruc.PointerDataOffset;
|
||||||
aCount = arrStruc.Count1;
|
aCount = arrStruc.Count1;
|
||||||
|
var aBlock = cont.Pso.GetBlock(aBlockId);
|
||||||
|
if (aBlock != null)
|
||||||
|
{
|
||||||
|
abOffset = aOffset + aBlock.Offset;
|
||||||
|
}
|
||||||
|
embedded = false;
|
||||||
break;
|
break;
|
||||||
case 1: //Raw in-line array
|
case 1: //Raw in-line array
|
||||||
break;
|
break;
|
||||||
@ -941,11 +964,20 @@ namespace CodeWalker.GameFiles
|
|||||||
case 4: //pointer array? default array?
|
case 4: //pointer array? default array?
|
||||||
if (arrEntry.Unk_5h == 3) //pointers...
|
if (arrEntry.Unk_5h == 3) //pointers...
|
||||||
{
|
{
|
||||||
var arrStruc4 = MetaTypes.ConvertData<Array_Structure>(data, eoffset);
|
arrStruc = MetaTypes.ConvertData<Array_Structure>(data, eoffset);
|
||||||
arrStruc4.SwapEnd();
|
arrStruc.SwapEnd();
|
||||||
aBlockId = (int)arrStruc4.PointerDataId;
|
aBlockId = (int)arrStruc.PointerDataId;
|
||||||
aOffset = (int)arrStruc4.PointerDataOffset;
|
aOffset = (int)arrStruc.PointerDataOffset;
|
||||||
aCount = arrStruc4.Count1;
|
aCount = arrStruc.Count1;
|
||||||
|
var aBlock2 = cont.Pso.GetBlock(aBlockId);
|
||||||
|
if (aBlock2 != null)
|
||||||
|
{
|
||||||
|
abOffset = aOffset + aBlock2.Offset;
|
||||||
|
}
|
||||||
|
embedded = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 129: //also raw inline array? in junctions.pso
|
case 129: //also raw inline array? in junctions.pso
|
||||||
@ -959,10 +991,11 @@ namespace CodeWalker.GameFiles
|
|||||||
break;
|
break;
|
||||||
case PsoDataType.Array:
|
case PsoDataType.Array:
|
||||||
var rk0 = (entry.ReferenceKey >> 16) & 0x0000FFFF;
|
var rk0 = (entry.ReferenceKey >> 16) & 0x0000FFFF;
|
||||||
|
//var rk1 = entry.ReferenceKey & 0x0000FFFF;
|
||||||
|
//var rk3 = (arrEntry.ReferenceKey >> 16) & 0x0000FFFF;
|
||||||
|
//var rk4 = arrEntry.ReferenceKey & 0x0000FFFF;
|
||||||
if (rk0 > 0)
|
if (rk0 > 0)
|
||||||
{
|
{
|
||||||
//var arrStruc5 = MetaTypes.ConvertDataArray<Array_StructurePointer>(data, eoffset, (int)rk0);
|
|
||||||
//for (int n = 0; n < rk0; n++) arrStruc5[n].SwapEnd();
|
|
||||||
aOffset = offset + entry.DataOffset;
|
aOffset = offset + entry.DataOffset;
|
||||||
|
|
||||||
OpenTag(sb, indent, arrTag);
|
OpenTag(sb, indent, arrTag);
|
||||||
@ -997,7 +1030,14 @@ namespace CodeWalker.GameFiles
|
|||||||
for (int n = 0; n < aCount; n++)
|
for (int n = 0; n < aCount; n++)
|
||||||
{
|
{
|
||||||
var ptrVal = ptrArr[n];
|
var ptrVal = ptrArr[n];
|
||||||
WriteNode(sb, aind, cont, ptrVal.BlockID, (int)ptrVal.ItemOffset, XmlTagMode.ItemAndType);
|
if (ptrVal.Pointer == 0)
|
||||||
|
{
|
||||||
|
SelfClosingTag(sb, aind, "Item"); //"null" entry...
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
WriteNode(sb, aind, cont, ptrVal.BlockID, (int)ptrVal.ItemOffset, XmlTagMode.ItemAndType);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
CloseTag(sb, indent, ename);
|
CloseTag(sb, indent, ename);
|
||||||
}
|
}
|
||||||
@ -1050,6 +1090,8 @@ namespace CodeWalker.GameFiles
|
|||||||
ErrorXml(sb, indent, ename + ": Unexpected String array subtype: " + entry.Unk_5h.ToString());
|
ErrorXml(sb, indent, ename + ": Unexpected String array subtype: " + entry.Unk_5h.ToString());
|
||||||
break;
|
break;
|
||||||
case 0: //hash array...
|
case 0: //hash array...
|
||||||
|
if (embedded)
|
||||||
|
{ }
|
||||||
var arrHash = MetaTypes.ConvertData<Array_uint>(data, eoffset);
|
var arrHash = MetaTypes.ConvertData<Array_uint>(data, eoffset);
|
||||||
arrHash.SwapEnd();
|
arrHash.SwapEnd();
|
||||||
var hashArr = PsoTypes.GetHashArray(cont.Pso, arrHash);
|
var hashArr = PsoTypes.GetHashArray(cont.Pso, arrHash);
|
||||||
@ -1064,54 +1106,70 @@ namespace CodeWalker.GameFiles
|
|||||||
WriteRawArray(sb, v2Arr, indent, ename, "Vector2", FormatVector2Swap, 1);
|
WriteRawArray(sb, v2Arr, indent, ename, "Vector2", FormatVector2Swap, 1);
|
||||||
break;
|
break;
|
||||||
case PsoDataType.Float3:
|
case PsoDataType.Float3:
|
||||||
aCount = (entry.ReferenceKey >> 16) & 0x0000FFFF;
|
if (!embedded)
|
||||||
|
{ }
|
||||||
arrTag += " itemType=\"Vector3\""; //this is actually aligned as vector4, the W values are crazy in places
|
arrTag += " itemType=\"Vector3\""; //this is actually aligned as vector4, the W values are crazy in places
|
||||||
var v4Arr = MetaTypes.ConvertDataArray<Vector4>(data, eoffset, (int)aCount);
|
var v4Arr = MetaTypes.ConvertDataArray<Vector4>(data, eoffset, (int)aCount);
|
||||||
WriteRawArray(sb, v4Arr, indent, ename, "Vector3", FormatVector4SwapXYZOnly, 1);
|
WriteRawArray(sb, v4Arr, indent, ename, "Vector3", FormatVector4SwapXYZOnly, 1);
|
||||||
break;
|
break;
|
||||||
case PsoDataType.UByte:
|
case PsoDataType.UByte:
|
||||||
|
if (embedded)
|
||||||
|
{ }
|
||||||
|
else
|
||||||
|
{ } //block type 2
|
||||||
var barr = new byte[aCount];
|
var barr = new byte[aCount];
|
||||||
if (aCount > 0)
|
if (aCount > 0)
|
||||||
{
|
{
|
||||||
var bblock = cont.Pso.GetBlock(aBlockId);
|
//var bblock = cont.Pso.GetBlock(aBlockId);
|
||||||
var boffs = bblock.Offset + aOffset;
|
//var boffs = bblock.Offset + aOffset;
|
||||||
Buffer.BlockCopy(data, boffs, barr, 0, (int)aCount);
|
Buffer.BlockCopy(data, abOffset /*boffs*/, barr, 0, (int)aCount);
|
||||||
}
|
}
|
||||||
WriteRawArray(sb, barr, indent, ename, "byte");
|
WriteRawArray(sb, barr, indent, ename, "byte");
|
||||||
break;
|
break;
|
||||||
case PsoDataType.Bool:
|
case PsoDataType.Bool:
|
||||||
|
if (embedded)
|
||||||
|
{ }
|
||||||
|
else
|
||||||
|
{ }
|
||||||
var barr2 = new byte[aCount];
|
var barr2 = new byte[aCount];
|
||||||
if (aCount > 0)
|
if (aCount > 0)
|
||||||
{
|
{
|
||||||
var bblock = cont.Pso.GetBlock(aBlockId);
|
//var bblock = cont.Pso.GetBlock(aBlockId);
|
||||||
var boffs = bblock.Offset + aOffset;
|
//var boffs = bblock.Offset + aOffset;
|
||||||
Buffer.BlockCopy(data, boffs, barr2, 0, (int)aCount);
|
Buffer.BlockCopy(data, abOffset /*boffs*/, barr2, 0, (int)aCount);
|
||||||
}
|
}
|
||||||
WriteRawArray(sb, barr2, indent, ename, "boolean"); //todo: true/false output
|
WriteRawArray(sb, barr2, indent, ename, "boolean"); //todo: true/false output
|
||||||
break;
|
break;
|
||||||
case PsoDataType.Float:
|
case PsoDataType.Float:
|
||||||
var arrFloat = MetaTypes.ConvertData<Array_float>(data, eoffset);
|
if (embedded)
|
||||||
arrFloat.SwapEnd();
|
{ }
|
||||||
|
var arrFloat = new Array_float(arrStruc.Pointer, arrStruc.Count1); //block type 7
|
||||||
var floatArr = PsoTypes.GetFloatArray(cont.Pso, arrFloat);
|
var floatArr = PsoTypes.GetFloatArray(cont.Pso, arrFloat);
|
||||||
WriteRawArray(sb, floatArr, indent, ename, "float");
|
WriteRawArray(sb, floatArr, indent, ename, "float");
|
||||||
break;
|
break;
|
||||||
case PsoDataType.UShort:
|
case PsoDataType.UShort:
|
||||||
var arrShort = MetaTypes.ConvertData<Array_Structure>(data, eoffset);
|
if (embedded)
|
||||||
arrShort.SwapEnd();
|
{ }
|
||||||
var shortArr = PsoTypes.GetUShortArray(cont.Pso, arrShort);
|
var shortArr = PsoTypes.GetUShortArray(cont.Pso, arrStruc); //block type 4
|
||||||
WriteRawArray(sb, shortArr, indent, ename, "ushort");
|
WriteRawArray(sb, shortArr, indent, ename, "ushort");
|
||||||
break;
|
break;
|
||||||
case PsoDataType.UInt:
|
case PsoDataType.UInt:
|
||||||
var intArr = MetaTypes.ConvertDataArray<int>(data, eoffset, (int)aCount);
|
if (embedded)
|
||||||
|
{ }
|
||||||
|
var arrUint = new Array_uint(arrStruc.Pointer, arrStruc.Count1); //block type 6
|
||||||
|
var intArr = PsoTypes.GetUintArray(cont.Pso, arrUint);
|
||||||
WriteRawArray(sb, intArr, indent, ename, "int");
|
WriteRawArray(sb, intArr, indent, ename, "int");
|
||||||
break;
|
break;
|
||||||
case PsoDataType.SInt:
|
case PsoDataType.SInt:
|
||||||
var arrUint2 = MetaTypes.ConvertData<Array_uint>(data, eoffset);
|
if (embedded)
|
||||||
arrUint2.SwapEnd();
|
{ }
|
||||||
|
var arrUint2 = new Array_uint(arrStruc.Pointer, arrStruc.Count1); //block type 5
|
||||||
var intArr2 = PsoTypes.GetUintArray(cont.Pso, arrUint2);
|
var intArr2 = PsoTypes.GetUintArray(cont.Pso, arrUint2);
|
||||||
WriteRawArray(sb, intArr2, indent, ename, "int");
|
WriteRawArray(sb, intArr2, indent, ename, "int");
|
||||||
break;
|
break;
|
||||||
case PsoDataType.Enum:
|
case PsoDataType.Enum:
|
||||||
|
if (embedded)
|
||||||
|
{ }
|
||||||
var arrEnum = MetaTypes.ConvertData<Array_uint>(data, eoffset);
|
var arrEnum = MetaTypes.ConvertData<Array_uint>(data, eoffset);
|
||||||
arrEnum.SwapEnd();
|
arrEnum.SwapEnd();
|
||||||
var enumArr = PsoTypes.GetUintArray(cont.Pso, arrEnum);
|
var enumArr = PsoTypes.GetUintArray(cont.Pso, arrEnum);
|
||||||
@ -1139,41 +1197,23 @@ namespace CodeWalker.GameFiles
|
|||||||
var mapidx2 = (entry.ReferenceKey >> 16) & 0x0000FFFF;
|
var mapidx2 = (entry.ReferenceKey >> 16) & 0x0000FFFF;
|
||||||
var mapreftype1 = structInfo.Entries[mapidx2];
|
var mapreftype1 = structInfo.Entries[mapidx2];
|
||||||
var mapreftype2 = structInfo.Entries[mapidx1];
|
var mapreftype2 = structInfo.Entries[mapidx1];
|
||||||
var x1 = MetaTypes.SwapBytes(BitConverter.ToInt32(data, eoffset));//same as ref key?
|
var x1 = MetaTypes.SwapBytes(BitConverter.ToInt32(data, eoffset));
|
||||||
var x2 = MetaTypes.SwapBytes(BitConverter.ToInt32(data, eoffset + 4));//0?
|
var x2 = MetaTypes.SwapBytes(BitConverter.ToInt32(data, eoffset + 4));
|
||||||
var x3 = MetaTypes.SwapBytes(BitConverter.ToInt32(data, eoffset + 8));//pointer?
|
var sptr = MetaTypes.ConvertData<Array_Structure>(data, eoffset + 8);
|
||||||
var x4 = MetaTypes.SwapBytes(BitConverter.ToInt32(data, eoffset + 12));//
|
sptr.SwapEnd();
|
||||||
var x5 = MetaTypes.SwapBytes(BitConverter.ToInt32(data, eoffset + 16));//count/capacity?
|
|
||||||
var x6 = MetaTypes.SwapBytes(BitConverter.ToInt32(data, eoffset + 20));//
|
|
||||||
|
|
||||||
//File.WriteAllText("C:\\CodeWalker.Projects\\testxml.xml", sb.ToString());
|
|
||||||
|
|
||||||
if (x1 != 0x1000000)
|
if (x1 != 0x1000000)
|
||||||
{ }
|
{ }
|
||||||
if (x2 != 0)
|
if (x2 != 0)
|
||||||
{ }
|
{ }
|
||||||
if (x4 != 0)
|
if (mapreftype2.ReferenceKey != 0)
|
||||||
{ }
|
|
||||||
if (x6 != 0)
|
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
var xBlockId = (int)sptr.PointerDataId;// x3 & 0xFFF;
|
||||||
var xBlockId = x3 & 0xFFF;
|
var xOffset = sptr.PointerDataOffset;// (x3 >> 12) & 0xFFFFF;
|
||||||
var xOffset = (x3 >> 12) & 0xFFFFF;
|
var xCount1 = sptr.Count1;// x5 & 0xFFFF;
|
||||||
var xCount1 = x5 & 0xFFFF;
|
var xCount2 = sptr.Count2;// (x5 >> 16) & 0xFFFF;
|
||||||
var xCount2 = (x5 >> 16) & 0xFFFF;
|
|
||||||
|
|
||||||
//var x1a = x1 & 0xFFF; //block id? for another pointer?
|
|
||||||
//var x1b = (x1 >> 12) & 0xFFFFF; //offset?
|
|
||||||
//var x4u = (uint)x4;
|
|
||||||
//var x4a = x4 & 0xFFF; //block id?
|
|
||||||
//var x4b = (x4 >> 12) & 0xFFFFF; //offset?
|
|
||||||
//var x2h = (MetaHash)(uint)x2;
|
|
||||||
//var x6h = (MetaHash)(uint)x6;
|
|
||||||
//if (x1a > 0)
|
|
||||||
//{ }
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var xBlock = cont.Pso.GetBlock(xBlockId);
|
var xBlock = cont.Pso.GetBlock(xBlockId);
|
||||||
if ((xBlock == null) && (xCount1 > 0))
|
if ((xBlock == null) && (xCount1 > 0))
|
||||||
@ -1183,8 +1223,7 @@ namespace CodeWalker.GameFiles
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (xCount1 != xCount2)
|
if (xCount1 != xCount2)
|
||||||
{
|
{ }
|
||||||
}
|
|
||||||
if (xCount1 > 0)
|
if (xCount1 > 0)
|
||||||
{
|
{
|
||||||
var xStruct = cont.GetStructureInfo(xBlock.NameHash);
|
var xStruct = cont.GetStructureInfo(xBlock.NameHash);
|
||||||
@ -1218,10 +1257,10 @@ namespace CodeWalker.GameFiles
|
|||||||
{
|
{
|
||||||
ErrorXml(sb, aind, ename + ": Map Item was not a structure!");
|
ErrorXml(sb, aind, ename + ": Map Item was not a structure!");
|
||||||
}
|
}
|
||||||
else if (iEntry.Unk_5h != 3)
|
//else if (iEntry.Unk_5h != 3)
|
||||||
{
|
//{
|
||||||
ErrorXml(sb, aind, ename + ": Map Item was not a structure pointer - TODO!");
|
// ErrorXml(sb, aind, ename + ": Map Item was not a structure pointer - TODO!");
|
||||||
}
|
//}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
OpenTag(sb, xind, ename);
|
OpenTag(sb, xind, ename);
|
||||||
@ -1236,30 +1275,39 @@ namespace CodeWalker.GameFiles
|
|||||||
var kOffset = sOffset + kEntry.DataOffset;
|
var kOffset = sOffset + kEntry.DataOffset;
|
||||||
var iOffset = sOffset + iEntry.DataOffset;
|
var iOffset = sOffset + iEntry.DataOffset;
|
||||||
var kStr = GetStringValue(cont.Pso, kEntry, data, kOffset);
|
var kStr = GetStringValue(cont.Pso, kEntry, data, kOffset);
|
||||||
var iPtr = MetaTypes.ConvertData<PsoPOINTER>(data, iOffset);
|
if (iEntry.ReferenceKey != 0)//(xBlock.NameHash != MetaName.ARRAYINFO)//257,258,259
|
||||||
iPtr.SwapEnd();
|
|
||||||
var iBlock = cont.Pso.GetBlock(iPtr.BlockID);
|
|
||||||
if (iBlock == null)
|
|
||||||
{
|
{
|
||||||
OpenTag(sb, aind, "Item type=\"" + HashString((MetaName)entry.ReferenceKey) + "\" key=\"" + kStr + "\"");
|
//embedded map values
|
||||||
WriteNode(sb, aind, cont, iPtr.BlockID, (int)iPtr.ItemOffset, XmlTagMode.None, (MetaName)entry.ReferenceKey);
|
var vOffset = xOffset2 + iEntry.DataOffset;
|
||||||
|
OpenTag(sb, aind, "Item type=\"" + HashString((MetaName)iEntry.ReferenceKey) + "\" key=\"" + kStr + "\"");
|
||||||
|
WriteNode(sb, aind, cont, xBlockId, vOffset, XmlTagMode.None, (MetaName)iEntry.ReferenceKey);
|
||||||
CloseTag(sb, aind, "Item");
|
CloseTag(sb, aind, "Item");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var iStr = "Item type=\"" + HashString(iBlock.NameHash) + "\" key=\"" + kStr + "\"";
|
var iPtr = MetaTypes.ConvertData<PsoPOINTER>(data, iOffset);
|
||||||
var iStruc = cont.GetStructureInfo(iBlock.NameHash);
|
iPtr.SwapEnd();
|
||||||
if (iStruc?.EntriesCount == 0)
|
var iBlock = cont.Pso.GetBlock(iPtr.BlockID);
|
||||||
|
if (iBlock == null)
|
||||||
{
|
{
|
||||||
//SelfClosingTag(sb, aind, iStr);
|
ErrorXml(sb, aind, ename + ": Could not find iBlock for Map entry!");
|
||||||
OpenTag(sb, aind, iStr);
|
|
||||||
CloseTag(sb, aind, "Item");
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
OpenTag(sb, aind, iStr);
|
var iStr = "Item type=\"" + HashString(iBlock.NameHash) + "\" key=\"" + kStr + "\"";
|
||||||
WriteNode(sb, aind, cont, iPtr.BlockID, (int)iPtr.ItemOffset, XmlTagMode.None);//, (MetaName)entry.ReferenceKey);
|
var iStruc = cont.GetStructureInfo(iBlock.NameHash);
|
||||||
CloseTag(sb, aind, "Item");
|
if (iStruc?.EntriesCount == 0)
|
||||||
|
{
|
||||||
|
//SelfClosingTag(sb, aind, iStr);
|
||||||
|
OpenTag(sb, aind, iStr);
|
||||||
|
CloseTag(sb, aind, "Item");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
OpenTag(sb, aind, iStr);
|
||||||
|
WriteNode(sb, aind, cont, iPtr.BlockID, (int)iPtr.ItemOffset, XmlTagMode.None);//, (MetaName)entry.ReferenceKey);
|
||||||
|
CloseTag(sb, aind, "Item");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
xOffset2 += xStruct.StructureLength;
|
xOffset2 += xStruct.StructureLength;
|
||||||
@ -1311,7 +1359,17 @@ namespace CodeWalker.GameFiles
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static string XmlEscape(string unescaped)
|
||||||
|
{
|
||||||
|
if (unescaped == null) return null;
|
||||||
|
XmlDocument doc = new XmlDocument();
|
||||||
|
XmlNode node = doc.CreateElement("root");
|
||||||
|
node.InnerText = unescaped;
|
||||||
|
var escaped = node.InnerXml;
|
||||||
|
if (escaped != unescaped)
|
||||||
|
{ }
|
||||||
|
return node.InnerXml;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public class PsoCont
|
public class PsoCont
|
||||||
|
@ -205,6 +205,13 @@ namespace CodeWalker.GameFiles
|
|||||||
public PsoSTRESection STRESection { get; set; }
|
public PsoSTRESection STRESection { get; set; }
|
||||||
public PsoCHKSSection CHKSSection { get; set; }
|
public PsoCHKSSection CHKSSection { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
public void Load(byte[] data)
|
||||||
|
{
|
||||||
|
using (var ms = new MemoryStream(data))
|
||||||
|
Load(ms);
|
||||||
|
}
|
||||||
|
|
||||||
public void Load(string fileName)
|
public void Load(string fileName)
|
||||||
{
|
{
|
||||||
using (var stream = new FileStream(fileName, FileMode.Open))
|
using (var stream = new FileStream(fileName, FileMode.Open))
|
||||||
@ -268,6 +275,19 @@ namespace CodeWalker.GameFiles
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public byte[] Save()
|
||||||
|
{
|
||||||
|
var ms = new MemoryStream();
|
||||||
|
Save(ms);
|
||||||
|
|
||||||
|
var buf = new byte[ms.Length];
|
||||||
|
ms.Position = 0;
|
||||||
|
ms.Read(buf, 0, buf.Length);
|
||||||
|
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
public void Save(string fileName)
|
public void Save(string fileName)
|
||||||
{
|
{
|
||||||
using (var stream = new FileStream(fileName, FileMode.Create))
|
using (var stream = new FileStream(fileName, FileMode.Create))
|
||||||
@ -280,6 +300,11 @@ namespace CodeWalker.GameFiles
|
|||||||
if (DataSection != null) DataSection.Write(writer);
|
if (DataSection != null) DataSection.Write(writer);
|
||||||
if (DataMapSection != null) DataMapSection.Write(writer);
|
if (DataMapSection != null) DataMapSection.Write(writer);
|
||||||
if (SchemaSection != null) SchemaSection.Write(writer);
|
if (SchemaSection != null) SchemaSection.Write(writer);
|
||||||
|
if (STRFSection != null) STRFSection.Write(writer);
|
||||||
|
if (STRSSection != null) STRSSection.Write(writer);
|
||||||
|
if (STRESection != null) STRESection.Write(writer);
|
||||||
|
if (PSIGSection != null) PSIGSection.Write(writer);
|
||||||
|
if (CHKSSection != null) CHKSSection.Write(writer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -342,11 +367,13 @@ namespace CodeWalker.GameFiles
|
|||||||
|
|
||||||
public void Write(DataWriter writer)
|
public void Write(DataWriter writer)
|
||||||
{
|
{
|
||||||
|
Length = Data.Length;
|
||||||
|
|
||||||
writer.Write(Data);
|
writer.Write(Data);
|
||||||
writer.Position -= Data.Length;
|
writer.Position -= Length;
|
||||||
writer.Write((uint)0x5053494E);
|
writer.Write(Ident);
|
||||||
writer.Write((uint)(Data.Length));
|
writer.Write((uint)(Length));
|
||||||
writer.Position += Data.Length - 8;
|
writer.Position += Length - 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
@ -413,10 +440,10 @@ namespace CodeWalker.GameFiles
|
|||||||
|
|
||||||
public void Read(DataReader reader)
|
public void Read(DataReader reader)
|
||||||
{
|
{
|
||||||
this.NameHash = (MetaName)reader.ReadUInt32();
|
NameHash = (MetaName)reader.ReadUInt32();
|
||||||
this.Offset = reader.ReadInt32();
|
Offset = reader.ReadInt32();
|
||||||
this.Unknown_8h = reader.ReadInt32();
|
Unknown_8h = reader.ReadInt32();
|
||||||
this.Length = reader.ReadInt32();
|
Length = reader.ReadInt32();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Write(DataWriter writer)
|
public void Write(DataWriter writer)
|
||||||
@ -449,7 +476,7 @@ namespace CodeWalker.GameFiles
|
|||||||
Length = reader.ReadInt32();
|
Length = reader.ReadInt32();
|
||||||
Count = reader.ReadUInt32();
|
Count = reader.ReadUInt32();
|
||||||
|
|
||||||
this.EntriesIdx = new PsoElementIndexInfo[Count];
|
EntriesIdx = new PsoElementIndexInfo[Count];
|
||||||
for (int i = 0; i < Count; i++)
|
for (int i = 0; i < Count; i++)
|
||||||
{
|
{
|
||||||
var entry = new PsoElementIndexInfo();
|
var entry = new PsoElementIndexInfo();
|
||||||
@ -457,7 +484,7 @@ namespace CodeWalker.GameFiles
|
|||||||
EntriesIdx[i] = entry;
|
EntriesIdx[i] = entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.Entries = new PsoElementInfo[Count];
|
Entries = new PsoElementInfo[Count];
|
||||||
for (int i = 0; i < Count; i++)
|
for (int i = 0; i < Count; i++)
|
||||||
{
|
{
|
||||||
reader.Position = EntriesIdx[i].Offset;
|
reader.Position = EntriesIdx[i].Offset;
|
||||||
@ -506,7 +533,7 @@ namespace CodeWalker.GameFiles
|
|||||||
|
|
||||||
writer.Write(Ident);
|
writer.Write(Ident);
|
||||||
writer.Write((int)(12 + entriesStream.Length + indexStream.Length));
|
writer.Write((int)(12 + entriesStream.Length + indexStream.Length));
|
||||||
writer.Write((int)(Entries.Length));
|
writer.Write((uint)(Entries.Length));
|
||||||
|
|
||||||
// write entries index data
|
// write entries index data
|
||||||
var buf1 = new byte[indexStream.Length];
|
var buf1 = new byte[indexStream.Length];
|
||||||
@ -536,8 +563,8 @@ namespace CodeWalker.GameFiles
|
|||||||
|
|
||||||
public void Read(DataReader reader)
|
public void Read(DataReader reader)
|
||||||
{
|
{
|
||||||
this.NameHash = (MetaName)reader.ReadUInt32();
|
NameHash = (MetaName)reader.ReadUInt32();
|
||||||
this.Offset = reader.ReadInt32();
|
Offset = reader.ReadInt32();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Write(DataWriter writer)
|
public void Write(DataWriter writer)
|
||||||
@ -590,11 +617,11 @@ namespace CodeWalker.GameFiles
|
|||||||
public override void Read(DataReader reader)
|
public override void Read(DataReader reader)
|
||||||
{
|
{
|
||||||
uint x = reader.ReadUInt32();
|
uint x = reader.ReadUInt32();
|
||||||
this.Type = (byte)((x & 0xFF000000) >> 24);
|
Type = (byte)((x & 0xFF000000) >> 24);
|
||||||
this.EntriesCount = (short)(x & 0xFFFF);
|
EntriesCount = (short)(x & 0xFFFF);
|
||||||
this.Unk = (byte)((x & 0x00FF0000) >> 16);
|
Unk = (byte)((x & 0x00FF0000) >> 16);
|
||||||
this.StructureLength = reader.ReadInt32();
|
StructureLength = reader.ReadInt32();
|
||||||
this.Unk_Ch = reader.ReadUInt32();
|
Unk_Ch = reader.ReadUInt32();
|
||||||
|
|
||||||
if (Unk_Ch != 0)
|
if (Unk_Ch != 0)
|
||||||
{ }
|
{ }
|
||||||
@ -655,7 +682,7 @@ namespace CodeWalker.GameFiles
|
|||||||
{
|
{
|
||||||
public MetaName EntryNameHash { get; set; }
|
public MetaName EntryNameHash { get; set; }
|
||||||
public PsoDataType Type { get; set; }
|
public PsoDataType Type { get; set; }
|
||||||
public byte Unk_5h { get; set; }
|
public byte Unk_5h { get; set; } //0 = default, 3 = pointer array?
|
||||||
public ushort DataOffset { get; set; }
|
public ushort DataOffset { get; set; }
|
||||||
public uint ReferenceKey { get; set; } // when array -> entry index with type
|
public uint ReferenceKey { get; set; } // when array -> entry index with type
|
||||||
|
|
||||||
@ -673,11 +700,11 @@ namespace CodeWalker.GameFiles
|
|||||||
|
|
||||||
public void Read(DataReader reader)
|
public void Read(DataReader reader)
|
||||||
{
|
{
|
||||||
this.EntryNameHash = (MetaName)reader.ReadUInt32();
|
EntryNameHash = (MetaName)reader.ReadUInt32();
|
||||||
this.Type = (PsoDataType)reader.ReadByte();
|
Type = (PsoDataType)reader.ReadByte();
|
||||||
this.Unk_5h = reader.ReadByte();
|
Unk_5h = reader.ReadByte();
|
||||||
this.DataOffset = reader.ReadUInt16();
|
DataOffset = reader.ReadUInt16();
|
||||||
this.ReferenceKey = reader.ReadUInt32();
|
ReferenceKey = reader.ReadUInt32();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Write(DataWriter writer)
|
public void Write(DataWriter writer)
|
||||||
@ -721,8 +748,8 @@ namespace CodeWalker.GameFiles
|
|||||||
public override void Read(DataReader reader)
|
public override void Read(DataReader reader)
|
||||||
{
|
{
|
||||||
uint x = reader.ReadUInt32();
|
uint x = reader.ReadUInt32();
|
||||||
this.Type = (byte)((x & 0xFF000000) >> 24);
|
Type = (byte)((x & 0xFF000000) >> 24);
|
||||||
this.EntriesCount = (int)(x & 0x00FFFFFF);
|
EntriesCount = (int)(x & 0x00FFFFFF);
|
||||||
|
|
||||||
Entries = new PsoEnumEntryInfo[EntriesCount];
|
Entries = new PsoEnumEntryInfo[EntriesCount];
|
||||||
for (int i = 0; i < EntriesCount; i++)
|
for (int i = 0; i < EntriesCount; i++)
|
||||||
@ -762,6 +789,21 @@ namespace CodeWalker.GameFiles
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public PsoEnumEntryInfo FindEntryByName(MetaName name)
|
||||||
|
{
|
||||||
|
if (Entries == null) return null;
|
||||||
|
for (int i = 0; i < Entries.Length; i++)
|
||||||
|
{
|
||||||
|
var entry = Entries[i];
|
||||||
|
if (entry.EntryNameHash == name)
|
||||||
|
{
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
@ -785,8 +827,8 @@ namespace CodeWalker.GameFiles
|
|||||||
|
|
||||||
public void Read(DataReader reader)
|
public void Read(DataReader reader)
|
||||||
{
|
{
|
||||||
this.EntryNameHash = (MetaName)reader.ReadUInt32();
|
EntryNameHash = (MetaName)reader.ReadUInt32();
|
||||||
this.EntryKey = reader.ReadInt32();
|
EntryKey = reader.ReadInt32();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Write(DataWriter writer)
|
public void Write(DataWriter writer)
|
||||||
@ -827,10 +869,25 @@ namespace CodeWalker.GameFiles
|
|||||||
|
|
||||||
public void Write(DataWriter writer)
|
public void Write(DataWriter writer)
|
||||||
{
|
{
|
||||||
|
var strStream = new MemoryStream();
|
||||||
|
var strWriter = new DataWriter(strStream, Endianess.BigEndian);
|
||||||
|
foreach (var str in Strings)
|
||||||
|
{
|
||||||
|
strWriter.Write(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
Length = (int)strStream.Length + 8;
|
||||||
|
|
||||||
writer.Write(Ident);
|
writer.Write(Ident);
|
||||||
writer.Write(Length);
|
writer.Write(Length);
|
||||||
|
|
||||||
|
if (strStream.Length > 0)
|
||||||
|
{
|
||||||
|
var buf1 = new byte[strStream.Length];
|
||||||
|
strStream.Position = 0;
|
||||||
|
strStream.Read(buf1, 0, buf1.Length);
|
||||||
|
writer.Write(buf1);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -867,10 +924,25 @@ namespace CodeWalker.GameFiles
|
|||||||
|
|
||||||
public void Write(DataWriter writer)
|
public void Write(DataWriter writer)
|
||||||
{
|
{
|
||||||
|
var strStream = new MemoryStream();
|
||||||
|
var strWriter = new DataWriter(strStream, Endianess.BigEndian);
|
||||||
|
foreach (var str in Strings)
|
||||||
|
{
|
||||||
|
strWriter.Write(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
Length = (int)strStream.Length + 8;
|
||||||
|
|
||||||
writer.Write(Ident);
|
writer.Write(Ident);
|
||||||
writer.Write(Length);
|
writer.Write(Length);
|
||||||
|
|
||||||
|
if (strStream.Length > 0)
|
||||||
|
{
|
||||||
|
var buf1 = new byte[strStream.Length];
|
||||||
|
strStream.Position = 0;
|
||||||
|
strStream.Read(buf1, 0, buf1.Length);
|
||||||
|
writer.Write(buf1);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -886,7 +958,6 @@ namespace CodeWalker.GameFiles
|
|||||||
public int Length { get; set; }
|
public int Length { get; set; }
|
||||||
public byte[] Data { get; set; }
|
public byte[] Data { get; set; }
|
||||||
|
|
||||||
//public MetaHash[] Hashes { get; set; }
|
|
||||||
//public byte[] Decr1 { get; set; }
|
//public byte[] Decr1 { get; set; }
|
||||||
//public byte[] Decr2 { get; set; }
|
//public byte[] Decr2 { get; set; }
|
||||||
|
|
||||||
@ -899,26 +970,25 @@ namespace CodeWalker.GameFiles
|
|||||||
{
|
{
|
||||||
Data = reader.ReadBytes(Length - 8);
|
Data = reader.ReadBytes(Length - 8);
|
||||||
|
|
||||||
//reader.Position = 8;
|
|
||||||
//List<MetaHash> hashes = new List<MetaHash>();
|
|
||||||
//while (reader.Position < reader.Length)
|
|
||||||
//{
|
|
||||||
// hashes.Add(reader.ReadUInt32());
|
|
||||||
//}
|
|
||||||
//Hashes = hashes.ToArray();
|
|
||||||
|
|
||||||
//Decr1 = GTACrypto.DecryptAES(Data);
|
//Decr1 = GTACrypto.DecryptAES(Data);
|
||||||
//Decr2 = GTACrypto.DecryptNG(Data, )
|
//Decr2 = GTACrypto.DecryptNG(Data, )
|
||||||
|
|
||||||
|
//TODO: someone plz figure out that encryption
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Write(DataWriter writer)
|
public void Write(DataWriter writer)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
Length = (Data?.Length??0) + 8;
|
||||||
|
|
||||||
writer.Write(Ident);
|
writer.Write(Ident);
|
||||||
writer.Write(Length);
|
writer.Write(Length);
|
||||||
|
|
||||||
|
if (Length > 8)
|
||||||
|
{
|
||||||
|
writer.Write(Data);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -947,10 +1017,15 @@ namespace CodeWalker.GameFiles
|
|||||||
|
|
||||||
public void Write(DataWriter writer)
|
public void Write(DataWriter writer)
|
||||||
{
|
{
|
||||||
|
Length = (Data?.Length ?? 0) + 8;
|
||||||
|
|
||||||
writer.Write(Ident);
|
writer.Write(Ident);
|
||||||
writer.Write(Length);
|
writer.Write(Length);
|
||||||
|
|
||||||
|
if (Length > 8)
|
||||||
|
{
|
||||||
|
writer.Write(Data);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -983,11 +1058,13 @@ namespace CodeWalker.GameFiles
|
|||||||
|
|
||||||
public void Write(DataWriter writer)
|
public void Write(DataWriter writer)
|
||||||
{
|
{
|
||||||
|
Length = 20;
|
||||||
|
|
||||||
writer.Write(Ident);
|
writer.Write(Ident);
|
||||||
writer.Write(Length);
|
writer.Write(Length);
|
||||||
|
writer.Write(FileSize);
|
||||||
|
writer.Write(Checksum);
|
||||||
|
writer.Write(Unk0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
|
504
CodeWalker.Core/GameFiles/MetaTypes/PsoBuilder.cs
Normal file
504
CodeWalker.Core/GameFiles/MetaTypes/PsoBuilder.cs
Normal file
@ -0,0 +1,504 @@
|
|||||||
|
using SharpDX;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace CodeWalker.GameFiles
|
||||||
|
{
|
||||||
|
public class PsoBuilder
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
public PsoBuilderPointer RootPointer { get; set; }
|
||||||
|
|
||||||
|
List<string> STRFStrings = new List<string>();
|
||||||
|
List<string> STRSStrings = new List<string>();
|
||||||
|
|
||||||
|
|
||||||
|
Dictionary<MetaName, PsoStructureInfo> StructureInfos = new Dictionary<MetaName, PsoStructureInfo>();
|
||||||
|
Dictionary<MetaName, PsoEnumInfo> EnumInfos = new Dictionary<MetaName, PsoEnumInfo>();
|
||||||
|
|
||||||
|
|
||||||
|
List<PsoBuilderBlock> Blocks = new List<PsoBuilderBlock>();
|
||||||
|
int MaxBlockLength = 0x100000; //TODO: figure what this should be!
|
||||||
|
|
||||||
|
public PsoBuilderBlock EnsureBlock(MetaName type)
|
||||||
|
{
|
||||||
|
foreach (var block in Blocks)
|
||||||
|
{
|
||||||
|
if (block.StructureNameHash == type)
|
||||||
|
{
|
||||||
|
if (block.TotalSize < MaxBlockLength)
|
||||||
|
{
|
||||||
|
return block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PsoBuilderBlock b = new PsoBuilderBlock();
|
||||||
|
b.StructureNameHash = type;
|
||||||
|
b.Index = Blocks.Count;
|
||||||
|
Blocks.Add(b);
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public PsoBuilderPointer AddItem<T>(MetaName type, T item) where T : struct
|
||||||
|
{
|
||||||
|
byte[] data = MetaTypes.ConvertToBytes(item);
|
||||||
|
return AddItem(type, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PsoBuilderPointer AddItem(MetaName type, byte[] data)
|
||||||
|
{
|
||||||
|
PsoBuilderBlock block = EnsureBlock(type);
|
||||||
|
int brem = data.Length % 16;
|
||||||
|
if (brem > 0)
|
||||||
|
{
|
||||||
|
int newlen = data.Length - brem + 16;
|
||||||
|
byte[] newdata = new byte[newlen];
|
||||||
|
Buffer.BlockCopy(data, 0, newdata, 0, data.Length);
|
||||||
|
data = newdata; //make sure item size is multiple of 16... so pointers don't need sub offsets!
|
||||||
|
}
|
||||||
|
int idx = block.AddItem(data);
|
||||||
|
PsoBuilderPointer r = new PsoBuilderPointer();
|
||||||
|
r.BlockID = block.Index + 1;
|
||||||
|
r.Offset = (idx * data.Length);
|
||||||
|
r.Length = data.Length;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PsoBuilderPointer AddItemArray<T>(MetaName type, T[] items) where T : struct
|
||||||
|
{
|
||||||
|
byte[] data = MetaTypes.ConvertArrayToBytes(items);
|
||||||
|
return AddItemArray(type, data, items.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PsoBuilderPointer AddItemArray(MetaName type, byte[] data, int length)
|
||||||
|
{
|
||||||
|
PsoBuilderBlock block = EnsureBlock(type);
|
||||||
|
int datalen = data.Length;
|
||||||
|
int newlen = datalen;
|
||||||
|
//int lenrem = newlen % 16;
|
||||||
|
//if (lenrem != 0)
|
||||||
|
//{
|
||||||
|
// newlen += (16 - lenrem);
|
||||||
|
//}
|
||||||
|
byte[] newdata = new byte[newlen];
|
||||||
|
Buffer.BlockCopy(data, 0, newdata, 0, datalen);
|
||||||
|
int offs = block.TotalSize;
|
||||||
|
int idx = block.AddItem(newdata);
|
||||||
|
PsoBuilderPointer r = new PsoBuilderPointer();
|
||||||
|
r.BlockID = block.Index + 1;
|
||||||
|
r.Offset = offs; //(idx * data.Length);;
|
||||||
|
r.Length = length;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public PsoPOINTER AddItemPtr<T>(MetaName type, T item) where T : struct //helper method for AddItem<T>
|
||||||
|
{
|
||||||
|
var ptr = AddItem(type, item);
|
||||||
|
return new PsoPOINTER(ptr.BlockID, ptr.Offset, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PsoPOINTER AddItemPtr(MetaName type, byte[] data)//helper method for AddItem<T>
|
||||||
|
{
|
||||||
|
var ptr = AddItem(type, data);
|
||||||
|
return new PsoPOINTER(ptr.BlockID, ptr.Offset, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Array_Structure AddItemArrayPtr<T>(MetaName type, T[] items) where T : struct //helper method for AddItemArray<T>
|
||||||
|
{
|
||||||
|
if ((items == null) || (items.Length == 0)) return new Array_Structure();
|
||||||
|
var ptr = AddItemArray(type, items);
|
||||||
|
return new Array_Structure(ptr.Pointer, ptr.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Array_Structure AddItemArrayPtr(MetaName type, byte[][] data) //helper method for AddItemArray<T>
|
||||||
|
{
|
||||||
|
if ((data == null) || (data.Length == 0)) return new Array_Structure();
|
||||||
|
|
||||||
|
int len = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < data.Length; i++)
|
||||||
|
{
|
||||||
|
len += data[i].Length;
|
||||||
|
}
|
||||||
|
|
||||||
|
var newdata = new byte[len];
|
||||||
|
|
||||||
|
int offset = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < data.Length; i++)
|
||||||
|
{
|
||||||
|
Buffer.BlockCopy(data[i], 0, newdata, offset, data[i].Length);
|
||||||
|
offset += data[i].Length;
|
||||||
|
}
|
||||||
|
|
||||||
|
var ptr = AddItemArray(type, newdata, data.Length);
|
||||||
|
return new Array_Structure(ptr.Pointer, ptr.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public Array_StructurePointer AddPointerArray(PsoPOINTER[] arr)
|
||||||
|
{
|
||||||
|
if ((arr == null) || (arr.Length == 0)) return new Array_StructurePointer();
|
||||||
|
var ptr = AddItemArray(MetaName.PsoPOINTER, arr);
|
||||||
|
Array_StructurePointer sp = new Array_StructurePointer();
|
||||||
|
sp.Count1 = (ushort)arr.Length;
|
||||||
|
sp.Count2 = sp.Count1;
|
||||||
|
sp.Pointer = ptr.Pointer;
|
||||||
|
return sp;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public PsoBuilderPointer AddString(string str)
|
||||||
|
{
|
||||||
|
PsoBuilderBlock block = EnsureBlock((MetaName)1); //PsoSTRING seems to be 1
|
||||||
|
byte[] data = Encoding.ASCII.GetBytes(str + (char)0);
|
||||||
|
int datalen = data.Length;
|
||||||
|
int newlen = datalen;
|
||||||
|
//int lenrem = newlen % 16;
|
||||||
|
//if (lenrem != 0) //pad the data length up to multiple of 16.
|
||||||
|
//{
|
||||||
|
// newlen += (16 - lenrem);
|
||||||
|
//}
|
||||||
|
byte[] newdata = new byte[newlen];
|
||||||
|
Buffer.BlockCopy(data, 0, newdata, 0, datalen);
|
||||||
|
int offs = block.TotalSize;
|
||||||
|
int idx = block.AddItem(newdata);
|
||||||
|
PsoBuilderPointer r = new PsoBuilderPointer();
|
||||||
|
r.BlockID = block.Index + 1;
|
||||||
|
r.Offset = offs;// (idx * data.Length);
|
||||||
|
r.Length = datalen; //actual length of string.
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Array_Vector3 AddPaddedVector3ArrayPtr(Vector4[] items)
|
||||||
|
{
|
||||||
|
if ((items == null) || (items.Length == 0)) return new Array_Vector3();
|
||||||
|
var ptr = AddItemArray((MetaName)1, items); //MetaName.VECTOR4 padded to vec4...
|
||||||
|
return new Array_Vector3(ptr.Pointer, items.Length);
|
||||||
|
}
|
||||||
|
public Array_Vector3 AddVector2ArrayPtr(Vector2[] items)
|
||||||
|
{
|
||||||
|
if ((items == null) || (items.Length == 0)) return new Array_Vector3();
|
||||||
|
var ptr = AddItemArray((MetaName)1, items); //MetaName.VECTOR4 padded to vec4...?
|
||||||
|
return new Array_Vector3(ptr.Pointer, items.Length);
|
||||||
|
}
|
||||||
|
public Array_uint AddHashArrayPtr(MetaHash[] items)
|
||||||
|
{
|
||||||
|
if ((items == null) || (items.Length == 0)) return new Array_uint();
|
||||||
|
var ptr = AddItemArray((MetaName)6, items); //MetaName.HASH
|
||||||
|
return new Array_uint(ptr.Pointer, items.Length);
|
||||||
|
}
|
||||||
|
public Array_uint AddUIntArrayPtr(uint[] items)
|
||||||
|
{
|
||||||
|
if ((items == null) || (items.Length == 0)) return new Array_uint();
|
||||||
|
var ptr = AddItemArray((MetaName)6, items);
|
||||||
|
return new Array_uint(ptr.Pointer, items.Length);
|
||||||
|
}
|
||||||
|
public Array_uint AddSIntArrayPtr(int[] items)
|
||||||
|
{
|
||||||
|
if ((items == null) || (items.Length == 0)) return new Array_uint();
|
||||||
|
var ptr = AddItemArray((MetaName)5, items);
|
||||||
|
return new Array_uint(ptr.Pointer, items.Length);
|
||||||
|
}
|
||||||
|
public Array_ushort AddUShortArrayPtr(ushort[] items)
|
||||||
|
{
|
||||||
|
if ((items == null) || (items.Length == 0)) return new Array_ushort();
|
||||||
|
var ptr = AddItemArray((MetaName)4, items);
|
||||||
|
return new Array_ushort(ptr.Pointer, items.Length);
|
||||||
|
}
|
||||||
|
public Array_byte AddByteArrayPtr(byte[] items)
|
||||||
|
{
|
||||||
|
if ((items == null) || (items.Length == 0)) return new Array_byte();
|
||||||
|
var ptr = AddItemArray((MetaName)2, items);
|
||||||
|
return new Array_byte(ptr.Pointer, items.Length);
|
||||||
|
}
|
||||||
|
public Array_float AddFloatArrayPtr(float[] items)
|
||||||
|
{
|
||||||
|
if ((items == null) || (items.Length == 0)) return new Array_float();
|
||||||
|
var ptr = AddItemArray((MetaName)7, items); //MetaName.PsoFLOAT ? comes up as MetaName.POINTER due to RSC meta values
|
||||||
|
return new Array_float(ptr.Pointer, items.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public void AddStringToSTRF(string str)
|
||||||
|
{
|
||||||
|
STRFStrings.Add(str);
|
||||||
|
}
|
||||||
|
public void AddStringToSTRS(string str)
|
||||||
|
{
|
||||||
|
STRSStrings.Add(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public void AddStructureInfo(MetaName name)
|
||||||
|
{
|
||||||
|
if (!StructureInfos.ContainsKey(name))
|
||||||
|
{
|
||||||
|
PsoStructureInfo si = PsoTypes.GetStructureInfo(name);
|
||||||
|
if (si != null)
|
||||||
|
{
|
||||||
|
StructureInfos[name] = si;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void AddEnumInfo(MetaName name)
|
||||||
|
{
|
||||||
|
if (!EnumInfos.ContainsKey(name))
|
||||||
|
{
|
||||||
|
PsoEnumInfo ei = PsoTypes.GetEnumInfo(name);
|
||||||
|
if (ei != null)
|
||||||
|
{
|
||||||
|
EnumInfos[name] = ei;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public PsoStructureInfo AddMapNodeStructureInfo(MetaName valType)
|
||||||
|
{
|
||||||
|
PsoStructureInfo inf = null;
|
||||||
|
|
||||||
|
if (valType == 0)
|
||||||
|
{
|
||||||
|
inf = PsoTypes.GetStructureInfo(MetaName.ARRAYINFO); //default ARRAYINFO with pointer
|
||||||
|
if (!StructureInfos.ContainsKey(inf.IndexInfo.NameHash))
|
||||||
|
{
|
||||||
|
StructureInfos[inf.IndexInfo.NameHash] = inf;
|
||||||
|
}
|
||||||
|
return inf;
|
||||||
|
}
|
||||||
|
|
||||||
|
var structInfo = PsoTypes.GetStructureInfo(valType);
|
||||||
|
if (structInfo == null)
|
||||||
|
{ }//error?
|
||||||
|
|
||||||
|
MetaName xName = MetaName.ARRAYINFO + 1; //257
|
||||||
|
bool nameOk = !StructureInfos.ContainsKey(xName);
|
||||||
|
while (!nameOk)
|
||||||
|
{
|
||||||
|
var exInfo = StructureInfos[xName];
|
||||||
|
var exInfoItem = exInfo.FindEntry(MetaName.Item);
|
||||||
|
if (((MetaName)(exInfoItem?.ReferenceKey ?? 0) == valType))
|
||||||
|
{
|
||||||
|
return exInfo; //this one already exists.. use it!
|
||||||
|
}
|
||||||
|
xName++;
|
||||||
|
nameOk = !StructureInfos.ContainsKey(xName);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
inf = new PsoStructureInfo(xName, 0, 2, 8 + structInfo.StructureLength,
|
||||||
|
new PsoStructureEntryInfo(MetaName.Key, PsoDataType.String, 0, 7, 0),
|
||||||
|
new PsoStructureEntryInfo(MetaName.Item, PsoDataType.Structure, 8, 0, valType)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!StructureInfos.ContainsKey(xName))
|
||||||
|
{
|
||||||
|
StructureInfos[xName] = inf;
|
||||||
|
}
|
||||||
|
|
||||||
|
return inf;
|
||||||
|
|
||||||
|
|
||||||
|
//switch (valType)
|
||||||
|
//{
|
||||||
|
// case (MetaName)331140115: return PsoTypes.GetStructureInfo((MetaName)257);
|
||||||
|
// case (MetaName)2046450505: return PsoTypes.GetStructureInfo((MetaName)258);
|
||||||
|
// case (MetaName)3219912345: return PsoTypes.GetStructureInfo((MetaName)259);
|
||||||
|
// case (MetaName)0: return PsoTypes.GetStructureInfo(MetaName.ARRAYINFO);
|
||||||
|
// default:
|
||||||
|
// return PsoTypes.GetStructureInfo(MetaName.ARRAYINFO);//error?
|
||||||
|
//}
|
||||||
|
//case (MetaName)257:
|
||||||
|
// return new PsoStructureInfo((MetaName)257, 0, 2, 32,
|
||||||
|
// new PsoStructureEntryInfo(MetaName.Key, PsoDataType.String, 0, 7, 0),
|
||||||
|
// new PsoStructureEntryInfo(MetaName.Item, PsoDataType.Structure, 8, 0, (MetaName)331140115)
|
||||||
|
// );
|
||||||
|
//case (MetaName)258:
|
||||||
|
// return new PsoStructureInfo((MetaName)258, 0, 2, 24,
|
||||||
|
// new PsoStructureEntryInfo(MetaName.Key, PsoDataType.String, 0, 7, 0),
|
||||||
|
// new PsoStructureEntryInfo(MetaName.Item, PsoDataType.Structure, 8, 0, (MetaName)2046450505)
|
||||||
|
// );
|
||||||
|
//case (MetaName)259:
|
||||||
|
// return new PsoStructureInfo((MetaName)259, 0, 2, 32,
|
||||||
|
// new PsoStructureEntryInfo(MetaName.Key, PsoDataType.String, 0, 7, 0),
|
||||||
|
// new PsoStructureEntryInfo(MetaName.Item, PsoDataType.Structure, 8, 0, (MetaName)3219912345)
|
||||||
|
// );
|
||||||
|
//case (MetaName)3219912345:
|
||||||
|
// return new PsoStructureInfo((MetaName)3219912345, 0, 0, 24,
|
||||||
|
// new PsoStructureEntryInfo(MetaName.ARRAYINFO, PsoDataType.Structure, 0, 0, (MetaName)2356519750),
|
||||||
|
// new PsoStructureEntryInfo((MetaName)4147768898, PsoDataType.Array, 8, 0, 0)
|
||||||
|
// );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public byte[] GetData()
|
||||||
|
{
|
||||||
|
int totlen = 16;
|
||||||
|
for (int i = 0; i < Blocks.Count; i++)
|
||||||
|
{
|
||||||
|
totlen += Blocks[i].TotalSize;
|
||||||
|
}
|
||||||
|
byte[] data = new byte[totlen];
|
||||||
|
int offset = 16; //reserved space for headers
|
||||||
|
for (int i = 0; i < Blocks.Count; i++)
|
||||||
|
{
|
||||||
|
var block = Blocks[i];
|
||||||
|
for (int j = 0; j < block.Items.Count; j++)
|
||||||
|
{
|
||||||
|
var bdata = block.Items[j];
|
||||||
|
Buffer.BlockCopy(bdata, 0, data, offset, bdata.Length);
|
||||||
|
offset += bdata.Length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (offset != data.Length)
|
||||||
|
{ }
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public PsoFile GetPso()
|
||||||
|
{
|
||||||
|
PsoFile pso = new PsoFile();
|
||||||
|
pso.SchemaSection = new PsoSchemaSection();
|
||||||
|
|
||||||
|
var schEntries = new List<PsoElementInfo>();
|
||||||
|
foreach (var structInfo in StructureInfos.Values)
|
||||||
|
{
|
||||||
|
schEntries.Add(structInfo);
|
||||||
|
}
|
||||||
|
foreach (var enumInfo in EnumInfos.Values)
|
||||||
|
{
|
||||||
|
schEntries.Add(enumInfo);
|
||||||
|
}
|
||||||
|
pso.SchemaSection.Entries = schEntries.ToArray();
|
||||||
|
pso.SchemaSection.EntriesIdx = new PsoElementIndexInfo[schEntries.Count];
|
||||||
|
for (int i = 0; i < schEntries.Count; i++)
|
||||||
|
{
|
||||||
|
pso.SchemaSection.EntriesIdx[i] = new PsoElementIndexInfo();
|
||||||
|
pso.SchemaSection.EntriesIdx[i].NameHash = schEntries[i].IndexInfo.NameHash;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (STRFStrings.Count > 0)
|
||||||
|
{
|
||||||
|
pso.STRFSection = new PsoSTRFSection();
|
||||||
|
pso.STRFSection.Strings = STRFStrings.ToArray();
|
||||||
|
}
|
||||||
|
if (STRSStrings.Count > 0)
|
||||||
|
{
|
||||||
|
pso.STRSSection = new PsoSTRSSection();
|
||||||
|
pso.STRSSection.Strings = STRSStrings.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pso.DataSection = new PsoDataSection();
|
||||||
|
pso.DataSection.Data = GetData();
|
||||||
|
|
||||||
|
pso.DataMapSection = new PsoDataMapSection();
|
||||||
|
pso.DataMapSection.Entries = new PsoDataMappingEntry[Blocks.Count];
|
||||||
|
pso.DataMapSection.RootId = RootPointer.BlockID;
|
||||||
|
var offset = 16;
|
||||||
|
for (int i = 0; i < Blocks.Count; i++)
|
||||||
|
{
|
||||||
|
var b = Blocks[i];
|
||||||
|
var e = new PsoDataMappingEntry();
|
||||||
|
e.NameHash = b.StructureNameHash;
|
||||||
|
e.Length = b.TotalSize;
|
||||||
|
e.Offset = offset;
|
||||||
|
offset += b.TotalSize;
|
||||||
|
pso.DataMapSection.Entries[i] = e;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return pso;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public class PsoBuilderBlock
|
||||||
|
{
|
||||||
|
public MetaName StructureNameHash { get; set; }
|
||||||
|
public List<byte[]> Items { get; set; } = new List<byte[]>();
|
||||||
|
public int TotalSize { get; set; } = 0;
|
||||||
|
public int Index { get; set; } = 0;
|
||||||
|
|
||||||
|
public int AddItem(byte[] item)
|
||||||
|
{
|
||||||
|
int idx = Items.Count;
|
||||||
|
Items.Add(item);
|
||||||
|
TotalSize += item.Length;
|
||||||
|
return idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
public uint BasePointer
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return (((uint)Index + 1) & 0xFFF);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//public MetaDataBlock GetMetaDataBlock()
|
||||||
|
//{
|
||||||
|
// if (TotalSize <= 0) return null;
|
||||||
|
// byte[] data = new byte[TotalSize];
|
||||||
|
// int offset = 0;
|
||||||
|
// for (int j = 0; j < Items.Count; j++)
|
||||||
|
// {
|
||||||
|
// var bdata = Items[j];
|
||||||
|
// Buffer.BlockCopy(bdata, 0, data, offset, bdata.Length);
|
||||||
|
// offset += bdata.Length;
|
||||||
|
// }
|
||||||
|
// MetaDataBlock db = new MetaDataBlock();
|
||||||
|
// db.StructureNameHash = StructureNameHash;
|
||||||
|
// db.DataLength = TotalSize;
|
||||||
|
// db.Data = data;
|
||||||
|
// return db;
|
||||||
|
//}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct PsoBuilderPointer
|
||||||
|
{
|
||||||
|
public int BlockID { get; set; } //1-based id
|
||||||
|
public int Offset { get; set; } //byte offset
|
||||||
|
public int Length { get; set; } //for temp use...
|
||||||
|
public uint Pointer
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
uint bidx = (((uint)BlockID) & 0xFFF);
|
||||||
|
uint offs = (((uint)Offset) & 0xFFFFF) << 12;
|
||||||
|
return bidx + offs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -647,11 +647,11 @@ namespace CodeWalker.GameFiles
|
|||||||
new PsoStructureEntryInfo(MetaName.Probabilities, PsoDataType.Array, 8, 0, 0)
|
new PsoStructureEntryInfo(MetaName.Probabilities, PsoDataType.Array, 8, 0, 0)
|
||||||
);
|
);
|
||||||
case (MetaName)2575850962:
|
case (MetaName)2575850962:
|
||||||
return new PsoStructureInfo((MetaName)2575850962, 0, 0, 40,
|
return new PsoStructureInfo((MetaName)2575850962, 0, 0, 44 /*40*/,
|
||||||
new PsoStructureEntryInfo(MetaName.ARRAYINFO, PsoDataType.UByte, 0, 0, 0),
|
new PsoStructureEntryInfo(MetaName.ARRAYINFO, PsoDataType.UByte, 0, 0, 0),
|
||||||
new PsoStructureEntryInfo(MetaName.indices, PsoDataType.Array, 8, 4, (MetaName)262144),
|
new PsoStructureEntryInfo(MetaName.indices, PsoDataType.Array, 8, 4, (MetaName)393216 /*262144*/),
|
||||||
new PsoStructureEntryInfo(MetaName.ARRAYINFO, PsoDataType.Bool, 0, 0, 0),
|
new PsoStructureEntryInfo(MetaName.ARRAYINFO, PsoDataType.Bool, 0, 0, 0),
|
||||||
new PsoStructureEntryInfo(MetaName.liveries, PsoDataType.Array, 12, 4, (MetaName)1638402)
|
new PsoStructureEntryInfo(MetaName.liveries, PsoDataType.Array, 14 /*12*/, 4, (MetaName)1966082 /*1638402*/)
|
||||||
);
|
);
|
||||||
case (MetaName)938618322:
|
case (MetaName)938618322:
|
||||||
return new PsoStructureInfo((MetaName)938618322, 0, 0, 16,
|
return new PsoStructureInfo((MetaName)938618322, 0, 0, 16,
|
||||||
@ -16104,10 +16104,13 @@ namespace CodeWalker.GameFiles
|
|||||||
var blocki = (int)ptr.PointerDataId;// (ptr.Pointer & 0xFFF) - 1;
|
var blocki = (int)ptr.PointerDataId;// (ptr.Pointer & 0xFFF) - 1;
|
||||||
var offset = (int)ptr.PointerDataOffset;// (ptr.Pointer >> 12) & 0xFFFFF;
|
var offset = (int)ptr.PointerDataOffset;// (ptr.Pointer >> 12) & 0xFFFFF;
|
||||||
|
|
||||||
var block = pso.GetBlock(blocki);
|
var block = pso.GetBlock(blocki); //nameHash = 1
|
||||||
if (block == null)
|
if (block == null)
|
||||||
{ return null; }
|
{ return null; }
|
||||||
|
|
||||||
|
//if (block.NameHash != (MetaName)1)
|
||||||
|
//{ }
|
||||||
|
|
||||||
var length = ptr.Count1;
|
var length = ptr.Count1;
|
||||||
var lastbyte = offset + length;
|
var lastbyte = offset + length;
|
||||||
if (lastbyte >= block.Length)
|
if (lastbyte >= block.Length)
|
||||||
@ -16133,10 +16136,13 @@ namespace CodeWalker.GameFiles
|
|||||||
var blocki = (int)ptr.PointerDataId;// (ptr.Pointer & 0xFFF) - 1;
|
var blocki = (int)ptr.PointerDataId;// (ptr.Pointer & 0xFFF) - 1;
|
||||||
var offset = (int)ptr.PointerDataOffset;// (ptr.Pointer >> 12) & 0xFFFFF;
|
var offset = (int)ptr.PointerDataOffset;// (ptr.Pointer >> 12) & 0xFFFFF;
|
||||||
|
|
||||||
var block = pso.GetBlock(blocki);
|
var block = pso.GetBlock(blocki); //nameHash = 1
|
||||||
if (block == null)
|
if (block == null)
|
||||||
{ return null; }
|
{ return null; }
|
||||||
|
|
||||||
|
//if (block.NameHash != (MetaName)1)
|
||||||
|
//{ }
|
||||||
|
|
||||||
//var length = ptr.Count1;
|
//var length = ptr.Count1;
|
||||||
//var lastbyte = offset + length;
|
//var lastbyte = offset + length;
|
||||||
//if (lastbyte >= block.Length)
|
//if (lastbyte >= block.Length)
|
||||||
@ -16217,6 +16223,13 @@ namespace CodeWalker.GameFiles
|
|||||||
public uint ItemOffset { get { return ((Pointer>>12) & 0xFFFFF); } } //byte offset
|
public uint ItemOffset { get { return ((Pointer>>12) & 0xFFFFF); } } //byte offset
|
||||||
|
|
||||||
|
|
||||||
|
public PsoPOINTER(int blockID, int itemOffset, uint extra)
|
||||||
|
{
|
||||||
|
Pointer = (((uint)itemOffset << 12) & 0xFFFFF000) + ((uint)blockID & 0xFFF);
|
||||||
|
Unk2 = extra;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
return BlockID.ToString() + ", " + ItemOffset.ToString() + ", " + Unk2.ToString();
|
return BlockID.ToString() + ", " + ItemOffset.ToString() + ", " + Unk2.ToString();
|
||||||
|
1222
CodeWalker.Core/GameFiles/MetaTypes/XmlPso.cs
Normal file
1222
CodeWalker.Core/GameFiles/MetaTypes/XmlPso.cs
Normal file
File diff suppressed because it is too large
Load Diff
@ -2251,6 +2251,8 @@ namespace CodeWalker
|
|||||||
var fi = new FileInfo(fpath);
|
var fi = new FileInfo(fpath);
|
||||||
var fname = fi.Name;
|
var fname = fi.Name;
|
||||||
var fnamel = fname.ToLowerInvariant();
|
var fnamel = fname.ToLowerInvariant();
|
||||||
|
var mformat = MetaFormat.RSC;
|
||||||
|
var trimlength = 4;
|
||||||
|
|
||||||
if (!fnamel.EndsWith(".xml"))
|
if (!fnamel.EndsWith(".xml"))
|
||||||
{
|
{
|
||||||
@ -2259,8 +2261,8 @@ namespace CodeWalker
|
|||||||
}
|
}
|
||||||
if (fnamel.EndsWith(".pso.xml"))
|
if (fnamel.EndsWith(".pso.xml"))
|
||||||
{
|
{
|
||||||
MessageBox.Show(fname + ": PSO XML import not yet supported.", "Cannot import XML");
|
mformat = MetaFormat.PSO;
|
||||||
continue;
|
trimlength = 8;
|
||||||
}
|
}
|
||||||
if (fnamel.EndsWith(".rbf.xml"))
|
if (fnamel.EndsWith(".rbf.xml"))
|
||||||
{
|
{
|
||||||
@ -2268,8 +2270,8 @@ namespace CodeWalker
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
fname = fname.Substring(0, fname.Length - 4);
|
fname = fname.Substring(0, fname.Length - trimlength);
|
||||||
fnamel = fnamel.Substring(0, fnamel.Length - 4);
|
fnamel = fnamel.Substring(0, fnamel.Length - trimlength);
|
||||||
|
|
||||||
var doc = new XmlDocument();
|
var doc = new XmlDocument();
|
||||||
string text = File.ReadAllText(fpath);
|
string text = File.ReadAllText(fpath);
|
||||||
@ -2278,21 +2280,46 @@ namespace CodeWalker
|
|||||||
doc.LoadXml(text);
|
doc.LoadXml(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
var meta = XmlMeta.GetMeta(doc);
|
byte[] data = null;
|
||||||
|
|
||||||
|
switch (mformat)
|
||||||
if ((meta.DataBlocks?.Data == null) || (meta.DataBlocks.Count == 0))
|
|
||||||
{
|
{
|
||||||
MessageBox.Show(fname + ": Schema not supported.", "Cannot import XML");
|
case MetaFormat.RSC:
|
||||||
continue;
|
{
|
||||||
|
var meta = XmlMeta.GetMeta(doc);
|
||||||
|
if ((meta.DataBlocks?.Data == null) || (meta.DataBlocks.Count == 0))
|
||||||
|
{
|
||||||
|
MessageBox.Show(fname + ": Schema not supported.", "Cannot import Meta XML");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
data = ResourceBuilder.Build(meta, 2); //meta is RSC V:2
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MetaFormat.PSO:
|
||||||
|
{
|
||||||
|
var pso = XmlPso.GetPso(doc);
|
||||||
|
if ((pso.DataSection == null) || (pso.DataMapSection == null) || (pso.SchemaSection == null))
|
||||||
|
{
|
||||||
|
MessageBox.Show(fname + ": Schema not supported.", "Cannot import PSO XML");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
data = pso.Save();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MetaFormat.RBF:
|
||||||
|
{
|
||||||
|
//todo!
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
byte[] data = ResourceBuilder.Build(meta, 2); //meta is RSC V:2
|
if (data != null)
|
||||||
|
{
|
||||||
|
RpfFile.CreateFile(parentrpffldr, fname, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
RpfFile.CreateFile(parentrpffldr, fname, data);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
#if !DEBUG
|
#if !DEBUG
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
@ -350,8 +350,14 @@ namespace CodeWalker.Forms
|
|||||||
data = ResourceBuilder.Build(meta, 2); //meta is RSC "Version":2 (it's actually a type identifier, not a version!)
|
data = ResourceBuilder.Build(meta, 2); //meta is RSC "Version":2 (it's actually a type identifier, not a version!)
|
||||||
break;
|
break;
|
||||||
case MetaFormat.PSO:
|
case MetaFormat.PSO:
|
||||||
MessageBox.Show("Sorry, PSO import is not supported yet.", "Cannot import PSO XML");
|
var pso = XmlPso.GetPso(doc);
|
||||||
return false;
|
if ((pso.DataSection == null) || (pso.DataMapSection == null) || (pso.SchemaSection == null))
|
||||||
|
{
|
||||||
|
MessageBox.Show("Schema not supported.", "Cannot import PSO XML");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
data = pso.Save();
|
||||||
|
break;
|
||||||
case MetaFormat.RBF:
|
case MetaFormat.RBF:
|
||||||
MessageBox.Show("Sorry, RBF import is not supported.", "Cannot import RBF XML");
|
MessageBox.Show("Sorry, RBF import is not supported.", "Cannot import RBF XML");
|
||||||
return false;
|
return false;
|
||||||
|
Loading…
Reference in New Issue
Block a user