private static string GetStringValue(PsoFile pso, PsoStructureEntryInfo entry, byte[] data, int eoffset) { switch (entry.Unk_5h) { default: return(null); case 0: var str0len = (int)((entry.ReferenceKey >> 16) & 0xFFFF); return(Encoding.ASCII.GetString(data, eoffset, str0len).Replace("\0", "")); case 1: case 2: var dataPtr2 = MetaUtils.ConvertData <DataBlockPointer>(data, eoffset); dataPtr2.SwapEnd(); return(PsoUtils.GetString(pso, dataPtr2)); case 3: var charPtr3 = MetaUtils.ConvertData <CharPointer>(data, eoffset); charPtr3.SwapEnd(); var strval = PsoUtils.GetString(pso, charPtr3); return(strval ?? ""); case 7: case 8: MetaName hashVal = (MetaName)MetaUtils.SwapBytes(MetaUtils.ConvertData <uint>(data, eoffset)); return(HashString(hashVal)); } }
public override void Parse(MetaFile meta, CMapTypes CMapTypes) { this.Meta = meta; this.MetaStructure = CMapTypes; // this.Extensions = CMapTypes.extensions; // CBaseArchetypeDef + CMloArchetypeDef + CTimeArchetypeDef var archPtrs = MetaUtils.GetPointerArray(this.Meta, this.MetaStructure.archetypes); if (archPtrs != null) { for (int i = 0; i < archPtrs.Length; i++) { var ptr = archPtrs[i]; var block = Meta.GetBlock(ptr.BlockID); if (block == null) { continue; } if ((ptr.Offset < 0) || (block.Data == null) || (ptr.Offset >= block.Data.Length)) { continue; } byte[] data = Array.ConvertAll(block.Data.ToArray(), e => (byte)e); switch ((MetaName)block.StructureNameHash) { case MetaName.CBaseArchetypeDef: { var struc = PsoUtils.ConvertDataRaw <RageLib.Resources.GTA5.PC.Meta.CBaseArchetypeDef>(data, ptr.Offset); var arch = new MCBaseArchetypeDef(); arch.Parse(meta, struc); this.Archetypes.Add(arch); break; } case MetaName.CMloArchetypeDef: { var struc = PsoUtils.ConvertDataRaw <RageLib.Resources.GTA5.PC.Meta.CMloArchetypeDef>(data, ptr.Offset); var arch = new MCMloArchetypeDef(); arch.Parse(meta, struc); this.MloArchetypes.Add(arch); break; } case MetaName.CTimeArchetypeDef: { var struc = PsoUtils.ConvertDataRaw <RageLib.Resources.GTA5.PC.Meta.CTimeArchetypeDef>(data, ptr.Offset); var arch = new MCTimeArchetypeDef(); arch.Parse(meta, struc); this.TimeArchetypes.Add(arch); break; } default: continue; } } } this.Name = (MetaName)CMapTypes.name; // this.Dependencies = CMapTypes.dependencies; var compositeEntityTypes = MetaUtils.ConvertDataArray <CCompositeEntityType>(meta, CMapTypes.compositeEntityTypes); this.CompositeEntityTypes = compositeEntityTypes?.Select(e => { var msw = new MCCompositeEntityType(); msw.Parse(meta, e); return(msw); }).ToList(); }
private static void WriteArrayNode(StringBuilder sb, int indent, PsoCont cont, int blockId, int offset, PsoStructureEntryInfo entry, PsoStructureInfo estruct, string ename) { var block = cont.Pso.GetBlock(blockId); var boffset = offset + block.Offset; var eoffset = boffset + entry.DataOffset; var aOffset = offset + entry.DataOffset; var aBlockId = blockId; uint aCount = ((uint)entry.ReferenceKey >> 16) & 0x0000FFFF; var aind = indent + 1; string arrTag = ename; PsoStructureEntryInfo arrEntry = estruct.GetEntry((int)(entry.ReferenceKey & 0xFFFF)); if (arrEntry == null) { ErrorXml(sb, indent, "ARRAYINFO not found for " + ename + "!"); return; } var data = cont.Pso.DataSection.Data; switch (entry.Unk_5h) { default: ErrorXml(sb, indent, ename + ": WIP! Unsupported Array subtype: " + entry.Unk_5h.ToString()); break; case 0: //Array_Structure var arrStruc = MetaUtils.ConvertData <Array_Structure>(data, eoffset); arrStruc.SwapEnd(); aBlockId = (int)arrStruc.PointerDataId; aOffset = (int)arrStruc.PointerDataOffset; aCount = arrStruc.Count1; break; case 1: //Raw in-line array break; case 2: //also raw in-line array, but how different from above? break; case 4: //pointer array? default array? if (arrEntry.Unk_5h == 3) //pointers... { var arrStruc4 = MetaUtils.ConvertData <Array_Structure>(data, eoffset); arrStruc4.SwapEnd(); aBlockId = (int)arrStruc4.PointerDataId; aOffset = (int)arrStruc4.PointerDataOffset; aCount = arrStruc4.Count1; } break; case 129: //also raw inline array? in junctions.pso break; } switch (arrEntry.Type) { default: ErrorXml(sb, indent, ename + ": WIP! Unsupported array entry DataType: " + arrEntry.Type.ToString()); break; case RageLib.GTA5.PSO.DataType.Array: var rk0 = (entry.ReferenceKey >> 16) & 0x0000FFFF; if (rk0 > 0) { //var arrStruc5 = MetaUtils.ConvertDataArray<Array_StructurePointer>(data, eoffset, (int)rk0); //for (int n = 0; n < rk0; n++) arrStruc5[n].SwapEnd(); aOffset = offset + entry.DataOffset; OpenTag(sb, indent, arrTag); for (int n = 0; n < rk0; n++) //ARRAY ARRAY! { WriteArrayNode(sb, aind, cont, blockId, aOffset, arrEntry, estruct, "Item"); aOffset += 16; //ptr size... todo: what if not pointer array? } CloseTag(sb, indent, ename); } else { SelfClosingTag(sb, indent, arrTag); } break; case RageLib.GTA5.PSO.DataType.Structure: switch (arrEntry.Unk_5h) { case 0: break; case 3: //structure pointer array var arrStrucPtr = MetaUtils.ConvertData <Array_StructurePointer>(data, eoffset); arrStrucPtr.SwapEnd(); aBlockId = (int)arrStrucPtr.PointerDataId; aOffset = (int)arrStrucPtr.PointerDataOffset; aCount = arrStrucPtr.Count1; if (aCount > 0) { var ptrArr = PsoUtils.GetPointerArray(cont.Pso, arrStrucPtr); OpenTag(sb, indent, arrTag); for (int n = 0; n < aCount; n++) { var ptrVal = ptrArr[n]; WriteNode(sb, aind, cont, ptrVal.BlockID, (int)ptrVal.ItemOffset, XmlTagMode.ItemAndType); } CloseTag(sb, indent, ename); } break; default: break; } arrTag += " itemType=\"" + HashString((MetaName)arrEntry.ReferenceKey) + "\""; if (aCount > 0) { var aBlock = cont.Pso.GetBlock(aBlockId); var atyp = cont.GetStructureInfo((MetaName)arrEntry.ReferenceKey); if (aBlock == null) { ErrorXml(sb, indent, ename + ": Array block not found: " + aBlockId.ToString()); } else if ((MetaName)aBlock.NameHash != MetaName.PsoPOINTER) { OpenTag(sb, indent, arrTag); if (atyp == null) { ErrorXml(sb, indent, ename + ": Array type not found: " + HashString((MetaName)arrEntry.ReferenceKey)); } else { for (int n = 0; n < aCount; n++) { WriteNode(sb, aind, cont, aBlockId, aOffset, XmlTagMode.Item, (MetaName)arrEntry.ReferenceKey); aOffset += atyp.StructureLength; if ((n < (aCount - 1)) && (aBlock != null) && (aOffset >= aBlock.Length)) { break; } } } CloseTag(sb, indent, ename); } else { } //pointer array should get here, but it's already handled above. should improve this. } else { SelfClosingTag(sb, indent, arrTag); } break; case RageLib.GTA5.PSO.DataType.String: switch (entry.Unk_5h) { default: ErrorXml(sb, indent, ename + ": Unexpected String array subtype: " + entry.Unk_5h.ToString()); break; case 0: //hash array... var arrHash = MetaUtils.ConvertData <Array_uint>(data, eoffset); arrHash.SwapEnd(); var hashArr = PsoUtils.GetHashArray(cont.Pso, arrHash); WriteItemArray(sb, hashArr, indent, ename, "Hash", HashString); break; } break; case RageLib.GTA5.PSO.DataType.Float2: aCount = ((uint)entry.ReferenceKey >> 16) & 0x0000FFFF; arrTag += " itemType=\"Vector2\""; var v2Arr = MetaUtils.ConvertDataArray <Vector2>(data, eoffset, (int)aCount); WriteRawArray(sb, v2Arr, indent, ename, "Vector2", FormatVector2Swap, 1); break; case RageLib.GTA5.PSO.DataType.Float3: aCount = ((uint)entry.ReferenceKey >> 16) & 0x0000FFFF; arrTag += " itemType=\"Vector3\""; //this is actually aligned as vector4, the W values are crazy in places var v4Arr = MetaUtils.ConvertDataArray <Vector4>(data, eoffset, (int)aCount); WriteRawArray(sb, v4Arr, indent, ename, "Vector3", FormatVector4SwapXYZOnly, 1); break; case RageLib.GTA5.PSO.DataType.UByte: var barr = new byte[aCount]; if (aCount > 0) { var bblock = cont.Pso.GetBlock(aBlockId); var boffs = bblock.Offset + aOffset; Buffer.BlockCopy(data, boffs, barr, 0, (int)aCount); } WriteRawArray(sb, barr, indent, ename, "byte"); break; case RageLib.GTA5.PSO.DataType.Bool: var barr2 = new byte[aCount]; if (aCount > 0) { var bblock = cont.Pso.GetBlock(aBlockId); var boffs = bblock.Offset + aOffset; Buffer.BlockCopy(data, boffs, barr2, 0, (int)aCount); } WriteRawArray(sb, barr2, indent, ename, "boolean"); //todo: true/false output break; case RageLib.GTA5.PSO.DataType.Float: var arrFloat = MetaUtils.ConvertData <Array_float>(data, eoffset); arrFloat.SwapEnd(); var floatArr = PsoUtils.GetFloatArray(cont.Pso, arrFloat); WriteRawArray(sb, floatArr, indent, ename, "float"); break; case RageLib.GTA5.PSO.DataType.UShort: var arrShort = MetaUtils.ConvertData <Array_Structure>(data, eoffset); arrShort.SwapEnd(); var shortArr = PsoUtils.GetUShortArray(cont.Pso, arrShort); WriteRawArray(sb, shortArr, indent, ename, "ushort"); break; case RageLib.GTA5.PSO.DataType.UInt: var intArr = MetaUtils.ConvertDataArray <int>(data, eoffset, (int)aCount); WriteRawArray(sb, intArr, indent, ename, "int"); break; case RageLib.GTA5.PSO.DataType.SInt: var arrUint2 = MetaUtils.ConvertData <Array_uint>(data, eoffset); arrUint2.SwapEnd(); var intArr2 = PsoUtils.GetUintArray(cont.Pso, arrUint2); WriteRawArray(sb, intArr2, indent, ename, "int"); break; case RageLib.GTA5.PSO.DataType.Enum: var arrEnum = MetaUtils.ConvertData <Array_uint>(data, eoffset); arrEnum.SwapEnd(); var enumArr = PsoUtils.GetUintArray(cont.Pso, arrEnum); var enumDef = cont.GetEnumInfo((MetaName)arrEntry.ReferenceKey); WriteItemArray(sb, enumArr, indent, ename, "enum", (ie) => { var eval = enumDef?.FindEntry((int)ie); return(HashString((MetaName)(eval?.EntryNameHash ?? 0))); }); break; } }