public void AddStructureInfo(MetaName name) { if (!StructureInfos.ContainsKey(name)) { PsoStructureInfo si = PsoTypes.GetStructureInfo(name); if (si != null) { StructureInfos[name] = si; } } }
public static void EnsurePsoTypes(PsoFile pso) { if ((pso.SchemaSection == null) || (pso.SchemaSection.Entries == null) || (pso.SchemaSection.EntriesIdx == null)) { return; } for (int i = 0; i < pso.SchemaSection.Entries.Length; i++) { var entry = pso.SchemaSection.Entries[i]; var enuminfo = entry as PsoEnumInfo; var structinfo = entry as PsoStructureInfo; if (enuminfo != null) { if (!EnumDict.ContainsKey(enuminfo.IndexInfo.NameHash)) { EnumDict.Add(enuminfo.IndexInfo.NameHash, enuminfo); } else { PsoEnumInfo oldei = EnumDict[enuminfo.IndexInfo.NameHash]; if (!ComparePsoEnumInfos(oldei, enuminfo)) { } } } else if (structinfo != null) { if (!StructDict.ContainsKey(structinfo.IndexInfo.NameHash)) { StructDict.Add(structinfo.IndexInfo.NameHash, structinfo); } else { PsoStructureInfo oldsi = StructDict[structinfo.IndexInfo.NameHash]; if (!ComparePsoStructureInfos(oldsi, structinfo)) { } } } } }
public void Read(DataReader reader) { Ident = reader.ReadInt32(); Length = reader.ReadInt32(); Count = reader.ReadUInt32(); this.EntriesIdx = new PsoElementIndexInfo[Count]; for (int i = 0; i < Count; i++) { var entry = new PsoElementIndexInfo(); entry.Read(reader); EntriesIdx[i] = entry; } this.Entries = new PsoElementInfo[Count]; for (int i = 0; i < Count; i++) { reader.Position = EntriesIdx[i].Offset; var type = reader.ReadByte(); reader.Position = EntriesIdx[i].Offset; if (type == 0) { var entry = new PsoStructureInfo(); entry.Read(reader); entry.IndexInfo = EntriesIdx[i]; Entries[i] = entry; } else if (type == 1) { var entry = new PsoEnumInfo(); entry.Read(reader); entry.IndexInfo = EntriesIdx[i]; Entries[i] = entry; } else { throw new Exception("unknown type!"); } } }
public static bool ComparePsoStructureInfos(PsoStructureInfo a, PsoStructureInfo b) { //returns true if they are the same. if (a.Entries.Length != b.Entries.Length) { return(false); } for (int i = 0; i < a.Entries.Length; i++) { if ((a.Entries[i].EntryNameHash != b.Entries[i].EntryNameHash) || (a.Entries[i].DataOffset != b.Entries[i].DataOffset) || (a.Entries[i].Type != b.Entries[i].Type)) { return(false); } } return(true); }
private static void TraverseArray(XmlNode node, PsoBuilder pb, PsoStructureEntryInfo entry, PsoStructureEntryInfo arrEntry, PsoArrayResults results, byte[] data, PsoStructureInfo structInfo) { int offset = entry.DataOffset; uint aCount = (entry.ReferenceKey >> 16) & 0x0000FFFF; uint aPtr = (entry.ReferenceKey) & 0x0000FFFF; byte[] adata = null; //how do we know when it's an "embedded" array? bool embedded = true; switch (entry.Unk_5h) { default: //ErrorXml(sb, indent, ename + ": WIP! Unsupported Array subtype: " + entry.Unk_5h.ToString()); break; case 0: //Array_Structure //var arrStruc = MetaTypes.ConvertData<Array_Structure>(data, eoffset); embedded = false; 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 = MetaTypes.ConvertData<Array_Structure>(data, eoffset); embedded = false; } else { } break; case 129: //also raw inline array? in junctions.pso (AutoJunctionAdjustments) break; } switch (arrEntry.Type) { case PsoDataType.Structure: { if (embedded) { if (arrEntry.ReferenceKey != 0) { var datas = TraverseArrayStructureRaw(node, pb, (MetaName)arrEntry.ReferenceKey); int aoffset = offset; for (int i = 0; i < datas.Length; i++) { Buffer.BlockCopy(datas[i], 0, data, aoffset, datas[i].Length); aoffset += datas[i].Length; } } else { var ptrs = TraverseArrayStructurePointerRaw(node, pb); adata = MetaTypes.ConvertArrayToBytes(ptrs); } } else { if (arrEntry.ReferenceKey != 0) { results.Structures[offset] = TraverseArrayStructure(node, pb, (MetaName)arrEntry.ReferenceKey); } else { results.StructurePointers[offset] = TraverseArrayStructurePointer(node, pb); } } break; } case PsoDataType.Float2: { var arr = TraverseVector2ArrayRaw(node); if (embedded) { adata = MetaTypes.ConvertArrayToBytes(arr); aCount *= 8; } else { results.Float_XYZs[offset] = pb.AddVector2ArrayPtr(arr); } break; } case PsoDataType.Float3: { var arr = TraverseVector3ArrayRaw(node); if (embedded) { adata = MetaTypes.ConvertArrayToBytes(arr); aCount *= 16; } else { results.Float_XYZs[offset] = pb.AddPaddedVector3ArrayPtr(arr); } break; } case PsoDataType.UByte: { var arr = TraverseUByteArrayRaw(node); if (embedded) { adata = arr; } else { results.UBytes[offset] = pb.AddByteArrayPtr(arr); } break; } case PsoDataType.Bool: { var arr = TraverseUByteArrayRaw(node); if (embedded) { adata = arr; } else { results.UBytes[offset] = pb.AddByteArrayPtr(arr); } break; } case PsoDataType.UInt: { var arr = TraverseUIntArrayRaw(node); if (embedded) { adata = MetaTypes.ConvertArrayToBytes(arr); aCount *= 4; } else { results.UInts[offset] = pb.AddUIntArrayPtr(arr); } break; } case PsoDataType.SInt: { var arr = TraverseSIntArrayRaw(node); if (embedded) { adata = MetaTypes.ConvertArrayToBytes(arr); aCount *= 4; } else { results.UInts[offset] = pb.AddSIntArrayPtr(arr); } break; } case PsoDataType.Float: { var arr = TraverseFloatArrayRaw(node); if (embedded) { adata = MetaTypes.ConvertArrayToBytes(arr); aCount *= 4; } else { results.Floats[offset] = pb.AddFloatArrayPtr(arr); } break; } case PsoDataType.UShort: { var arr = TraverseUShortArrayRaw(node); if (embedded) { adata = MetaTypes.ConvertArrayToBytes(arr); aCount *= 2; } else { results.UShorts[offset] = pb.AddUShortArrayPtr(arr); } break; } case PsoDataType.String: { switch (entry.Unk_5h) { default: //ErrorXml(sb, indent, ename + ": Unexpected String array subtype: " + entry.Unk_5h.ToString()); break; case 0: //hash array... var hashes = TraverseHashArrayRaw(node); if (embedded) { adata = MetaTypes.ConvertArrayToBytes(hashes); aCount *= 4; } else { results.Hashes[offset] = pb.AddHashArrayPtr(hashes); } break; } break; } case PsoDataType.Enum: { var hashes = TraverseHashArrayRaw(node); if (arrEntry.ReferenceKey != 0) { var _infos = PsoTypes.GetEnumInfo((MetaName)arrEntry.ReferenceKey); pb.AddEnumInfo(_infos.IndexInfo.NameHash); var values = new uint[hashes.Length]; for (int i = 0; i < hashes.Length; i++) { var enumname = (MetaName)MetaTypes.SwapBytes(hashes[i]); //yeah swap it back to little endian..! var enuminf = _infos.FindEntryByName(enumname); if (enuminf != null) { values[i] = MetaTypes.SwapBytes((uint)enuminf.EntryKey); } else { } //error? } if (embedded) { } //TODO? else { results.UInts[offset] = pb.AddUIntArrayPtr(values); } } else { } break; } case PsoDataType.Array: { //array array... var rk0 = (entry.ReferenceKey >> 16) & 0x0000FFFF; var rk1 = arrEntry.ReferenceKey & 0x0000FFFF; if (rk0 > 0) //should be count of items { var subarrEntry = structInfo.GetEntry((int)rk1); var subarrType = (MetaName)subarrEntry.ReferenceKey; var origOffset = arrEntry.DataOffset; arrEntry.DataOffset = entry.DataOffset; //slight hack for traversing array array foreach (XmlNode cnode in node.ChildNodes) { TraverseArray(cnode, pb, arrEntry, subarrEntry, results, data, structInfo); arrEntry.DataOffset += 16; //ptr size... todo: what if not pointer array? } arrEntry.DataOffset = origOffset; } break; } default: break; } if (embedded) { if (adata?.Length > 0) { if (adata.Length > aCount) { } //bad! old data won't fit in new slot... Buffer.BlockCopy(adata, 0, data, offset, adata.Length); } else { } } }
private static void TraverseMap(XmlNode node, PsoBuilder pb, PsoStructureEntryInfo entry, PsoStructureInfo infos, byte[] data, PsoArrayResults arrayResults) { var mapidx1 = entry.ReferenceKey & 0x0000FFFF; var mapidx2 = (entry.ReferenceKey >> 16) & 0x0000FFFF; var mapreftype1 = infos.Entries[mapidx2]; var mapreftype2 = infos.Entries[mapidx1]; if (mapreftype2.ReferenceKey != 0) { } var xStruct = pb.AddMapNodeStructureInfo((MetaName)mapreftype2.ReferenceKey); var xName = xStruct.IndexInfo.NameHash; var kEntry = xStruct?.FindEntry(MetaName.Key); var iEntry = xStruct?.FindEntry(MetaName.Item); if (kEntry.Type != PsoDataType.String) { } List <byte[]> nodesData = new List <byte[]>(); foreach (XmlNode cnode in node.ChildNodes) { var kattr = cnode.Attributes["key"].Value; var tattr = cnode.Attributes["type"].Value;//CW invention for convenience..! var khash = (MetaName)(uint)GetHash(kattr); var thash = (MetaName)(uint)GetHash(tattr); byte[] strucBytes = Traverse(cnode, pb, thash); byte[] nodeBytes = new byte[xStruct.StructureLength]; TraverseStringRaw(kattr, pb, kEntry, nodeBytes); //write the key if (xName != (MetaName)MetaTypeName.ARRAYINFO) // (mapreftype2.ReferenceKey != 0) { //value struct embedded in ARRAYINFO node Buffer.BlockCopy(strucBytes, 0, nodeBytes, iEntry.DataOffset, strucBytes.Length); } else { //normal ARRAYINFO with pointer value var itemptr = pb.AddItemPtr(thash, strucBytes); itemptr.SwapEnd(); //big schmigg var ptrbytes = MetaTypes.ConvertToBytes(itemptr); Buffer.BlockCopy(ptrbytes, 0, nodeBytes, iEntry.DataOffset, ptrbytes.Length); } nodesData.Add(nodeBytes); } Write(0x1000000, data, entry.DataOffset); Write(0, data, entry.DataOffset + 4); arrayResults.Structures[entry.DataOffset + 8] = pb.AddItemArrayPtr(xName, nodesData.ToArray()); //pb.AddPointerArray(nodeptrs); }
public PsoStructureInfo AddMapNodeStructureInfo(MetaName valType) { PsoStructureInfo inf = null; if (valType == 0) { inf = PsoTypes.GetStructureInfo((MetaName)MetaTypeName.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)MetaTypeName.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.fwClipDictionaryMetadata: return PsoTypes.GetStructureInfo((MetaName)257); // case MetaName.fwMemoryGroupMetadata: return PsoTypes.GetStructureInfo((MetaName)258); // case (MetaName)3219912345: return PsoTypes.GetStructureInfo((MetaName)259); // case (MetaName)0: return PsoTypes.GetStructureInfo((MetaName)MetaTypeName.ARRAYINFO); // default: // return PsoTypes.GetStructureInfo((MetaName)MetaTypeName.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.fwClipDictionaryMetadata) // ); //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.fwMemoryGroupMetadata) // ); //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)MetaTypeName.ARRAYINFO, PsoDataType.Structure, 0, 0, (MetaName)2356519750), // new PsoStructureEntryInfo(MetaName.Adjustments, PsoDataType.Array, 8, 0, 0) // ); }