Esempio n. 1
0
        protected bool ReadHeaderData(BinaryReader reader)
        {
            Header = reader.Read <STUHeader>();
            if (Header.InstanceCount == 0 || Header.InstanceListOffset == 0)
            {
                return(false);
            }

            InstanceInfo    = new STUInstanceRecord[Header.InstanceCount];
            Stream.Position = Header.InstanceListOffset;
            for (uint i = 0; i < InstanceInfo.Length; ++i)
            {
                InstanceInfo[i] = reader.Read <STUInstanceRecord>();
            }

            InstanceArrayRef = new STUInstanceArrayRef[Header.EntryInstanceCount];
            Stream.Position  = Header.EntryInstanceListOffset;
            for (uint i = 0; i < InstanceArrayRef.Length; ++i)
            {
                InstanceArrayRef[i] = reader.Read <STUInstanceArrayRef>();
            }

            InstanceFieldLists = new STUInstanceFieldList[Header.InstanceFieldListCount];
            Stream.Position    = Header.InstanceFieldListOffset;
            for (uint i = 0; i < InstanceFieldLists.Length; ++i)
            {
                InstanceFieldLists[i] = reader.Read <STUInstanceFieldList>();
            }


            InstanceFieldLists = new STUInstanceFieldList[Header.InstanceFieldListCount];
            Stream.Position    = Header.InstanceFieldListOffset;
            for (uint i = 0; i < InstanceFieldLists.Length; ++i)
            {
                InstanceFieldLists[i] = reader.Read <STUInstanceFieldList>();
            }

            InstanceFields = new STUInstanceField[Header.InstanceFieldListCount][];
            for (uint i = 0; i < InstanceFieldLists.Length; ++i)
            {
                InstanceFields[i] = new STUInstanceField[InstanceFieldLists[i].FieldCount];
                Stream.Position   = InstanceFieldLists[i].ListOffset;
                for (uint j = 0; j < InstanceFields[i].Length; ++j)
                {
                    InstanceFields[i][j] = reader.Read <STUInstanceField>();
                }
            }

            Metadata = new MemoryStream((int)Header.MetadataSize);
            Metadata.Write(reader.ReadBytes((int)Header.MetadataSize), 0, (int)Header.MetadataSize);
            Metadata.Position = 0;
            MetadataReader    = new BinaryReader(Metadata, Encoding.UTF8, false);

            return(true);
        }
Esempio n. 2
0
        protected void TryReadArray(FieldGuessData output, STUInstanceField field, BinaryReader reader)
        {
            long beforePos = reader.BaseStream.Position;

            try {
                int offset = reader.ReadInt32();
                Metadata.Position = offset;
                STUArrayInfo array = MetadataReader.Read <STUArrayInfo>();

                if (array.Count < 99999 && array.Count > 0)
                {
                    output.IsArray   = true;
                    output.ArrayInfo = array;
                }
                // uint parent = 0;
                // if (instanceArrayRef?.Length > array.InstanceIndex) {
                //     parent = instanceArrayRef[array.InstanceIndex].Checksum;
                // }
            }
            catch (Exception) {
                output.IsArray = false;
            }
            reader.BaseStream.Position = beforePos;
        }
