add support for metadata v106 and fix support for detecting TypeIndex size

This commit is contained in:
LukeFZ
2026-02-09 20:02:09 +01:00
parent 584f0be399
commit bf2cedd8d1
11 changed files with 176 additions and 15 deletions

View File

@@ -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);
}

View File

@@ -0,0 +1,45 @@
using VersionedSerialization;
namespace Il2CppInspector.Next.Metadata;
public struct DefaultValueDataIndex(int value) : IIndexType<DefaultValueDataIndex>, IReadable, IEquatable<DefaultValueDataIndex>
{
public const string TagPrefix = nameof(DefaultValueDataIndex);
static string IIndexType<DefaultValueDataIndex>.TagPrefix => TagPrefix;
static StructVersion IIndexType<DefaultValueDataIndex>.AddedVersion => MetadataVersions.V390;
private int _value = value;
public static int Size(in StructVersion version = default, bool is32Bit = false)
=> IIndexType<DefaultValueDataIndex>.IndexSize(version, is32Bit);
public void Read<TReader>(ref TReader reader, in StructVersion version = default) where TReader : IReader, allows ref struct
{
_value = IIndexType<DefaultValueDataIndex>.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
}

View File

@@ -0,0 +1,45 @@
using VersionedSerialization;
namespace Il2CppInspector.Next.Metadata;
public struct FieldIndex(int value) : IIndexType<FieldIndex>, IReadable, IEquatable<FieldIndex>
{
public const string TagPrefix = nameof(FieldIndex);
static string IIndexType<FieldIndex>.TagPrefix => TagPrefix;
static StructVersion IIndexType<FieldIndex>.AddedVersion => MetadataVersions.V390;
private int _value = value;
public static int Size(in StructVersion version = default, bool is32Bit = false)
=> IIndexType<FieldIndex>.IndexSize(version, is32Bit);
public void Read<TReader>(ref TReader reader, in StructVersion version = default) where TReader : IReader, allows ref struct
{
_value = IIndexType<FieldIndex>.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
}

View File

@@ -0,0 +1,45 @@
using VersionedSerialization;
namespace Il2CppInspector.Next.Metadata;
public struct GenericParameterIndex(int value) : IIndexType<GenericParameterIndex>, IReadable, IEquatable<GenericParameterIndex>
{
public const string TagPrefix = nameof(GenericParameterIndex);
static string IIndexType<GenericParameterIndex>.TagPrefix => TagPrefix;
static StructVersion IIndexType<GenericParameterIndex>.AddedVersion => MetadataVersions.V390;
private int _value = value;
public static int Size(in StructVersion version = default, bool is32Bit = false)
=> IIndexType<GenericParameterIndex>.IndexSize(version, is32Bit);
public void Read<TReader>(ref TReader reader, in StructVersion version = default) where TReader : IReader, allows ref struct
{
_value = IIndexType<GenericParameterIndex>.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
}

View File

@@ -2,9 +2,6 @@
namespace Il2CppInspector.Next.Metadata;
using FieldIndex = int;
using DefaultValueDataIndex = int;
[VersionedStruct]
public partial record struct Il2CppFieldDefaultValue
{

View File

@@ -1,7 +1,6 @@
namespace Il2CppInspector.Next.Metadata;
using VersionedSerialization.Attributes;
using FieldIndex = int;
[VersionedStruct]
public partial record struct Il2CppFieldMarshaledSize

View File

@@ -2,8 +2,6 @@
namespace Il2CppInspector.Next.Metadata;
using FieldIndex = int;
[VersionedStruct]
public partial record struct Il2CppFieldRef
{

View File

@@ -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;
}

View File

@@ -1,6 +1,5 @@
namespace Il2CppInspector.Next.Metadata;
using DefaultValueDataIndex = int;
using VersionedSerialization.Attributes;
[VersionedStruct]

View File

@@ -5,7 +5,6 @@ using VersionedSerialization.Attributes;
namespace Il2CppInspector.Next.Metadata;
using StringIndex = int;
using FieldIndex = int;
using VTableIndex = int;
[VersionedStruct]

View File

@@ -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.
}