Skip to content

Commit b012807

Browse files
committed
Merge PR Perfare#903: Add support for metadata v35-v39 (Unity 6)
Cherry-picks from roytu/Il2CppDumper:v39 (Perfare PR Perfare#903, unmerged upstream). Adds parser support for global-metadata.dat versions 32 through 39, including Unity 6000 family. Source PR is mergeable-clean against upstream master (4741d46, last upstream commit 2024-07-06). Adopted in lxraa fork because upstream Il2CppDumper has been inactive since 2024-08; PR sat unreviewed for >2 months. Verified locally as part of the reverse-engineering pipeline (Il2CppDumper consumer in stage5 unity handler).
2 parents 4741d46 + 540425f commit b012807

13 files changed

Lines changed: 754 additions & 217 deletions

Il2CppDumper/IO/BinaryStream.cs

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,144 @@ private object ReadPrimitive(Type type)
112112
return ReadClass<T>();
113113
}
114114

115+
public TypeIndex ReadTypeIndex()
116+
{
117+
if (Version < 35)
118+
{
119+
// Before Version 35, these were always Int32
120+
int value = ReadInt32();
121+
return new TypeIndex(value);
122+
}
123+
else
124+
{
125+
switch (Metadata.typeIndexSize)
126+
{
127+
case 1:
128+
{
129+
uint value = ReadByte();
130+
if (value == Byte.MaxValue) return new TypeIndex(-1);
131+
return new TypeIndex((int)value);
132+
}
133+
case 2:
134+
{
135+
uint value = ReadUInt16();
136+
if (value == UInt16.MaxValue) return new TypeIndex(-1);
137+
return new TypeIndex((int)value);
138+
}
139+
case 4:
140+
default:
141+
{
142+
uint value = ReadUInt32();
143+
if (value == UInt32.MaxValue) return new TypeIndex(-1);
144+
return new TypeIndex((int)value);
145+
}
146+
}
147+
}
148+
}
149+
150+
public TypeDefinitionIndex ReadTypeDefinitionIndex()
151+
{
152+
if (Version < 35)
153+
{
154+
// Before Version 35, these were always Int32
155+
int value = ReadInt32();
156+
return new TypeDefinitionIndex(value);
157+
}
158+
else
159+
{
160+
switch (Metadata.typeDefinitionIndexSize)
161+
{
162+
case 1:
163+
{
164+
uint value = ReadByte();
165+
if (value == Byte.MaxValue) return new TypeDefinitionIndex(-1);
166+
return new TypeDefinitionIndex((int)value);
167+
}
168+
case 2:
169+
{
170+
uint value = ReadUInt16();
171+
if (value == UInt16.MaxValue) return new TypeDefinitionIndex(-1);
172+
return new TypeDefinitionIndex((int)value);
173+
}
174+
case 4:
175+
default:
176+
{
177+
uint value = ReadUInt32();
178+
if (value == UInt32.MaxValue) return new TypeDefinitionIndex(-1);
179+
return new TypeDefinitionIndex((int)value);
180+
}
181+
}
182+
}
183+
}
184+
public GenericContainerIndex ReadGenericContainerIndex()
185+
{
186+
if (Version < 35)
187+
{
188+
// Before Version 35, these were always Int32
189+
int value = ReadInt32();
190+
return new GenericContainerIndex(value);
191+
}
192+
else
193+
{
194+
switch (Metadata.genericContainerIndexSize)
195+
{
196+
case 1:
197+
{
198+
uint value = ReadByte();
199+
if (value == Byte.MaxValue) return new GenericContainerIndex(-1);
200+
return new GenericContainerIndex((int)value);
201+
}
202+
case 2:
203+
{
204+
uint value = ReadUInt16();
205+
if (value == UInt16.MaxValue) return new GenericContainerIndex(-1);
206+
return new GenericContainerIndex((int)value);
207+
}
208+
case 4:
209+
default:
210+
{
211+
uint value = ReadUInt32();
212+
if (value == UInt32.MaxValue) return new GenericContainerIndex(-1);
213+
return new GenericContainerIndex((int)value);
214+
}
215+
}
216+
}
217+
}
218+
public ParameterIndex ReadParameterIndex()
219+
{
220+
if (Version < 39)
221+
{
222+
// Before Version 39, these were always Int32
223+
int value = ReadInt32();
224+
return new ParameterIndex(value);
225+
}
226+
else
227+
{
228+
switch (Metadata.parameterIndexSize)
229+
{
230+
case 1:
231+
{
232+
uint value = ReadByte();
233+
if (value == Byte.MaxValue) return new ParameterIndex(-1);
234+
return new ParameterIndex((int)value);
235+
}
236+
case 2:
237+
{
238+
uint value = ReadUInt16();
239+
if (value == UInt16.MaxValue) return new ParameterIndex(-1);
240+
return new ParameterIndex((int)value);
241+
}
242+
case 4:
243+
default:
244+
{
245+
uint value = ReadUInt32();
246+
if (value == UInt32.MaxValue) return new ParameterIndex(-1);
247+
return new ParameterIndex((int)value);
248+
}
249+
}
250+
}
251+
}
252+
115253
public T ReadClass<T>() where T : new()
116254
{
117255
var type = typeof(T);
@@ -168,6 +306,26 @@ private object ReadPrimitive(Type type)
168306
}
169307
i.SetValue(t, methodInfo.Invoke(this, new object[] { arrayLengthAttribute.Length }));
170308
}
309+
else if (fieldType == typeof(TypeIndex))
310+
{
311+
i.SetValue(t, ReadTypeIndex());
312+
}
313+
else if (fieldType == typeof(TypeDefinitionIndex))
314+
{
315+
i.SetValue(t, ReadTypeDefinitionIndex());
316+
}
317+
else if (fieldType == typeof(GenericContainerIndex))
318+
{
319+
i.SetValue(t, ReadGenericContainerIndex());
320+
}
321+
else if (fieldType == typeof(ParameterIndex))
322+
{
323+
i.SetValue(t, ReadParameterIndex());
324+
}
325+
else if (fieldType == typeof(Il2CppSectionMetadata))
326+
{
327+
i.SetValue(t, ReadClass<Il2CppSectionMetadata>());
328+
}
171329
else
172330
{
173331
if (!genericMethodCache.TryGetValue(fieldType, out var methodInfo))

Il2CppDumper/Il2Cpp/Il2Cpp.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ namespace Il2CppDumper
77
{
88
public abstract class Il2Cpp : BinaryStream
99
{
10-
private Il2CppMetadataRegistration pMetadataRegistration;
10+
public Il2CppMetadataRegistration pMetadataRegistration;
1111
private Il2CppCodeRegistration pCodeRegistration;
1212
public ulong[] methodPointers;
1313
public ulong[] genericMethodPointers;

Il2CppDumper/Il2Cpp/Il2CppClass.cs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
using System;
2+
using System.Linq;
3+
using System.Reflection;
24

35
namespace Il2CppDumper
46
{
@@ -63,6 +65,41 @@ public class Il2CppCodeRegistration
6365
public ulong codeGenModulesCount;
6466
[Version(Min = 24.2)]
6567
public ulong codeGenModules;
68+
69+
public static ulong Size(double version)
70+
{
71+
ulong size = 0;
72+
foreach (var field in typeof(Il2CppCodeRegistration).GetFields()) {
73+
// Check if the field exists in our version
74+
var versionAttributes = field.GetCustomAttributes<VersionAttribute>().ToArray();
75+
if (versionAttributes?.Length > 0)
76+
{
77+
var isInVersionRange = false;
78+
foreach (var versionAttribute in versionAttributes)
79+
{
80+
if (versionAttribute.Min <= version && version <= versionAttribute.Max)
81+
{
82+
isInVersionRange = true;
83+
break;
84+
}
85+
}
86+
if (!isInVersionRange)
87+
{
88+
continue;
89+
}
90+
}
91+
92+
if (field.FieldType == typeof(byte) || field.FieldType == typeof(sbyte))
93+
size += sizeof(byte);
94+
if (field.FieldType == typeof(long) || field.FieldType == typeof(ulong))
95+
size += sizeof(ulong);
96+
if (field.FieldType == typeof(int) || field.FieldType == typeof(uint))
97+
size += sizeof(uint);
98+
if (field.FieldType == typeof(short) || field.FieldType == typeof(ushort))
99+
size += sizeof(ushort);
100+
}
101+
return size;
102+
}
66103
}
67104

68105
public class Il2CppMetadataRegistration

0 commit comments

Comments
 (0)