private static void InitializeUnityVersion() { string unityVersion = string.Copy(MelonUtils.GetUnityVersion()); if (string.IsNullOrEmpty(unityVersion)) { return; } string[] unityVersionSplit = unityVersion.Split('.'); if ((unityVersionSplit == null) || (unityVersionSplit.Length < 2)) { return; } int major = int.Parse(unityVersionSplit[0]); int minor = int.Parse(unityVersionSplit[1]); int patch = 0; if (unityVersionSplit.Length > 2) { string patchString = unityVersionSplit[2]; char firstBadChar = patchString.FirstOrDefault(it => it <'0' || it> '9'); patch = int.Parse(firstBadChar == 0 ? patchString : patchString.Substring(0, patchString.IndexOf(firstBadChar))); } UnityVersionHandler.Initialize(major, minor, patch); }
static Mesh() { InternalClassPointerStore <Mesh> .NativeClassPtr = UnityInternals.GetClass("UnityEngine.CoreModule.dll", "UnityEngine", "Mesh"); UnityInternals.runtime_class_init(InternalClassPointerStore <Mesh> .NativeClassPtr); m_ctor = UnityInternals.GetMethod(InternalClassPointerStore <Mesh> .NativeClassPtr, ".ctor", "System.Void"); m_set_triangles = UnityInternals.GetMethod(InternalClassPointerStore <Mesh> .NativeClassPtr, "set_triangles", "System.Void", "System.Int32[]"); m_RecalculateBounds = UnityInternals.GetMethod(InternalClassPointerStore <Mesh> .NativeClassPtr, "RecalculateBounds", "System.Void"); if (NativeSignatureResolver.IsUnityVersionOverOrEqual(MelonUtils.GetUnityVersion(), new string[] { "2020.1.0" })) { m_SetArrayForChannelImpl_2020 = UnityInternals.ResolveICall <SetArrayForChannelImpl_2020>("UnityEngine.Mesh::SetArrayForChannelImpl"); type_SetArrayForChannelImpl = 2; } else if (NativeSignatureResolver.IsUnityVersionOverOrEqual(MelonUtils.GetUnityVersion(), new string[] { "2019.3.0" })) { m_SetArrayForChannelImpl_2019 = UnityInternals.ResolveICall <SetArrayForChannelImpl_2019>("UnityEngine.Mesh::SetArrayForChannelImpl"); type_SetArrayForChannelImpl = 1; } else if (NativeSignatureResolver.IsUnityVersionOverOrEqual(MelonUtils.GetUnityVersion(), new string[] { "2017.1.0" })) { m_SetArrayForChannelImpl_2017 = UnityInternals.ResolveICall <SetArrayForChannelImpl_2017>("UnityEngine.Mesh::SetArrayForChannelImpl"); type_SetArrayForChannelImpl = 0; } }
unsafe static Graphics() { InternalClassPointerStore <Graphics> .NativeClassPtr = UnityInternals.GetClass("UnityEngine.CoreModule.dll", "UnityEngine", "Graphics"); fd_Internal_DrawTexture = UnityInternals.ResolveICall <Internal_DrawTextureDelegate>("UnityEngine.Graphics::Internal_DrawTexture"); if (NativeSignatureResolver.IsUnityVersionOverOrEqual(MelonUtils.GetUnityVersion(), new string[] { "2018.2.0", "2019.1.0" })) { fd_Internal_DrawMeshNow1_Injected = UnityInternals.ResolveICall <Internal_DrawMeshNow1_InjectedDelegate>("UnityEngine.Graphics::Internal_DrawMeshNow1_Injected"); } else { fd_Internal_DrawMeshNow1_Injected = UnityInternals.ResolveICall <Internal_DrawMeshNow1_InjectedDelegate>("UnityEngine.Graphics::INTERNAL_CALL_Internal_DrawMeshNow1"); } if (NativeSignatureResolver.IsUnityVersionOverOrEqual(MelonUtils.GetUnityVersion(), new string[] { "2019.3.0", "2020.1.0" })) { m_DrawTexture_Internal_struct = 3; } else if (NativeSignatureResolver.IsUnityVersionOverOrEqual(MelonUtils.GetUnityVersion(), new string[] { "2018.2.0", "2019.1.0" })) { m_DrawTexture_Internal_struct = 2; } else if (NativeSignatureResolver.IsUnityVersionOverOrEqual(MelonUtils.GetUnityVersion(), new string[] { "2017.3.0", "2018.1.0" })) { m_DrawTexture_Internal_struct = 1; } else if (NativeSignatureResolver.IsUnityVersionOverOrEqual(MelonUtils.GetUnityVersion(), new string[] { "2017.2.0" })) { m_DrawTexture_Internal_struct = 0; } }
internal UnityDependencies() { Version = MelonLaunchOptions.Il2CppAssemblyGenerator.ForceVersion_UnityDependencies; if (string.IsNullOrEmpty(Version) || Version.Equals("0.0.0.0")) { Version = string.Copy(MelonUtils.GetUnityVersion()); } URL = "https://github.com/LavaGang/Unity-Runtime-Libraries/raw/master/" + Version + ".zip"; Destination = Path.Combine(Core.BasePath, "UnityDependencies"); }
static GfxDevice() { if (NativeSignatureResolver.IsUnityVersionOverOrEqual(MelonUtils.GetUnityVersion(), new[] { "2020.2.7", "2020.3.0", "2021.1.0" })) { // `FrameTimingManager_CUSTOM_CaptureFrameTimings()` calls `GetRealGfxDevice()` after 4 bytes. m_GetRealGfxDevice = (GetRealGfxDeviceDelegate)Marshal.GetDelegateForFunctionPointer( CppUtils.ResolveRelativeInstruction( (IntPtr)((long)UnityInternals.ResolveICall("UnityEngine.FrameTimingManager::CaptureFrameTimings") + (MelonUtils.IsGame32Bit() ? 0 : 4))), typeof(GetRealGfxDeviceDelegate)); } }
static Texture() { InternalClassPointerStore <Texture> .NativeClassPtr = UnityInternals.GetClass("UnityEngine.CoreModule.dll", "UnityEngine", "Texture"); if (NativeSignatureResolver.IsUnityVersionOverOrEqual(MelonUtils.GetUnityVersion(), new string[] { "2018.1.0" })) { getDataWidth = UnityInternals.ResolveICall <GetDataWidthDelegate>("UnityEngine.Texture::GetDataWidth"); getDataHeight = UnityInternals.ResolveICall <GetDataHeightDelegate>("UnityEngine.Texture::GetDataHeight"); } else if (NativeSignatureResolver.IsUnityVersionOverOrEqual(MelonUtils.GetUnityVersion(), new string[] { "2017.1.0" })) { getDataWidth = UnityInternals.ResolveICall <GetDataWidthDelegate>("UnityEngine.Texture::Internal_GetWidth"); getDataHeight = UnityInternals.ResolveICall <GetDataHeightDelegate>("UnityEngine.Texture::Internal_GetHeight"); } set_filterMode_ = UnityInternals.ResolveICall <set_filterModeDelegate>("UnityEngine.Texture::set_filterMode"); }
unsafe static UnityInternals() { if (MelonUtils.IsGameIl2Cpp()) { domain = il2cpp_domain_get(); uint assemblyCount = 0; IntPtr *assemblyArray = il2cpp_domain_get_assemblies(domain, ref assemblyCount); for (int i = 0; i < assemblyCount; ++i) { assemblies.Add(new InternalAssembly(il2cpp_assembly_get_image(*(assemblyArray + i)))); } } else { domain = mono_domain_get(); string unityVersion = MelonUtils.GetUnityVersion(); MonoClass *testclass = (MonoClass *)Marshal.AllocHGlobal(sizeof(MonoClass)); testclass->applyZeroes(); testclass->nested_in_0x04 = (IntPtr)0x1234; testclass->nested_in_0x08 = (IntPtr)0x5678; testclass->nested_in_0x0C = (IntPtr)0x9012; long returnedName = (long)mono_class_get_name((IntPtr)testclass); MelonDebug.Msg($"returnedName {returnedName:X}"); Marshal.FreeHGlobal((IntPtr)testclass); if (returnedName == 0x1234) { monoClassOffset = 0; } else if (returnedName == 0x5678) { monoClassOffset = (uint)IntPtr.Size * 1; } else if (returnedName == 0x9012) { monoClassOffset = (uint)IntPtr.Size * 2; } else { throw new Exception("Failed to find MonoClass name offset"); } MelonDebug.Msg("monoClassOffset? " + monoClassOffset); } }
internal static void Init() { if (disabled) { return; } MelonDebug.Msg("Initializing UIStyleValues"); UIStyleValues.Init(); MelonDebug.Msg("UIStyleValues Initialized"); if (UICustomization.VersionText.Enabled) { TextGenerationSettings settings = new TextGenerationSettings(); settings.textAnchor = TextAnchor.MiddleCenter; settings.color = UICustomization.VersionText.TextColor; settings.generationExtents = new Vector2(540, 47.5f); settings.richText = true; settings.font = UIStyleValues.TextFont; settings.pivot = new Vector2(0.5f, 0.5f); settings.fontSize = 24; settings.fontStyle = FontStyle.Bold; settings.verticalOverflow = VerticalWrapMode.Overflow; settings.scaleFactor = 1f; settings.lineSpacing = 1f; MelonDebug.Msg("TextGenerationSettings settings set"); string melonloaderText = (MelonLaunchOptions.Console.Mode == MelonLaunchOptions.Console.DisplayMode.LEMON) ? "<color=#FFCC4D>LemonLoader</color>" : "<color=#78f764>Melon</color><color=#ff3c6a>Loader</color>"; melonloaderversionTextmesh = TextMeshGenerator.Generate($"{melonloaderText} v{BuildInfo.Version} Open-Beta", settings); } if (UICustomization.ProgressBar.Enabled || UICustomization.ProgressText.Enabled) { progressBar = new ProgressBar(width: 540, height: 36); } uint graphicsDeviceType = SystemInfo.GetGraphicsDeviceType(); MelonDebug.Msg("Graphics Device Type: " + graphicsDeviceType); shouldCallWFLPAGT = NativeSignatureResolver.IsUnityVersionOverOrEqual(MelonUtils.GetUnityVersion(), new[] { "2020.2.7", "2020.3.0", "2021.1.0" }) && (graphicsDeviceType == /*DX11*/ 2 || graphicsDeviceType == /*DX12*/ 18) ? graphicsDeviceType : 0; }
unsafe static UIVertexWrapper() { if (NativeSignatureResolver.IsUnityVersionOverOrEqual(MelonUtils.GetUnityVersion(), new string[] { "2020.2.0", "2021.1.0" })) { mode = 2; sizeOfElement = sizeof(UIVertex_2020); } else if (NativeSignatureResolver.IsUnityVersionOverOrEqual(MelonUtils.GetUnityVersion(), new string[] { "2018.1.0" })) { mode = 1; sizeOfElement = sizeof(UIVertex_2018); } else if (NativeSignatureResolver.IsUnityVersionOverOrEqual(MelonUtils.GetUnityVersion(), new string[] { "2017.2.0" })) { mode = 0; sizeOfElement = sizeof(UIVertex_2017); } }
internal static int LoadAndRun(LemonFunc <int> functionToWaitForAsync) { // We don't support Unity versions under 2017.2.0 (yet?) if (!MelonLaunchOptions.Core.StartScreen || !MelonUtils.GetUnityVersion().StartsWith("20") || MelonUtils.GetUnityVersion().StartsWith("2017.1")) { return(functionToWaitForAsync()); } if (!Load()) { return(functionToWaitForAsync()); } if (LoadAndRunMethod != null) { return((int)LoadAndRunMethod.Invoke(null, new object[] { functionToWaitForAsync })); } return(-1); }
static Texture2D() { InternalClassPointerStore <Texture2D> .NativeClassPtr = UnityInternals.GetClass("UnityEngine.CoreModule.dll", "UnityEngine", "Texture2D"); UnityInternals.runtime_class_init(InternalClassPointerStore <Texture2D> .NativeClassPtr); m_ctor = UnityInternals.GetMethod(InternalClassPointerStore <Texture2D> .NativeClassPtr, ".ctor", "System.Void", "System.Int32", "System.Int32"); m_get_whiteTexture = UnityInternals.GetMethod(InternalClassPointerStore <Texture2D> .NativeClassPtr, "get_whiteTexture", "UnityEngine.Texture2D"); if (NativeSignatureResolver.IsUnityVersionOverOrEqual(MelonUtils.GetUnityVersion(), new string[] { "2018.1.0" })) { type_SetPixelsImpl = 1; m_SetPixelsImpl_2018 = UnityInternals.ResolveICall <SetPixelsImplDelegate_2018>("UnityEngine.Texture2D::SetPixelsImpl"); } else if (NativeSignatureResolver.IsUnityVersionOverOrEqual(MelonUtils.GetUnityVersion(), new string[] { "2017.1.0" })) { type_SetPixelsImpl = 0; m_SetPixelsImpl_2017 = UnityInternals.ResolveICall <SetPixelsImplDelegate_2017>("UnityEngine.Texture2D::SetPixels"); } m_Apply = UnityInternals.GetMethod(InternalClassPointerStore <Texture2D> .NativeClassPtr, "Apply", "System.Void"); }
internal static bool Apply() { NativeSignatureFlags currentFlags = default; currentFlags |= MelonUtils.IsGame32Bit() ? NativeSignatureFlags.X86 : NativeSignatureFlags.X64; currentFlags |= MelonUtils.IsGameIl2Cpp() ? NativeSignatureFlags.Il2Cpp : NativeSignatureFlags.Mono; MelonDebug.Msg("Current Unity flags: " + (uint)currentFlags); string currentUnityVersion = MelonUtils.GetUnityVersion(); int splitIndex = currentUnityVersion.IndexOf('f'); if (splitIndex == -1) { splitIndex = currentUnityVersion.IndexOf('p'); } if (splitIndex > 0) { currentUnityVersion = currentUnityVersion.Substring(0, splitIndex); } MelonDebug.Msg("Unity version: " + currentUnityVersion); string moduleName = "UnityPlayer.dll"; #if LINUX // TODO #elif OSX // TODO #elif ANDROID // TODO #else if (!currentUnityVersion.StartsWith("20") || currentUnityVersion.StartsWith("2017.1")) { moduleName = "player_win.exe"; } #endif IntPtr moduleAddress = IntPtr.Zero; int moduleSize = 0; foreach (ProcessModule module in Process.GetCurrentProcess().Modules) { if (module.ModuleName == moduleName) { moduleAddress = module.BaseAddress; moduleSize = module.ModuleMemorySize; break; } } if (moduleAddress == IntPtr.Zero) { MelonLogger.Error($"Failed to find module \"{moduleName}\""); return(false); } bool success = true; foreach (Type type in typeof(NativeSignatureResolver).Assembly.GetTypes()) { foreach (FieldInfo fi in type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static)) { bool hasAttribute = false; bool signaturefound = false; bool optionalOnEarlyVersion = false; IOrderedEnumerable <NativeSignatureAttribute> nativeSignatureAttributes = fi.GetCustomAttributes(false) .Where(attr => attr is NativeSignatureAttribute) .Select(attr => (NativeSignatureAttribute)attr) .OrderByDescending(attr => attr.LookupIndex); foreach (NativeSignatureAttribute attribute in nativeSignatureAttributes) { hasAttribute = true; if ((attribute.Flags & currentFlags) != attribute.Flags) { continue; } if (!IsUnityVersionOverOrEqual(currentUnityVersion, attribute.MinimalUnityVersions)) { continue; } signaturefound = true; if (attribute.Signature == null) { optionalOnEarlyVersion = true; break; } IntPtr ptr = CppUtils.Sigscan(moduleAddress, moduleSize, attribute.Signature); if (ptr == IntPtr.Zero) { success = false; MelonLogger.Error("Failed to find the signature for field " + fi.Name + " in module. Signature: " + attribute.Signature); break; } if (typeof(Delegate).IsAssignableFrom(fi.FieldType)) { fi.SetValue(null, Marshal.GetDelegateForFunctionPointer(ptr, fi.FieldType)); } else if (typeof(IntPtr).IsAssignableFrom(fi.FieldType)) { fi.SetValue(null, ptr); } else { MelonLogger.Error($"Invalid target type for field \"{fi.FieldType} {fi.Name}\""); } MelonDebug.Msg("Signature for " + fi.Name + ": " + attribute.Signature); break; } if (hasAttribute && !signaturefound && !optionalOnEarlyVersion) { MelonLogger.Error("Failed to find a signature for field " + fi.Name + " for this version of Unity"); success = false; } hasAttribute = false; signaturefound = false; IOrderedEnumerable <NativeFieldValueAttribute> nativeFieldValueAttributes = fi.GetCustomAttributes(false) .Where(attr => attr is NativeFieldValueAttribute) .Select(attr => (NativeFieldValueAttribute)attr) .OrderByDescending(attr => attr.LookupIndex); foreach (NativeFieldValueAttribute attribute in nativeFieldValueAttributes) { hasAttribute = true; if ((attribute.Flags & currentFlags) != attribute.Flags) { continue; } if (!IsUnityVersionOverOrEqual(currentUnityVersion, attribute.MinimalUnityVersions)) { continue; } signaturefound = true; fi.SetValue(null, attribute.Value); MelonDebug.Msg("Value for " + fi.Name + ": " + attribute.Value); break; } if (hasAttribute && !signaturefound) { MelonLogger.Error("Failed to find a value for field " + fi.Name + " for this version of Unity"); success = false; } } } return(success); }
public static string GetUnityVersion() => MelonUtils.GetUnityVersion();