public MetaBuilderPointer AddItemArray <T>(MetaName type, T[] items) where T : struct { MetaBuilderBlock block = EnsureBlock(type); byte[] data = MetaTypes.ConvertArrayToBytes(items); 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 / 16; int idx = block.AddItem(newdata); MetaBuilderPointer r = new MetaBuilderPointer(); r.Block = block.Index + 1; r.Offset = offs; //(idx * data.Length) / 16; r.Length = items.Length; return(r); }
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 { } } }
public PsoBuilderPointer AddItemArray <T>(MetaName type, T[] items) where T : struct { byte[] data = MetaTypes.ConvertArrayToBytes(items); return(AddItemArray(type, data, items.Length)); }
public override void Write(ResourceDataWriter writer, params object[] parameters) { byte[] data = MetaTypes.ConvertArrayToBytes(Items); writer.Write(data); }