diff --git a/Il2CppInspector.Common/IL2CPP/Metadata.cs b/Il2CppInspector.Common/IL2CPP/Metadata.cs index 2254b07..00e14f6 100644 --- a/Il2CppInspector.Common/IL2CPP/Metadata.cs +++ b/Il2CppInspector.Common/IL2CPP/Metadata.cs @@ -134,15 +134,15 @@ namespace Il2CppInspector // as we do not have it available at this point. // thankfully, we can just guess the size based off the three available options and the known total size of // a type entry that uses TypeIndex. - var expectedEventDefinitionSize = Header.Events.SectionSize / Header.Events.Count; - var maxEventDefinitionSize = Il2CppEventDefinition.Size(tempVersion); + var actualSize = Header.InterfaceOffsets.SectionSize / Header.InterfaceOffsets.Count; + var maxSize = Il2CppEventDefinition.Size(tempVersion); int typeIndexSize; - if (expectedEventDefinitionSize == maxEventDefinitionSize) + if (actualSize == maxSize) typeIndexSize = sizeof(int); - else if (expectedEventDefinitionSize == maxEventDefinitionSize - 2) + else if (actualSize == maxSize - 2) typeIndexSize = sizeof(ushort); - else if (expectedEventDefinitionSize == maxEventDefinitionSize - 3) + else if (actualSize == maxSize - 3) typeIndexSize = sizeof(byte); else throw new InvalidOperationException("Could not determine TypeIndex size based on the metadata header"); @@ -173,6 +173,16 @@ namespace Il2CppInspector fullTag += $"_{MethodIndex.TagPrefix}{methodIndexSize}"; } + if (Version >= MetadataVersions.V1060) + { + var genericParameterIndexSize = GetIndexSize(Header.GenericParameters.Count); + var fieldIndexSize = GetIndexSize(Header.Fields.Count); + var defaultValueDataIndex = GetIndexSize(Header.FieldAndParameterDefaultValueData.Count); + fullTag += $"_{GenericParameterIndex.TagPrefix}{genericParameterIndexSize}" + + $"_{FieldIndex.TagPrefix}{fieldIndexSize}" + + $"_{DefaultValueDataIndex.TagPrefix}{defaultValueDataIndex}"; + } + Version = new StructVersion(Version.Major, Version.Minor, fullTag); } diff --git a/Il2CppInspector.Common/Next/Metadata/DefaultValueDataIndex.cs b/Il2CppInspector.Common/Next/Metadata/DefaultValueDataIndex.cs new file mode 100644 index 0000000..e69b56a --- /dev/null +++ b/Il2CppInspector.Common/Next/Metadata/DefaultValueDataIndex.cs @@ -0,0 +1,45 @@ +using VersionedSerialization; + +namespace Il2CppInspector.Next.Metadata; + +public struct DefaultValueDataIndex(int value) : IIndexType, IReadable, IEquatable +{ + public const string TagPrefix = nameof(DefaultValueDataIndex); + + static string IIndexType.TagPrefix => TagPrefix; + static StructVersion IIndexType.AddedVersion => MetadataVersions.V390; + + private int _value = value; + + public static int Size(in StructVersion version = default, bool is32Bit = false) + => IIndexType.IndexSize(version, is32Bit); + + public void Read(ref TReader reader, in StructVersion version = default) where TReader : IReader, allows ref struct + { + _value = IIndexType.ReadIndex(ref reader, in version); + } + + #region Operators + ToString + + public static implicit operator int(DefaultValueDataIndex idx) => idx._value; + public static implicit operator DefaultValueDataIndex(int idx) => new(idx); + + public static bool operator ==(DefaultValueDataIndex left, DefaultValueDataIndex right) + => left._value == right._value; + + public static bool operator !=(DefaultValueDataIndex left, DefaultValueDataIndex right) + => !(left == right); + + public readonly override bool Equals(object obj) + => obj is DefaultValueDataIndex other && Equals(other); + + public readonly bool Equals(DefaultValueDataIndex other) + => this == other; + + public readonly override int GetHashCode() + => HashCode.Combine(_value); + + public readonly override string ToString() => _value.ToString(); + + #endregion +} \ No newline at end of file diff --git a/Il2CppInspector.Common/Next/Metadata/FieldIndex.cs b/Il2CppInspector.Common/Next/Metadata/FieldIndex.cs new file mode 100644 index 0000000..d9050ed --- /dev/null +++ b/Il2CppInspector.Common/Next/Metadata/FieldIndex.cs @@ -0,0 +1,45 @@ +using VersionedSerialization; + +namespace Il2CppInspector.Next.Metadata; + +public struct FieldIndex(int value) : IIndexType, IReadable, IEquatable +{ + public const string TagPrefix = nameof(FieldIndex); + + static string IIndexType.TagPrefix => TagPrefix; + static StructVersion IIndexType.AddedVersion => MetadataVersions.V390; + + private int _value = value; + + public static int Size(in StructVersion version = default, bool is32Bit = false) + => IIndexType.IndexSize(version, is32Bit); + + public void Read(ref TReader reader, in StructVersion version = default) where TReader : IReader, allows ref struct + { + _value = IIndexType.ReadIndex(ref reader, in version); + } + + #region Operators + ToString + + public static implicit operator int(FieldIndex idx) => idx._value; + public static implicit operator FieldIndex(int idx) => new(idx); + + public static bool operator ==(FieldIndex left, FieldIndex right) + => left._value == right._value; + + public static bool operator !=(FieldIndex left, FieldIndex right) + => !(left == right); + + public readonly override bool Equals(object obj) + => obj is FieldIndex other && Equals(other); + + public readonly bool Equals(FieldIndex other) + => this == other; + + public readonly override int GetHashCode() + => HashCode.Combine(_value); + + public readonly override string ToString() => _value.ToString(); + + #endregion +} \ No newline at end of file diff --git a/Il2CppInspector.Common/Next/Metadata/GenericParameterIndex.cs b/Il2CppInspector.Common/Next/Metadata/GenericParameterIndex.cs new file mode 100644 index 0000000..dde565c --- /dev/null +++ b/Il2CppInspector.Common/Next/Metadata/GenericParameterIndex.cs @@ -0,0 +1,45 @@ +using VersionedSerialization; + +namespace Il2CppInspector.Next.Metadata; + +public struct GenericParameterIndex(int value) : IIndexType, IReadable, IEquatable +{ + public const string TagPrefix = nameof(GenericParameterIndex); + + static string IIndexType.TagPrefix => TagPrefix; + static StructVersion IIndexType.AddedVersion => MetadataVersions.V390; + + private int _value = value; + + public static int Size(in StructVersion version = default, bool is32Bit = false) + => IIndexType.IndexSize(version, is32Bit); + + public void Read(ref TReader reader, in StructVersion version = default) where TReader : IReader, allows ref struct + { + _value = IIndexType.ReadIndex(ref reader, in version); + } + + #region Operators + ToString + + public static implicit operator int(GenericParameterIndex idx) => idx._value; + public static implicit operator GenericParameterIndex(int idx) => new(idx); + + public static bool operator ==(GenericParameterIndex left, GenericParameterIndex right) + => left._value == right._value; + + public static bool operator !=(GenericParameterIndex left, GenericParameterIndex right) + => !(left == right); + + public readonly override bool Equals(object obj) + => obj is GenericParameterIndex other && Equals(other); + + public readonly bool Equals(GenericParameterIndex other) + => this == other; + + public readonly override int GetHashCode() + => HashCode.Combine(_value); + + public readonly override string ToString() => _value.ToString(); + + #endregion +} \ No newline at end of file diff --git a/Il2CppInspector.Common/Next/Metadata/Il2CppFieldDefaultValue.cs b/Il2CppInspector.Common/Next/Metadata/Il2CppFieldDefaultValue.cs index 4e98bd6..1150428 100644 --- a/Il2CppInspector.Common/Next/Metadata/Il2CppFieldDefaultValue.cs +++ b/Il2CppInspector.Common/Next/Metadata/Il2CppFieldDefaultValue.cs @@ -2,9 +2,6 @@ namespace Il2CppInspector.Next.Metadata; -using FieldIndex = int; -using DefaultValueDataIndex = int; - [VersionedStruct] public partial record struct Il2CppFieldDefaultValue { diff --git a/Il2CppInspector.Common/Next/Metadata/Il2CppFieldMarshaledSize.cs b/Il2CppInspector.Common/Next/Metadata/Il2CppFieldMarshaledSize.cs index eee0110..4ca39e5 100644 --- a/Il2CppInspector.Common/Next/Metadata/Il2CppFieldMarshaledSize.cs +++ b/Il2CppInspector.Common/Next/Metadata/Il2CppFieldMarshaledSize.cs @@ -1,7 +1,6 @@ namespace Il2CppInspector.Next.Metadata; using VersionedSerialization.Attributes; -using FieldIndex = int; [VersionedStruct] public partial record struct Il2CppFieldMarshaledSize diff --git a/Il2CppInspector.Common/Next/Metadata/Il2CppFieldRef.cs b/Il2CppInspector.Common/Next/Metadata/Il2CppFieldRef.cs index c83305b..381361e 100644 --- a/Il2CppInspector.Common/Next/Metadata/Il2CppFieldRef.cs +++ b/Il2CppInspector.Common/Next/Metadata/Il2CppFieldRef.cs @@ -2,8 +2,6 @@ namespace Il2CppInspector.Next.Metadata; -using FieldIndex = int; - [VersionedStruct] public partial record struct Il2CppFieldRef { diff --git a/Il2CppInspector.Common/Next/Metadata/Il2CppGenericContainer.cs b/Il2CppInspector.Common/Next/Metadata/Il2CppGenericContainer.cs index 54d4969..eb33941 100644 --- a/Il2CppInspector.Common/Next/Metadata/Il2CppGenericContainer.cs +++ b/Il2CppInspector.Common/Next/Metadata/Il2CppGenericContainer.cs @@ -1,13 +1,32 @@ -namespace Il2CppInspector.Next.Metadata; +using System.Runtime.InteropServices; + +namespace Il2CppInspector.Next.Metadata; using VersionedSerialization.Attributes; -using GenericParameterIndex = int; [VersionedStruct] +[StructLayout(LayoutKind.Explicit)] public partial record struct Il2CppGenericContainer { + [field: FieldOffset(0)] public int OwnerIndex { get; private set; } + + [VersionCondition(LessThan = "105.0")] + [field: FieldOffset(4)] public int TypeArgc { get; private set; } + + [VersionCondition(LessThan = "105.0")] + [field: FieldOffset(8)] public int IsMethod { get; private set; } + + [field: FieldOffset(12)] public GenericParameterIndex GenericParameterStart { get; private set; } + + [VersionCondition(GreaterThan = "106.0")] + [field: FieldOffset(4)] + private ushort _newTypeArgc; + + [VersionCondition(LessThan = "106.0")] + [field: FieldOffset(8)] + public byte _newIsMethod; } \ No newline at end of file diff --git a/Il2CppInspector.Common/Next/Metadata/Il2CppParameterDefaultValue.cs b/Il2CppInspector.Common/Next/Metadata/Il2CppParameterDefaultValue.cs index 4556cf5..7eabd97 100644 --- a/Il2CppInspector.Common/Next/Metadata/Il2CppParameterDefaultValue.cs +++ b/Il2CppInspector.Common/Next/Metadata/Il2CppParameterDefaultValue.cs @@ -1,6 +1,5 @@ namespace Il2CppInspector.Next.Metadata; -using DefaultValueDataIndex = int; using VersionedSerialization.Attributes; [VersionedStruct] diff --git a/Il2CppInspector.Common/Next/Metadata/Il2CppTypeDefinition.cs b/Il2CppInspector.Common/Next/Metadata/Il2CppTypeDefinition.cs index be4cf84..70852d0 100644 --- a/Il2CppInspector.Common/Next/Metadata/Il2CppTypeDefinition.cs +++ b/Il2CppInspector.Common/Next/Metadata/Il2CppTypeDefinition.cs @@ -5,7 +5,6 @@ using VersionedSerialization.Attributes; namespace Il2CppInspector.Next.Metadata; using StringIndex = int; -using FieldIndex = int; using VTableIndex = int; [VersionedStruct] diff --git a/Il2CppInspector.Common/Next/MetadataVersions.cs b/Il2CppInspector.Common/Next/MetadataVersions.cs index f39f361..e5693cb 100644 --- a/Il2CppInspector.Common/Next/MetadataVersions.cs +++ b/Il2CppInspector.Common/Next/MetadataVersions.cs @@ -48,4 +48,9 @@ public static class MetadataVersions // Unity 6000.5.0a5 public static readonly StructVersion V1050 = new(105); // NOTE: This version additionally uses a tag to specify the size of MethodIndex. + + // Unity 6000.5.0a6 + public static readonly StructVersion V1060 = new(106); + // NOTE: This version additionally uses tags to specify the size of GenericParameterIndex, FieldIndex, DefaultValueDataIndex, + // alongside changing TypeArgc to a ushort and IsMethod to a byte in Il2CppGenericContainer. } \ No newline at end of file