Esempio n. 3
0
        protected WrittenFieldData[] ReadFields(STUInstanceField[] definedFields, BinaryReader reader, uint instanceChecksum)
        {
            if (InstanceJSON == null)
            {
                return(null);
            }
            if (!InstanceJSON.ContainsKey(instanceChecksum))
            {
                Debugger.Log(0, "STULib", $"[Version2HashComparer]: Instance {instanceChecksum:X} does not exist in the dataset\n");
                return(new WrittenFieldData[0]);
            }

            WrittenFieldData[] output = new WrittenFieldData[definedFields.Length];

            for (int i = 0; i < definedFields.Length; i++)
            {
                STUInstanceField             field     = definedFields[i];
                STUInstanceJSON.STUFieldJSON jsonField = InstanceJSON[instanceChecksum].GetField(field.FieldChecksum);

                if (jsonField == null)
                {
                    Debugger.Log(0, "STULib",
                                 $"[Version2HashComparer]: Field {instanceChecksum:X}:{field.FieldChecksum:X} does not exist in the dataset\n");
                    continue;
                }

                WrittenFieldData outputField = new WrittenFieldData(jsonField);
                using (SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider()) {
                    /*switch (jsonField.SerializationType) {
                     *  case 2:
                     *  case 3:
                     *      reader.BaseStream.Position += field.FieldSize;
                     *      break;
                     *  case 4:
                     *  case 5:
                     *      reader.BaseStream.Position += reader.ReadUInt32();
                     *      // outputField.SHA1 = sha1.ComputeHash(BitConverter.GetBytes(jsonField.Size));
                     *      break;
                     *  case 8:
                     *  case 0:
                     *      outputField.SHA1 = sha1.ComputeHash(reader.ReadBytes((int) field.FieldSize));
                     *      break;
                     *  case 9:
                     *  case 1:
                     *      int offset = reader.ReadInt32();
                     *      metadata.Position = offset;
                     *      STUArrayInfo array = metadataReader.Read<STUArrayInfo>();
                     *      outputField.ArraySHA1 = new FieldSHA1[array.Count];
                     *      int arrayItemSize = 0; // todo
                     *      if (arrayItemSize == 0) {
                     *          break;
                     *      }
                     *      for (int j = 0; j < array.Count; j++) {
                     *          outputField.ArraySHA1[i] = sha1.ComputeHash(metadataReader.ReadBytes(arrayItemSize));
                     *      }
                     *      break;
                     *  case 7: // todo hashmap
                     *      Debugger.Break();
                     *      break;
                     *  case 10:
                     *  case 12:
                     *      Common.STUGUID f = new Common.STUGUID(reader.ReadUInt64());
                     *      DemangleInstance(f, field.FieldChecksum);
                     *      outputField.SHA1Demangle = sha1.ComputeHash(BitConverter.GetBytes(f));
                     *      break;
                     *  case 11:
                     *  case 13:
                     *      int offset2 = reader.ReadInt32();
                     *      metadata.Position = offset2;
                     *      STUArrayInfo array2 = metadataReader.Read<STUArrayInfo>();
                     *      outputField.ArraySHA1 = new FieldSHA1[array2.Count];
                     *      for (int j = 0; j < array2.Count; j++) {
                     *          FakeArrayGUID fakeArrayGUID = metadataReader.Read<FakeArrayGUID>();
                     *          Common.STUGUID f2 = new Common.STUGUID(fakeArrayGUID.Key, fakeArrayGUID.Padding);
                     *          DemangleInstance(f2, field.FieldChecksum);
                     *          outputField.ArraySHA1[j] = sha1.ComputeHash(BitConverter.GetBytes(f2));
                     *      }
                     *      break;
                     *  // case 10: // todo guid
                     *  // case 11: // todo guid array
                     *  //     break;
                     *
                     *  // case 0: Primitive
                     *  // case 1: STUArray<STU{stuField.Type}Primitive>
                     *  // case 2: STUEmbed<{stuField.Type}>    // ex chained
                     *  // case 3: STUArray<STUEmbed<{stuField.Type}>>
                     *  // case 4: STUInline<{stuField.Type}>  // ex nested
                     *  // case 5: STUArray<STUInline<{stuField.Type}>>
                     *  // case 7: STUHashMap<{stuField.Type}>
                     *  // case 8: Enums.{stuField.Type}?
                     *  // case 9: STUArray<Enums.{stuField.Type}?>
                     *  // case 10: STUAssetRef<ulong>
                     *  // case 11: STUArray<STUAssetRef<ulong>>
                     *  // case 12: STUAssetRef<{stuField.Type}>
                     *  // case 13: STUArray<STUAssetRef<{stuField.Type}>>
                     * }*/
                }
                output[i] = outputField;
            }

            return(output);
        }
Esempio n. 4
0
        private object GetValueArray(Type type, STUFieldAttribute element, STUArrayInfo info, STUInstanceField writtenField)
        {
            Array array = Array.CreateInstance(type, info.Count);

            for (uint i = 0; i < info.Count; ++i)
            {
                if (element != null)
                {
                    Metadata.Position += element.Padding;
                }

                uint parent = 0;
                if (InstanceArrayRef?.Length > info.InstanceIndex)
                {
                    parent = InstanceArrayRef[info.InstanceIndex].Checksum;
                }
                array.SetValue(GetValueArrayInner(type, element, parent, writtenField.FieldChecksum), i);
            }
            return(array);
        }
