Extract Unity version range management from UnityHeader to UnityVersionRange

This commit is contained in:
Katy Coe
2020-07-20 06:14:31 +02:00
parent e7d3600f67
commit 964685e44a
4 changed files with 103 additions and 31 deletions

View File

@@ -20,34 +20,18 @@ namespace Il2CppInspector.Cpp.UnityHeaders
public double MetadataVersion { get; }
// Minimum and maximum Unity version numbers corresponding to this header. Both endpoints are inclusive
public UnityVersion MinVersion { get; }
public UnityVersion MaxVersion { get; }
public UnityVersionRange Version { get; }
// Filename for the embedded .h resource file containing the header
public string HeaderFilename { get; }
private UnityHeader(string headerFilename) {
HeaderFilename = headerFilename;
var bits = headerFilename.Replace(".h", "").Split("-");
MetadataVersion = double.Parse(bits[0], NumberFormatInfo.InvariantInfo);
MinVersion = new UnityVersion(bits[1]);
if (bits.Length == 2)
MaxVersion = MinVersion;
else if (bits[2] != "")
MaxVersion = new UnityVersion(bits[2]);
Version = UnityVersionRange.FromFilename(HeaderFilename);
MetadataVersion = double.Parse(headerFilename.Split("-")[0], NumberFormatInfo.InvariantInfo);
}
public override string ToString() {
var res = $"{MinVersion}";
if (MaxVersion == null)
res += "+";
else if (MaxVersion != MinVersion)
res += $" - {MaxVersion}";
return res;
}
// Determine if this header supports the given version of Unity
public bool Contains(UnityVersion version) => version.CompareTo(MinVersion) >= 0 && (MaxVersion == null || version.CompareTo(MaxVersion) <= 0);
public override string ToString() => Version.ToString();
// Return the contents of this header file as a string
public string GetHeaderText() {
@@ -62,7 +46,7 @@ namespace Il2CppInspector.Cpp.UnityHeaders
return result;
}
// List all header files embedded into this build of Il2Cpp
// List all header files embedded into this build of Il2CppInspector
public static IEnumerable<UnityHeader> GetAllHeaders() {
string prefix = typeof(UnityHeader).Namespace + ".";
Assembly assembly = Assembly.GetExecutingAssembly();
@@ -71,26 +55,58 @@ namespace Il2CppInspector.Cpp.UnityHeaders
.Select(s => new UnityHeader(s.Substring(prefix.Length)));
}
// List all API header files and versions embedded into this build of Il2CppInspector
public static IEnumerable<(string resourceName, UnityVersion minVersion, UnityVersion maxVersion)> GetAPIList() {
string prefix = "Il2CppInspector.Cpp.Il2CppAPIHeaders.";
Assembly assembly = Assembly.GetExecutingAssembly();
var versions = new List<(string resourceName, UnityVersion minVersion, UnityVersion maxVersion)>();
foreach (var headerFilename in assembly.GetManifestResourceNames().Where(s => s.StartsWith(prefix) && s.EndsWith(".h"))) {
var bits = headerFilename.Substring(prefix.Length).Replace(".h", "").Split("-");
var min = new UnityVersion(bits[0]);
UnityVersion max = min;
if (bits.Length == 2 && bits[1] != "")
max = new UnityVersion(bits[1]);
versions.Add((headerFilename, min, max));
}
return versions;
}
// Get the header file which supports the given version of Unity
public static UnityHeader GetHeaderForVersion(string version) => GetHeaderForVersion(new UnityVersion(version));
public static UnityHeader GetHeaderForVersion(UnityVersion version) => GetAllHeaders().Where(v => v.Contains(version)).First();
public static UnityHeader GetHeaderForVersion(UnityVersion version) => GetAllHeaders().First(h => h.Version.Contains(version));
public static string GetAPIResourceNameForVersion(UnityVersion version) =>
GetAPIList().First(v => version.CompareTo(v.minVersion) >= 0 && (v.maxVersion == null || version.CompareTo(v.maxVersion) <= 0)).resourceName;
public static string GetAPITextForVersion(UnityVersion version) {
var apiResource = GetAPIResourceNameForVersion(version);
Assembly assembly = Assembly.GetCallingAssembly();
using Stream stream = assembly.GetManifestResourceStream(apiResource);
if (stream == null) {
throw new FileNotFoundException(apiResource);
}
using StreamReader reader = new StreamReader(stream);
string result = reader.ReadToEnd();
return result;
}
// Guess which header file(s) correspond to the given metadata+binary.
// Note that this may match multiple headers due to structural changes between versions
// that are not reflected in the metadata version.
public static List<UnityHeader> GuessHeadersForModel(Reflection.TypeModel model) {
List<UnityHeader> result = new List<UnityHeader>();
foreach (var v in GetAllHeaders()) {
if (v.MetadataVersion != model.Package.BinaryImage.Version)
foreach (var h in GetAllHeaders()) {
if (h.MetadataVersion != model.Package.BinaryImage.Version)
continue;
if (v.MetadataVersion == 21) {
if (h.MetadataVersion == 21) {
/* Special version logic for metadata version 21 based on the Il2CppMetadataRegistration.fieldOffsets field */
var headerFieldOffsetsArePointers = v.MinVersion.CompareTo("5.3.7") >= 0 && v.MinVersion.CompareTo("5.4.0") != 0;
var headerFieldOffsetsArePointers = h.Version.Min.CompareTo("5.3.7") >= 0 && h.Version.Min.CompareTo("5.4.0") != 0;
var binaryFieldOffsetsArePointers = model.Package.Binary.FieldOffsets == null;
if (headerFieldOffsetsArePointers != binaryFieldOffsetsArePointers)
continue;
}
result.Add(v);
result.Add(h);
}
return result;
}