diff --git a/Cpp2IL/AssemblyBuilder.cs b/Cpp2IL/AssemblyBuilder.cs
index b672d20a..25d6d71b 100644
--- a/Cpp2IL/AssemblyBuilder.cs
+++ b/Cpp2IL/AssemblyBuilder.cs
@@ -11,10 +11,8 @@
namespace Cpp2IL
{
- internal static partial class AssemblyBuilder
+ internal static class AssemblyBuilder
{
-
-
///
/// Creates all the Assemblies defined in the provided metadata, along with (stub) definitions of all the types contained therein, and registers them with the resolver.
///
@@ -124,7 +122,8 @@ public static void ConfigureHierarchy(Il2CppMetadata metadata, PE.PE theDll)
var currentAssembly = firstTypeDefinition.Module.Assembly;
//Ensure type directory exists
- Directory.CreateDirectory(Path.Combine(Path.GetFullPath("cpp2il_out"), "types", currentAssembly.Name.Name));
+ if(!Program.CommandLineOptions.SkipMetadataTextFiles && !Program.CommandLineOptions.SkipAnalysis)
+ Directory.CreateDirectory(Path.Combine(Path.GetFullPath("cpp2il_out"), "types", currentAssembly.Name.Name));
var lastTypeIndex = imageDef.firstTypeIndex + imageDef.typeCount;
var methods = new List<(TypeDefinition type, List methods)>();
@@ -370,7 +369,8 @@ private static List ProcessTypeContents(Il2CppMetadata metadata,
ilTypeDefinition.Events.Add(eventDefinition);
}
- File.WriteAllText(Path.Combine(Path.GetFullPath("cpp2il_out"), "types", ilTypeDefinition.Module.Assembly.Name.Name, ilTypeDefinition.Name.Replace("<", "_").Replace(">", "_").Replace("|", "_") + "_metadata.txt"), typeMetaText.ToString());
+ if(!Program.CommandLineOptions.SkipMetadataTextFiles)
+ File.WriteAllText(Path.Combine(Path.GetFullPath("cpp2il_out"), "types", ilTypeDefinition.Module.Assembly.Name.Name, ilTypeDefinition.Name.Replace("<", "_").Replace(">", "_").Replace("|", "_") + "_metadata.txt"), typeMetaText.ToString());
if (cppTypeDefinition.genericContainerIndex < 0) return typeMethods; //Finished processing if not generic
diff --git a/Cpp2IL/PE/PE.cs b/Cpp2IL/PE/PE.cs
index 66f5979b..7cebac3c 100644
--- a/Cpp2IL/PE/PE.cs
+++ b/Cpp2IL/PE/PE.cs
@@ -332,7 +332,7 @@ public bool PlusSearch(int methodCount, int typeDefinitionsCount)
List methodBodyRuntimeInit = Utils.GetMethodBodyAtRawAddress(this, MapVirtualAddressToRaw(virtualAddressRuntimeInit), false);
Disassembler.Translator.IncludeBinary = true;
- File.WriteAllText(Path.Combine("cpp2il_out", "runtime_init_dump.txt"), string.Join('\n', methodBodyRuntimeInit.Select(i => i.ToString())));
+ // File.WriteAllText(Path.Combine("cpp2il_out", "runtime_init_dump.txt"), string.Join('\n', methodBodyRuntimeInit.Select(i => i.ToString())));
//This is kind of sketchy, but look for a global read (i.e an LEA where the second base is RIP), as that's the framework version read, then there's a MOV, then 4 calls, the third of which is our target.
//So as to ensure compat with 2018, ensure we have a call before this LEA.
diff --git a/Cpp2IL/Program.cs b/Cpp2IL/Program.cs
index dce78af8..11edbcdc 100644
--- a/Cpp2IL/Program.cs
+++ b/Cpp2IL/Program.cs
@@ -30,6 +30,9 @@ internal class Options
[Option("skip-analysis", Required = false, HelpText = "Skip the analysis section and stop once DummyDLLs have been generated.")]
public bool SkipAnalysis { get; set; }
+
+ [Option("skip-metadata-txts", Required = false, HelpText = "Skip the generation of [classname]_metadata.txt files.")]
+ public bool SkipMetadataTextFiles { get; set; }
}
public static float MetadataVersion = 24f;
@@ -43,6 +46,7 @@ internal class Options
private static List Assemblies = new List();
internal static Il2CppMetadata? Metadata;
internal static PE.PE ThePE;
+ internal static Options CommandLineOptions;
public static void PrintUsage()
{
@@ -55,13 +59,13 @@ public static void Main(string[] args)
Console.WriteLine("A Tool to Reverse Unity's \"il2cpp\" Build Process.");
Console.WriteLine("Running on " + Environment.OSVersion.Platform);
- Options commandLineOptions = null;
+ CommandLineOptions = null;
Parser.Default.ParseArguments(args).WithParsed(options =>
{
- commandLineOptions = options;
+ CommandLineOptions = options;
});
- if (commandLineOptions == null)
+ if (CommandLineOptions == null)
{
return;
}
@@ -93,7 +97,7 @@ public static void Main(string[] args)
// return;
// }
- var baseGamePath = commandLineOptions.GamePath;
+ var baseGamePath = CommandLineOptions.GamePath;
Console.WriteLine("Using path: " + baseGamePath);
@@ -105,11 +109,12 @@ public static void Main(string[] args)
}
var assemblyPath = Path.Combine(baseGamePath, "GameAssembly.dll");
- var exeName = Path.GetFileNameWithoutExtension(Directory.GetFiles(baseGamePath).First(f => f.EndsWith(".exe") && !blacklistedExecutableFilenames.Contains(f)));
+ var exeName = Path.GetFileNameWithoutExtension(Directory.GetFiles(baseGamePath)
+ .First(f => f.EndsWith(".exe") && !blacklistedExecutableFilenames.Any(bl => f.EndsWith(bl))));
- if (commandLineOptions.ExeName != null)
+ if (CommandLineOptions.ExeName != null)
{
- exeName = commandLineOptions.ExeName;
+ exeName = CommandLineOptions.ExeName;
Console.WriteLine($"Using OVERRIDDEN game name: {exeName}");
}
else
@@ -136,10 +141,32 @@ public static void Main(string[] args)
Console.WriteLine("\nAttempting to determine Unity version...");
- var unityVer = FileVersionInfo.GetVersionInfo(unityPlayerPath);
-
- var unityVerUseful = new[] {unityVer.FileMajorPart, unityVer.FileMinorPart, unityVer.FileBuildPart};
-
+ int[] unityVerUseful;
+ if (Environment.OSVersion.Platform == PlatformID.Win32NT)
+ {
+ var unityVer = FileVersionInfo.GetVersionInfo(unityPlayerPath);
+
+ unityVerUseful = new[] {unityVer.FileMajorPart, unityVer.FileMinorPart, unityVer.FileBuildPart};
+ }
+ else
+ {
+ //Globalgamemanagers
+ var globalgamemanagersPath = Path.Combine(baseGamePath, $"{exeName}_Data", "globalgamemanagers");
+ var ggmBytes = File.ReadAllBytes(globalgamemanagersPath);
+ var verString = new StringBuilder();
+ var idx = 0x14;
+ while (ggmBytes[idx] != 0)
+ {
+ verString.Append(Convert.ToChar(ggmBytes[idx]));
+ idx++;
+ }
+
+ var unityVer = verString.ToString();
+ unityVer = unityVer.Substring(0, unityVer.IndexOf("f"));
+ Console.WriteLine("Read version string from globalgamemanagers: " + unityVer);
+ unityVerUseful = unityVer.Split(".").Select(int.Parse).ToArray();
+ }
+
Console.WriteLine("This game is built with Unity version " + string.Join(".", unityVerUseful));
if (unityVerUseful[0] <= 4)
@@ -246,7 +273,7 @@ public static void Main(string[] args)
#endregion
KeyFunctionAddresses keyFunctionAddresses = null;
- if (!commandLineOptions.SkipAnalysis)
+ if (!CommandLineOptions.SkipAnalysis)
{
Console.WriteLine("\tPass 5: Locating Globals...");
@@ -281,7 +308,7 @@ public static void Main(string[] args)
Directory.CreateDirectory(outputPath);
var methodOutputDir = Path.Combine(outputPath, "types");
- if (!Directory.Exists(methodOutputDir))
+ if (!CommandLineOptions.SkipAnalysis && !Directory.Exists(methodOutputDir))
Directory.CreateDirectory(methodOutputDir);
Console.WriteLine("Saving Header DLLs to " + outputPath + "...");
@@ -294,7 +321,7 @@ public static void Main(string[] args)
assembly.Write(dllPath);
- if (assembly.Name.Name != "Assembly-CSharp" || commandLineOptions.SkipAnalysis) continue;
+ if (assembly.Name.Name != "Assembly-CSharp" || CommandLineOptions.SkipAnalysis) continue;
Console.WriteLine("Dumping method bytes to " + methodOutputDir);
Directory.CreateDirectory(Path.Combine(methodOutputDir, assembly.Name.Name));