Esempio n. 5
0
        private object InitializeObjectArray(STUInstanceField field, Type type, BinaryReader reader, STUFieldAttribute element)
        {
            if (field.FieldSize == 0 && field.FieldChecksum != 0)
            {
                STUInlineArrayInfo inlineInfo = reader.Read <STUInlineArrayInfo>();
                if (inlineInfo.Size > 600000)
                {
                    return(null);                          // i feel that it's unlikley that there will be an inline with this count, exceptions if this isn't checked.
                }
                Array array = Array.CreateInstance(type, (uint)inlineInfo.Count);
                // if (inlineInfo.FieldListIndex == 0) return array;
                for (uint i = 0; i < (uint)inlineInfo.Count; ++i)
                {
                    Stream.Position += element.Padding;
                    uint   fieldIndex = reader.ReadUInt32();
                    object instance   = Activator.CreateInstance(type);
                    if (fieldIndex >= InstanceFieldLists.Length)
                    {
                        continue;
                    }
                    array.SetValue(InitializeObject(instance, type, InstanceFields[fieldIndex], reader), i);
                    STUInstance fieldInstance = array.GetValue(i) as STUInstance;
                    if (fieldInstance != null)
                    {
                        fieldInstance.Usage = InstanceUsage.InlineArray;
                    }
                    HiddenInstances.Add(fieldInstance);
                }
                return(array);
            }
            if (typeof(STUInstance).IsAssignableFrom(type))
            {
                int embedArrayOffset = reader.ReadInt32();
                Metadata.Position = embedArrayOffset;
                STUEmbedArrayInfo embedArrayInfo = MetadataReader.Read <STUEmbedArrayInfo>();

                if (embedArrayInfo.Count == 0)
                {
                    return(null);
                }
                Metadata.Position = embedArrayInfo.Offset;

                Array array = Array.CreateInstance(type, embedArrayInfo.Count);

                List <int> request = new List <int>();
                for (int i = 0; i < embedArrayInfo.Count; i++)
                {
                    int instanceIndex = MetadataReader.ReadInt32();
                    MetadataReader.ReadInt32(); // Padding
                    if (instanceIndex == -1)
                    {
                        return(null);
                    }
                    request.Add(instanceIndex);
                }
                EmbedArrayRequests[array] = request.ToArray();
                return(array);
            }
            int offset = reader.ReadInt32();

            Metadata.Position = offset;
            STUArrayInfo arrayInfo = MetadataReader.Read <STUArrayInfo>();

            Metadata.Position = arrayInfo.Offset;
            return(GetValueArray(type, element, arrayInfo, field));
        }
Esempio n. 6
0
        // ReSharper disable once UnusedParameter.Local
        private object GetValue(object fieldOwner, STUInstanceField field, Type type, BinaryReader reader, STUFieldAttribute element, FieldInfo fieldInfo)
        {
            if (type.IsArray)
            {
                return(InitializeObjectArray(field, type.GetElementType(), reader, element));
            }
            switch (type.Name)
            {
            case "String": {
                int stringPos = reader.ReadInt32();
                if (stringPos == -1)
                {
                    return(null);
                }
                Metadata.Position = stringPos;
                return(ReadMetadataString());
            }

            case "Single":
                return(reader.ReadSingle());

            case "Int16":
            case "UInt16":
            case "Int32":
            case "UInt32":
            case "Int64":
            case "UInt64":
            case "SByte":
            case "Byte":
            case "Char":
                return(GetPrimitiveVarValue(reader, field, type));

            case "Boolean":
                return((byte)GetPrimitiveVarValue(reader, field, typeof(byte)) != 0);

            case "Object":
                reader.BaseStream.Position += 4;
                return(null);

            default:
                if (type.GetInterfaces().Contains(typeof(ISTUCustomSerializable)))
                {
                    return(((ISTUCustomSerializable)Activator.CreateInstance(type)).Deserialize(fieldOwner, this, fieldInfo,
                                                                                                reader, MetadataReader));
                }
                if (typeof(STUInstance).IsAssignableFrom(type))
                {
                    return(null);    // Set later by the second pass. Usually this is uint, indicating which STU instance entry to load inorder to get the instance. However this is only useful when you're streaming specific STUs.
                }
                if (type.IsEnum)
                {
                    return(GetValue(fieldOwner, field, type.GetEnumUnderlyingType(), reader, element, null));
                }
                if (type.IsClass)
                {
                    return(InitializeObject(Activator.CreateInstance(type), type, field.FieldChecksum, field.FieldChecksum, reader, element.FakeBuffer, element.Demangle));
                }
                if (type.IsValueType)
                {
                    return(InitializeObject(Activator.CreateInstance(type), type, CreateInstanceFields(type),
                                            reader));
                }
                return(null);
            }
        }
