C++: Many small quality-of-life code improvements
This commit is contained in:
@@ -4,6 +4,7 @@
|
|||||||
All rights reserved.
|
All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Il2CppInspector.Cpp.UnityHeaders;
|
using Il2CppInspector.Cpp.UnityHeaders;
|
||||||
@@ -40,20 +41,30 @@ namespace Il2CppInspector.Cpp
|
|||||||
public List<Export> Exports { get; }
|
public List<Export> Exports { get; }
|
||||||
public int WordSize => ILModel.Package.BinaryImage.Bits;
|
public int WordSize => ILModel.Package.BinaryImage.Bits;
|
||||||
|
|
||||||
public CppApplicationModel(Il2CppModel model, UnityVersion unityVersion, CppCompiler.Type compiler = CppCompiler.Type.BinaryFormat) {
|
public CppApplicationModel(Il2CppModel model, UnityVersion unityVersion = null, CppCompiler.Type compiler = CppCompiler.Type.BinaryFormat) {
|
||||||
// Set key properties
|
// Set key properties
|
||||||
Compiler = compiler == CppCompiler.Type.BinaryFormat ? CppCompiler.GuessFromImage(model.Package.BinaryImage) : compiler;
|
Compiler = compiler == CppCompiler.Type.BinaryFormat ? CppCompiler.GuessFromImage(model.Package.BinaryImage) : compiler;
|
||||||
UnityVersion = unityVersion;
|
|
||||||
|
var unityHeader = unityVersion != null ? UnityHeader.GetHeaderForVersion(unityVersion) : UnityHeader.GuessHeadersForModel(model)[0];
|
||||||
|
|
||||||
|
UnityVersion = unityVersion ?? unityHeader.MinVersion;
|
||||||
ILModel = model;
|
ILModel = model;
|
||||||
|
|
||||||
|
// Check for matching metadata and binary versions
|
||||||
|
if (unityHeader.MetadataVersion != model.Package.BinaryImage.Version) {
|
||||||
|
Console.WriteLine($"Warning: selected version {UnityVersion} (metadata version {unityHeader.MetadataVersion})" +
|
||||||
|
$" does not match metadata version {model.Package.BinaryImage.Version}.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get addresses of IL2CPP API function exports
|
||||||
|
Exports = model.Package.Binary.Image.GetExports().ToList();
|
||||||
|
|
||||||
// Start creation of type model by parsing all of the Unity IL2CPP headers
|
// Start creation of type model by parsing all of the Unity IL2CPP headers
|
||||||
Types = CppTypes.FromUnityVersion(unityVersion, WordSize);
|
Types = CppTypes.FromUnityHeaders(unityHeader, WordSize);
|
||||||
|
|
||||||
// TODO: Process every type in the binary
|
// TODO: Process every type in the binary
|
||||||
var decl = new CppDeclarationGenerator(ILModel, UnityVersion);
|
//var decl = new CppDeclarationGenerator(this);
|
||||||
|
|
||||||
// Add addresses of IL2CPP API function exports
|
|
||||||
Exports = model.Package.Binary.Image.GetExports().ToList();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,10 +10,16 @@ namespace Il2CppInspector.Cpp
|
|||||||
public class CppField
|
public class CppField
|
||||||
{
|
{
|
||||||
// The name of the field
|
// The name of the field
|
||||||
public string Name { get; set; }
|
public string Name { get; }
|
||||||
|
|
||||||
|
// The type of the field
|
||||||
|
public CppType Type { get; }
|
||||||
|
|
||||||
// The offset of the field into the type
|
// The offset of the field into the type
|
||||||
public int Offset { get; set; }
|
public int Offset { get; internal set; }
|
||||||
|
|
||||||
|
// The size of the field in bits
|
||||||
|
public int BitfieldSize { get; }
|
||||||
|
|
||||||
// The offset of the field into the type in bytes
|
// The offset of the field into the type in bytes
|
||||||
public int OffsetBytes => Offset / 8;
|
public int OffsetBytes => Offset / 8;
|
||||||
@@ -23,17 +29,18 @@ namespace Il2CppInspector.Cpp
|
|||||||
|
|
||||||
public int SizeBytes => (Size / 8) + (Size % 8 > 0 ? 1 : 0);
|
public int SizeBytes => (Size / 8) + (Size % 8 > 0 ? 1 : 0);
|
||||||
|
|
||||||
// The size of the field in bits
|
|
||||||
public int BitfieldSize { get; set; }
|
|
||||||
|
|
||||||
// The LSB of the bitfield
|
// The LSB of the bitfield
|
||||||
public int BitfieldLSB => Offset % 8;
|
public int BitfieldLSB => Offset % 8;
|
||||||
|
|
||||||
// The MSB of the bitfield
|
// The MSB of the bitfield
|
||||||
public int BitfieldMSB => BitfieldLSB + Size - 1;
|
public int BitfieldMSB => BitfieldLSB + Size - 1;
|
||||||
|
|
||||||
// The type of the field
|
// Initialize field
|
||||||
public CppType Type { get; set; }
|
public CppField(string name, CppType type, int bitfieldSize = 0) {
|
||||||
|
Name = name;
|
||||||
|
Type = type;
|
||||||
|
BitfieldSize = bitfieldSize;
|
||||||
|
}
|
||||||
|
|
||||||
// C++ representation of field
|
// C++ representation of field
|
||||||
public virtual string ToString(string format = "") {
|
public virtual string ToString(string format = "") {
|
||||||
@@ -67,7 +74,9 @@ namespace Il2CppInspector.Cpp
|
|||||||
public class CppEnumField : CppField
|
public class CppEnumField : CppField
|
||||||
{
|
{
|
||||||
// The value of this key name
|
// The value of this key name
|
||||||
public ulong Value { get; set; }
|
public ulong Value { get; }
|
||||||
|
|
||||||
|
public CppEnumField(string name, CppType type, ulong value) : base(name, type) => Value = value;
|
||||||
|
|
||||||
public override string ToString(string format = "") => Name + " = " + Value;
|
public override string ToString(string format = "") => Name + " = " + Value;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,8 +16,8 @@ using Il2CppInspector.Cpp.UnityHeaders;
|
|||||||
|
|
||||||
namespace Il2CppInspector.Cpp
|
namespace Il2CppInspector.Cpp
|
||||||
{
|
{
|
||||||
// Compound type
|
// Value type with fields
|
||||||
public enum CompoundType
|
public enum ComplexValueType
|
||||||
{
|
{
|
||||||
Struct,
|
Struct,
|
||||||
Union,
|
Union,
|
||||||
@@ -50,6 +50,11 @@ namespace Il2CppInspector.Cpp
|
|||||||
// Generate typedef to this type
|
// Generate typedef to this type
|
||||||
public CppAlias AsAlias(string Name) => new CppAlias(Name, this);
|
public CppAlias AsAlias(string Name) => new CppAlias(Name, this);
|
||||||
|
|
||||||
|
// Helper factories
|
||||||
|
public static CppComplexType NewStruct(string name = "") => new CppComplexType(ComplexValueType.Struct) {Name = name};
|
||||||
|
public static CppComplexType NewUnion(string name = "") => new CppComplexType(ComplexValueType.Union) {Name = name};
|
||||||
|
public static CppEnumType NewEnum(CppType underlyingType, string name = "") => new CppEnumType(underlyingType) {Name = name};
|
||||||
|
|
||||||
public virtual string ToString(string format = "") => format == "o" ? $"/* {SizeBytes:x2} - {Name} */" : $"/* {Name} */";
|
public virtual string ToString(string format = "") => format == "o" ? $"/* {SizeBytes:x2} - {Name} */" : $"/* {Name} */";
|
||||||
|
|
||||||
public override string ToString() => ToString();
|
public override string ToString() => ToString();
|
||||||
@@ -173,12 +178,7 @@ namespace Il2CppInspector.Cpp
|
|||||||
var baseOffset = field.Offset;
|
var baseOffset = field.Offset;
|
||||||
var fields = ct.Flattened.Fields.Select(kl => new {
|
var fields = ct.Flattened.Fields.Select(kl => new {
|
||||||
Key = kl.Key + baseOffset,
|
Key = kl.Key + baseOffset,
|
||||||
Value = kl.Value.Select(f => new CppField {
|
Value = kl.Value.Select(f => new CppField(f.Name, f.Type, f.BitfieldSize) { Offset = f.Offset + baseOffset }).ToList()
|
||||||
Name = f.Name,
|
|
||||||
Type = f.Type,
|
|
||||||
BitfieldSize = f.BitfieldSize,
|
|
||||||
Offset = f.Offset + baseOffset
|
|
||||||
}).ToList()
|
|
||||||
}).ToDictionary(kv => kv.Key, kv => kv.Value);
|
}).ToDictionary(kv => kv.Key, kv => kv.Value);
|
||||||
|
|
||||||
flattened = new SortedDictionary<int, List<CppField>>(flattened.Union(fields).ToDictionary(kv => kv.Key, kv => kv.Value));
|
flattened = new SortedDictionary<int, List<CppField>>(flattened.Union(fields).ToDictionary(kv => kv.Key, kv => kv.Value));
|
||||||
@@ -211,17 +211,17 @@ namespace Il2CppInspector.Cpp
|
|||||||
}
|
}
|
||||||
|
|
||||||
// The compound type
|
// The compound type
|
||||||
public CompoundType CompoundType;
|
public ComplexValueType ComplexValueType;
|
||||||
|
|
||||||
// Dictionary of byte offset in the type to each field
|
// Dictionary of byte offset in the type to each field
|
||||||
// Unions and bitfields can have more than one field at the same offset
|
// Unions and bitfields can have more than one field at the same offset
|
||||||
public SortedDictionary<int, List<CppField>> Fields { get; internal set; } = new SortedDictionary<int, List<CppField>>();
|
public SortedDictionary<int, List<CppField>> Fields { get; internal set; } = new SortedDictionary<int, List<CppField>>();
|
||||||
|
|
||||||
public CppComplexType(CompoundType compoundType) : base("", 0) => CompoundType = compoundType;
|
public CppComplexType(ComplexValueType complexValueType) : base("", 0) => ComplexValueType = complexValueType;
|
||||||
|
|
||||||
// Size can't be calculated lazily (as we go along adding fields) because of forward declarations
|
// Size can't be calculated lazily (as we go along adding fields) because of forward declarations
|
||||||
public override int Size =>
|
public override int Size =>
|
||||||
CompoundType == CompoundType.Union
|
ComplexValueType == ComplexValueType.Union
|
||||||
// Union size is the size of the largest element in the union
|
// Union size is the size of the largest element in the union
|
||||||
? Fields.Values.SelectMany(f => f).Select(f => f.Size).Max()
|
? Fields.Values.SelectMany(f => f).Select(f => f.Size).Max()
|
||||||
// For structs we look for the last item and add the size;
|
// For structs we look for the last item and add the size;
|
||||||
@@ -231,7 +231,7 @@ namespace Il2CppInspector.Cpp
|
|||||||
// Add a field to the type. Returns the offset of the field in the type
|
// Add a field to the type. Returns the offset of the field in the type
|
||||||
public int AddField(CppField field, int alignmentBytes = 0) {
|
public int AddField(CppField field, int alignmentBytes = 0) {
|
||||||
// Unions and enums always have an offset of zero
|
// Unions and enums always have an offset of zero
|
||||||
field.Offset = CompoundType == CompoundType.Struct ? Size : 0;
|
field.Offset = ComplexValueType == ComplexValueType.Struct ? Size : 0;
|
||||||
|
|
||||||
// If we just came out of a bitfield, move to the next byte if necessary
|
// If we just came out of a bitfield, move to the next byte if necessary
|
||||||
if (field.BitfieldSize == 0 && field.Offset % 8 != 0)
|
if (field.BitfieldSize == 0 && field.Offset % 8 != 0)
|
||||||
@@ -249,25 +249,23 @@ namespace Il2CppInspector.Cpp
|
|||||||
return Size;
|
return Size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add a field to the type
|
||||||
|
public int AddField(string name, CppType type, int alignmentBytes = 0, int bitfield = 0)
|
||||||
|
=> AddField(new CppField(name, type, bitfield), alignmentBytes);
|
||||||
|
|
||||||
// Summarize all field names and offsets
|
// Summarize all field names and offsets
|
||||||
public override string ToString(string format = "") {
|
public override string ToString(string format = "") {
|
||||||
var sb = new StringBuilder();
|
var sb = new StringBuilder();
|
||||||
|
|
||||||
if (Name.Length > 0)
|
if (Name.Length > 0)
|
||||||
sb.Append("typedef ");
|
sb.Append("typedef ");
|
||||||
sb.Append(CompoundType == CompoundType.Struct ? "struct " : CompoundType == CompoundType.Enum? "enum " : "union ");
|
sb.Append(ComplexValueType == ComplexValueType.Struct ? "struct " : "union ");
|
||||||
sb.Append(Name + (Name.Length > 0 ? " " : ""));
|
sb.Append(Name + (Name.Length > 0 ? " " : ""));
|
||||||
|
|
||||||
var delimiter = CompoundType == CompoundType.Enum ? "," : ";";
|
|
||||||
|
|
||||||
if (Fields.Any()) {
|
if (Fields.Any()) {
|
||||||
sb.Append("{");
|
sb.Append("{");
|
||||||
foreach (var field in Fields.Values.SelectMany(f => f))
|
foreach (var field in Fields.Values.SelectMany(f => f))
|
||||||
sb.Append("\n\t" + string.Join("\n\t", field.ToString(format).Split('\n')) + delimiter);
|
sb.Append("\n\t" + string.Join("\n\t", field.ToString(format).Split('\n')) + ";");
|
||||||
|
|
||||||
// Chop off final comma
|
|
||||||
if (CompoundType == CompoundType.Enum)
|
|
||||||
sb = sb.Remove(sb.Length - 1, 1);
|
|
||||||
|
|
||||||
sb.Append($"\n}}{(Name.Length > 0? " " + Name : "")}{(format == "o"? $" /* Size: 0x{SizeBytes:x2} */" : "")};");
|
sb.Append($"\n}}{(Name.Length > 0? " " + Name : "")}{(format == "o"? $" /* Size: 0x{SizeBytes:x2} */" : "")};");
|
||||||
}
|
}
|
||||||
@@ -279,4 +277,39 @@ namespace Il2CppInspector.Cpp
|
|||||||
return sb.ToString();
|
return sb.ToString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Enumeration type
|
||||||
|
public class CppEnumType : CppComplexType
|
||||||
|
{
|
||||||
|
// The underlying type of the enum
|
||||||
|
public CppType UnderlyingType { get; }
|
||||||
|
|
||||||
|
public override int Size => UnderlyingType.Size;
|
||||||
|
|
||||||
|
public CppEnumType(CppType underlyingType) : base(ComplexValueType.Enum) => UnderlyingType = underlyingType;
|
||||||
|
|
||||||
|
public void AddField(string name, ulong value) => AddField(new CppEnumField(name, UnderlyingType, value));
|
||||||
|
|
||||||
|
public override string ToString(string format = "") {
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
|
||||||
|
sb.Append($"typedef enum {Name} : {UnderlyingType.Name}");
|
||||||
|
|
||||||
|
if (Fields.Any()) {
|
||||||
|
sb.Append(" {");
|
||||||
|
foreach (var field in Fields.Values.SelectMany(f => f))
|
||||||
|
sb.Append("\n\t" + string.Join("\n\t", field.ToString(format).Split('\n')) + ",");
|
||||||
|
|
||||||
|
// Chop off final comma
|
||||||
|
sb = sb.Remove(sb.Length - 1, 1);
|
||||||
|
sb.Append($"\n}} {Name}{(format == "o"? $" /* Size: 0x{SizeBytes:x2} */" : "")};");
|
||||||
|
}
|
||||||
|
// Forward declaration
|
||||||
|
else {
|
||||||
|
sb.Append($"{Name};");
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -198,7 +198,7 @@ namespace Il2CppInspector.Cpp
|
|||||||
if (externDecl.Success) {
|
if (externDecl.Success) {
|
||||||
var declType = externDecl.Groups[1].Captures[0].ToString();
|
var declType = externDecl.Groups[1].Captures[0].ToString();
|
||||||
|
|
||||||
Types.Add(declType, new CppComplexType(CompoundType.Struct) {Name = declType});
|
Types.Add(declType, CppType.NewStruct(declType));
|
||||||
|
|
||||||
Debug.WriteLine($"[EXTERN DECL ] {line}");
|
Debug.WriteLine($"[EXTERN DECL ] {line}");
|
||||||
continue;
|
continue;
|
||||||
@@ -213,7 +213,7 @@ namespace Il2CppInspector.Cpp
|
|||||||
|
|
||||||
// Sometimes we might get multiple forward declarations for the same type
|
// Sometimes we might get multiple forward declarations for the same type
|
||||||
if (!Types.ContainsKey(declType))
|
if (!Types.ContainsKey(declType))
|
||||||
Types.Add(declType, new CppComplexType(CompoundType.Struct) {Name = declType});
|
Types.Add(declType, CppType.NewStruct(declType));
|
||||||
|
|
||||||
// Sometimes the alias might be the same name as the type (this is usually the case)
|
// Sometimes the alias might be the same name as the type (this is usually the case)
|
||||||
if (!Types.ContainsKey(alias))
|
if (!Types.ContainsKey(alias))
|
||||||
@@ -261,7 +261,7 @@ namespace Il2CppInspector.Cpp
|
|||||||
// typedef struct <optional-type-name>
|
// typedef struct <optional-type-name>
|
||||||
if ((line.StartsWith("typedef struct") || line.StartsWith("struct ")) && line.IndexOf(";", StringComparison.Ordinal) == -1
|
if ((line.StartsWith("typedef struct") || line.StartsWith("struct ")) && line.IndexOf(";", StringComparison.Ordinal) == -1
|
||||||
&& currentType.Count == 0) {
|
&& currentType.Count == 0) {
|
||||||
currentType.Push(new CppComplexType(CompoundType.Struct));
|
currentType.Push(CppType.NewStruct());
|
||||||
|
|
||||||
if (line.StartsWith("struct "))
|
if (line.StartsWith("struct "))
|
||||||
currentType.Peek().Name = line.Split(' ')[1];
|
currentType.Peek().Name = line.Split(' ')[1];
|
||||||
@@ -273,7 +273,7 @@ namespace Il2CppInspector.Cpp
|
|||||||
// Start of union
|
// Start of union
|
||||||
// typedef union <optional-type-name>
|
// typedef union <optional-type-name>
|
||||||
if (line.StartsWith("typedef union") && line.IndexOf(";", StringComparison.Ordinal) == -1) {
|
if (line.StartsWith("typedef union") && line.IndexOf(";", StringComparison.Ordinal) == -1) {
|
||||||
currentType.Push(new CppComplexType(CompoundType.Union));
|
currentType.Push(CppType.NewUnion());
|
||||||
|
|
||||||
Debug.WriteLine($"\n[UNION START ] {line}");
|
Debug.WriteLine($"\n[UNION START ] {line}");
|
||||||
continue;
|
continue;
|
||||||
@@ -282,7 +282,7 @@ namespace Il2CppInspector.Cpp
|
|||||||
// Start of enum
|
// Start of enum
|
||||||
// typedef enum <optional-type-name>
|
// typedef enum <optional-type-name>
|
||||||
if (line.StartsWith("typedef enum") && line.IndexOf(";", StringComparison.Ordinal) == -1) {
|
if (line.StartsWith("typedef enum") && line.IndexOf(";", StringComparison.Ordinal) == -1) {
|
||||||
currentType.Push(new CppComplexType(CompoundType.Enum));
|
currentType.Push(NewDefaultEnum());
|
||||||
nextEnumValue = 0;
|
nextEnumValue = 0;
|
||||||
|
|
||||||
Debug.WriteLine($"\n[ENUM START ] {line}");
|
Debug.WriteLine($"\n[ENUM START ] {line}");
|
||||||
@@ -294,7 +294,7 @@ namespace Il2CppInspector.Cpp
|
|||||||
// union <optional-type-name>
|
// union <optional-type-name>
|
||||||
var words = line.Split(' ');
|
var words = line.Split(' ');
|
||||||
if ((words[0] == "union" || words[0] == "struct") && words.Length <= 2) {
|
if ((words[0] == "union" || words[0] == "struct") && words.Length <= 2) {
|
||||||
currentType.Push(new CppComplexType(words[0] == "struct"? CompoundType.Struct : CompoundType.Union));
|
currentType.Push(words[0] == "struct" ? CppType.NewStruct() : CppType.NewUnion());
|
||||||
|
|
||||||
Debug.WriteLine($"[FIELD START ] {line}");
|
Debug.WriteLine($"[FIELD START ] {line}");
|
||||||
continue;
|
continue;
|
||||||
@@ -339,7 +339,7 @@ namespace Il2CppInspector.Cpp
|
|||||||
// Otherwise it's a field name in the current type
|
// Otherwise it's a field name in the current type
|
||||||
else {
|
else {
|
||||||
var parent = currentType.Peek();
|
var parent = currentType.Peek();
|
||||||
parent.AddField(new CppField { Name = name, Type = ct });
|
parent.AddField(name, ct, alignment);
|
||||||
|
|
||||||
Debug.WriteLine($"[FIELD END ] {line} -- {ct.Name} {name}");
|
Debug.WriteLine($"[FIELD END ] {line} -- {ct.Name} {name}");
|
||||||
}
|
}
|
||||||
@@ -354,7 +354,7 @@ namespace Il2CppInspector.Cpp
|
|||||||
var name = fieldFnPtr.Groups[2].Captures[0].ToString();
|
var name = fieldFnPtr.Groups[2].Captures[0].ToString();
|
||||||
|
|
||||||
var ct = currentType.Peek();
|
var ct = currentType.Peek();
|
||||||
ct.AddField(new CppField {Name = name, Type = fnPtrType}, alignment);
|
ct.AddField(name, fnPtrType, alignment);
|
||||||
|
|
||||||
Debug.WriteLine($"[FIELD FNPTR ] {line} -- {name}");
|
Debug.WriteLine($"[FIELD FNPTR ] {line} -- {name}");
|
||||||
continue;
|
continue;
|
||||||
@@ -395,7 +395,7 @@ namespace Il2CppInspector.Cpp
|
|||||||
if (arraySize > 0)
|
if (arraySize > 0)
|
||||||
type = type.AsArray(arraySize);
|
type = type.AsArray(arraySize);
|
||||||
|
|
||||||
ct.AddField(new CppField {Name = name, Type = type, BitfieldSize = bitfield}, alignment);
|
ct.AddField(name, type, alignment, bitfield);
|
||||||
|
|
||||||
if (bitfield == 0)
|
if (bitfield == 0)
|
||||||
Debug.WriteLine($"[FIELD {(pointers > 0 ? "PTR" : "VAL")} ] {line} -- {name}");
|
Debug.WriteLine($"[FIELD {(pointers > 0 ? "PTR" : "VAL")} ] {line} -- {name}");
|
||||||
@@ -423,7 +423,7 @@ namespace Il2CppInspector.Cpp
|
|||||||
}
|
}
|
||||||
|
|
||||||
var ct = currentType.Peek();
|
var ct = currentType.Peek();
|
||||||
ct.AddField(new CppEnumField {Name = name, Type = WordSize == 32 ? Types["uint32_t"] : Types["uint64_t"], Value = value});
|
((CppEnumType) ct).AddField(name, value);
|
||||||
|
|
||||||
Debug.WriteLine($"[ENUM VALUE ] {line} -- {name} = {value}");
|
Debug.WriteLine($"[ENUM VALUE ] {line} -- {name} = {value}");
|
||||||
continue;
|
continue;
|
||||||
@@ -468,6 +468,14 @@ namespace Il2CppInspector.Cpp
|
|||||||
// Add a type externally
|
// Add a type externally
|
||||||
public void Add(CppType type) => Types.Add(type.Name, type);
|
public void Add(CppType type) => Types.Add(type.Name, type);
|
||||||
|
|
||||||
|
// Add a field to a type specifying the field type and/or declaring type name as a string
|
||||||
|
// Convenient when the field type is a pointer, or to avoid referencing this.Types or this.WordSize externally
|
||||||
|
public int AddField(CppComplexType declaringType, string fieldName, string typeName)
|
||||||
|
=> declaringType.AddField(fieldName, GetType(typeName));
|
||||||
|
|
||||||
|
// Create an empty enum with the default underlying type for the architecture (32 or 64-bit)
|
||||||
|
public CppEnumType NewDefaultEnum() => CppType.NewEnum(Types["int"]);
|
||||||
|
|
||||||
// Generate a populated CppTypes object from a set of Unity headers
|
// Generate a populated CppTypes object from a set of Unity headers
|
||||||
public static CppTypes FromUnityVersion(UnityVersion version, int wordSize = 32)
|
public static CppTypes FromUnityVersion(UnityVersion version, int wordSize = 32)
|
||||||
=> FromUnityHeaders(UnityHeader.GetHeaderForVersion(version), wordSize);
|
=> FromUnityHeaders(UnityHeader.GetHeaderForVersion(version), wordSize);
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ namespace Il2CppInspector
|
|||||||
var cppTypes = CppTypes.FromUnityHeaders(unityHeader);
|
var cppTypes = CppTypes.FromUnityHeaders(unityHeader);
|
||||||
|
|
||||||
foreach (var cppType in cppTypes.Types)
|
foreach (var cppType in cppTypes.Types)
|
||||||
Debug.WriteLine("// " + cppType.Key + "\n" + cppType.Value + "\n");
|
Debug.WriteLine("// " + cppType.Key + "\n" + cppType.Value.ToString("o") + "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do a few sanity checks taken from real applications
|
// Do a few sanity checks taken from real applications
|
||||||
|
|||||||
Reference in New Issue
Block a user