Esempio n. 7
0
        private object GetPrimitiveVarValue(BinaryReader reader, STUInstanceField field, Type target)
        {
            object value  = 0;
            bool   signed = Convert.ToBoolean(target.GetField("MinValue").GetValue(null));
            uint   size   = field.FieldSize > 0 ? field.FieldSize : (uint)Marshal.SizeOf(target);

            if (size == 16)
            {
                value = reader.ReadDecimal();
            }
            if (!signed)
            {
                switch (size)
                {
                case 16: break;

                case 8:
                    value = reader.ReadUInt64();
                    break;

                case 4:
                    value = reader.ReadUInt32();
                    break;

                case 2:
                    value = reader.ReadUInt16();
                    break;

                case 1:
                    value = reader.ReadByte();
                    break;

                default: throw new InvalidDataException();
                }
            }
            else
            {
                switch (size)
                {
                case 16: break;

                case 8:
                    value = reader.ReadInt64();
                    break;

                case 4:
                    value = reader.ReadInt32();
                    break;

                case 2:
                    value = reader.ReadInt16();
                    break;

                case 1:
                    value = reader.ReadSByte();
                    break;

                default: throw new InvalidDataException();
                }
            }
            return(Convert.ChangeType(value, target)); // if you get an OverflowException, you need to use a bigger type
        }
Esempio n. 8
0
        public static void ListSTU(Stream file)
        {
            using (BinaryReader reader = new BinaryReader(file)) {
                STUHeader header = reader.Read <STUHeader>();

                Util.DumpStruct(header, "");
                Console.Out.WriteLine("{0} instances", header.InstanceCount);
                file.Position = header.InstanceListOffset;
                long totalSize = 0;
                for (uint i = 0; i < header.InstanceCount; ++i)
                {
                    STUInstanceRecord record = reader.Read <STUInstanceRecord>();
                    Console.Out.WriteLine("\t{0:X8} - {1:X8} - {2} - {3} bytes", record.InstanceChecksum, record.AssignFieldChecksum, record.AssignInstanceIndex, record.InstanceSize - 4);
                    long position = file.Position;
                    file.Position = header.Offset + totalSize;
                    int listIndex = reader.ReadInt32();
                    if (listIndex > -1 && (uint)listIndex >= header.InstanceFieldListCount)
                    {
                        throw new Exception();
                    }
                    Console.Out.WriteLine("\t\tfield list index {0:X}", listIndex);
                    file.Position = position;
                    totalSize    += record.InstanceSize;
                }
                Console.Out.WriteLine("Total: {0} bytes", totalSize);
                if (header.EntryInstanceCount > 0)
                {
                    Console.Out.WriteLine("{0} reference entries", header.EntryInstanceCount);
                    file.Position = header.EntryInstanceListOffset;
                    for (int i = (int)header.EntryInstanceCount; i > 0; --i)
                    {
                        STUInstanceField entry = reader.Read <STUInstanceField>();
                        Console.Out.WriteLine("\t\t{0:X8} - {1} bytes", entry.FieldChecksum, entry.FieldSize);
                    }
                }
                Console.Out.WriteLine("{0} variable lists", header.InstanceFieldListCount);
                file.Position = header.InstanceFieldListOffset;
                for (uint i = 0; i < header.InstanceFieldListCount; ++i)
                {
                    STUInstanceFieldList info = reader.Read <STUInstanceFieldList>();
                    Console.Out.WriteLine("\t{0} variables", info.FieldCount);
                    long tmp = file.Position;
                    file.Position = info.ListOffset;
                    totalSize     = 0;
                    for (uint j = 0; j < info.FieldCount; ++j)
                    {
                        STUInstanceField entry = reader.Read <STUInstanceField>();
                        Console.Out.WriteLine("\t\t{0:X8} - {1} bytes", entry.FieldChecksum, entry.FieldSize);
                        totalSize += entry.FieldSize;
                    }
                    Console.Out.WriteLine("\t\tTotal: {0} bytes", totalSize);
                    file.Position = tmp;
                }

                if (System.Diagnostics.Debugger.IsAttached)
                {
                    file.Position = 0;
                    ISTU stu = ISTU.NewInstance(file, uint.MaxValue);
                    System.Diagnostics.Debugger.Break();
                }
            }
        }