From 4841e82bd5e399c4fc39313bbc93c6fc1bb12b2a Mon Sep 17 00:00:00 2001 From: hch <305670599@qq.com> Date: 星期五, 20 六月 2025 17:26:10 +0800 Subject: [PATCH] 0312 热更插件 --- Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/LDasm.cs | 903 +++ Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/SevenZipHelper.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/LDasm.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/AOT/GenericReferenceWriter.cs | 139 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/GenericMethod.cs | 109 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/CopyStrippedAOTAssemblies.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/IAssemblyResolver.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/MethodBridge/Generator.cs | 1256 ++++ Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Template/FileRegionReplace.cs | 74 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/README_EN.md | 87 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Template/FileRegionReplace.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/CodePatcher.cs | 320 + Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Commands/StripAOTDllCommand.cs | 199 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/LZMA/LzmaBase.cs | 76 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta.meta | 8 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ABI/ParamOrReturnType.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/MethodBridge/Analyzer.cs | 205 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/MethodReferenceAnalyzer.cs | 79 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/Node.cs | 10 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/Plugins/x86_64/libMonoHookUtils_OSX.dylib.meta | 81 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/FixedSetAssemblyResolver.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/Plugins/silicon/libMonoHookUtils_OSX.dylib | 0 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/PatchScriptingAssemblyList.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Data~/NetStandard/netstandard2.1.dll | 0 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/LZMA/LzmaEncoder.cs | 1480 ++++ Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/HotUpdate/MissingMetadataChecker.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/Plugins/silicon/libMonoHookUtils_OSX.dylib.meta | 81 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Installer/BashUtil.cs | 143 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/LZMA/LzmaDecoder.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/CheckSettings.cs | 94 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/HybridCLR.Editor.asmdef.meta | 7 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/FixedSetAssemblyResolver.cs | 37 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Common/CommandLineParser.cs | 274 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/Node.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/HookPool.cs | 74 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/AddLil2cppSourceCodeToXcodeproj2022OrNewer.cs | 82 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Commands/MethodBridgeGeneratorCommand.cs | 95 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/HookPool.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/MethodReferenceAnalyzer.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/LZMA.meta | 8 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/BuildProcessorUtil.cs | 25 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/AssemblyCache.cs | 20 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/AssemblySorter.cs | 105 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/StreamFile.cs | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/MethodHook.cs | 381 + Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/AssemblyResolverBase.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Settings/SettingsPresetReceiver.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/HookUtils_OSX.cs | 116 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/EndianBinaryWriter.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress.meta | 8 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/MethodHook.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/Plugins.meta | 8 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/BuildProcessorUtil.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/CombinedAssemblyResolver.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/CombinedAssemblyResolver.cs | 33 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Commands/CompileDllCommand.cs | 101 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ReversePInvokeWrap/Analyzer.cs | 74 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/HotUpdate.meta | 8 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/ArchiveFlags.cs | 14 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/SevenZipHelper.cs | 49 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/AOT/ConstraintContext.cs | 73 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Settings/SettingsPresetReceiver.cs | 39 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/LZ/IMatchFinder.cs | 24 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/RELEASELOG.md.meta | 7 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/FilterHotFixAssemblies.cs | 68 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/EndianType.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/MsvcStdextWorkaround.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ABI/TypeInfo.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/BundleFileInfo.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/RangeCoder/RangeCoderBit.cs | 117 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Data~/Templates/MethodBridge.cpp.tpl | 32 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/BundleFileWriter.cs | 112 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/AssemblyResolverBase.cs | 33 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Runtime/ReversePInvokeWrapperGenerationAttribute.cs | 19 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/ICoder.cs | 157 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Installer/InstallerController.cs | 308 + Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip.meta | 8 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/UnityBinFile.cs | 124 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/SettingsUtil.cs | 116 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/RangeCoder/RangeCoder.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Commands/AOTReferenceGeneratorCommand.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Plugins.meta | 8 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Plugins/LZ4.dll | 0 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/README.md.meta | 7 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/AssemblyCache.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/LZ/LzBinTree.cs | 367 + Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/README_EN.md.meta | 7 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/AssemblyReferenceDeepCollector.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/LZ.meta | 8 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Runtime/HomologousImageMode.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Data~/hybridclr_version.json | 39 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Data~/NetStandard/netstandard2.0.dll | 0 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Runtime/LoadImageErrorCode.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/HybridCLRHooks.meta | 8 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/Plugins/Utils.cpp | 23 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Runtime/RuntimeOptionId.cs | 12 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/CompressionType.cs | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/AddLil2cppSourceCodeToXcodeproj2020Or2021.cs | 244 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Commands/Il2CppDefGeneratorCommand.cs | 33 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook.meta | 8 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/BundleFileReader.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/HybridCLRHooks/CopyStrippedAOTAssembliesHook.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ABI/ParamInfo.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Settings/HybridCLRSettingProvider.cs | 178 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ABI/ParamOrReturnType.cs | 27 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Runtime/RuntimeApi.cs | 139 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/AddLil2cppSourceCodeToXcodeproj2019.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Common/OutBuffer.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/Header.cs | 14 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/LZMA/LzmaEncoder.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Settings/EditorStatusWatcher.cs | 29 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/CodePatcher.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Common/CRC.cs | 55 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Runtime/RuntimeOptionId.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Commands/AOTReferenceGeneratorCommand.cs | 132 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/ScriptingAssembliesJsonPatcher.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/LZ/LzBinTree.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Installer/InstallerWindow.cs | 113 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/BinaryReaderExtensions.cs | 51 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ABI/MethodDesc.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/CheckSettings.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Data~/Templates/AssemblyManifest.cpp.tpl | 12 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Common/OutBuffer.cs | 47 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/GenericClass.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Commands.meta | 8 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Runtime/HomologousImageMode.cs | 10 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds.meta | 8 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/AssemblyReferenceDeepCollector.cs | 50 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/PatchScriptingAssemblyList.cs | 189 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/CompressionType.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Runtime/ReversePInvokeWrapperGenerationAttribute.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Link.meta | 8 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/AOT/Analyzer.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/RangeCoder/RangeCoderBitTree.cs | 157 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Settings/EditorStatusWatcher.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/HotUpdate/MissingMetadataChecker.cs | 109 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Runtime/RuntimeApi.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/BinaryWriterExtensions.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/EndianType.cs | 14 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ABI/MethodDesc.cs | 77 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/BinaryReaderExtensions.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/MetaUtil.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ReversePInvokeWrap.meta | 8 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors.meta | 8 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/EndianBinaryReader.cs | 107 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Commands/PrebuildCommand.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Runtime/LoadImageErrorCode.cs | 16 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/AddLil2cppSourceCodeToXcodeproj2019.cs | 258 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/StreamExtensions.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/GenericArgumentContext.cs | 126 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/EndianBinaryWriter.cs | 107 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Data~/ModifiedUnityAssemblies/2019.4.40.meta | 8 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/GlobalgamedatasPatcher.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Common.meta | 8 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/LZ/LzOutWindow.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/HashUtil.cs | 28 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/StorageBlockFlags.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/RangeCoder.meta | 8 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/HybridCLRHooks/PatchScriptingAssembliesJsonHook.cs | 74 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/RELEASELOG.md | 899 ++ Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Settings/ScriptableSignleton.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/HybridCLRHooks/CopyStrippedAOTAssembliesHook.cs | 67 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Installer/InstallerWindow.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/BundleFileWriter.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/AOT/Analyzer.cs | 231 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/AOT/AOTAssemblyMetadataStripper.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/MetaUtil.cs | 193 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/Plugins/x86_64/libMonoHookUtils_OSX.dylib | 0 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/HybridCLRHooks/GetIl2CppFolderHook.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/README.md | 88 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Common/InBuffer.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/AssemblyCacheBase.cs | 99 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/AOT.meta | 8 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/HybridCLR.Editor.asmdef | 18 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/ScriptingAssembliesJsonPatcher.cs | 50 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/LZ/LzOutWindow.cs | 110 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/MethodBridge/Analyzer.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/package.json | 22 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/GenericMethod.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Plugins/LZ4.dll.meta | 87 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/PathAssemblyResolver.cs | 35 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/FilterHotFixAssemblies.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ABI/ParamInfo.cs | 30 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/CopyStrippedAOTAssemblies.cs | 134 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ABI/TypeCreator.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Link/LinkXmlWriter.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Data~/ModifiedUnityAssemblies/2019.4.40/Unity.IL2CPP-Win.dll | 0 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ABI/PlatformABI.cs | 10 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/HookUtils_OSX.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Il2CppDef/Il2CppDefGenerator.cs | 107 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/AddLil2cppSourceCodeToXcodeproj2020Or2021.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ABI/ValueTypeSizeAligmentCalculator.cs | 181 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Runtime.meta | 8 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/MethodBridge.meta | 8 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Il2CppDef.meta | 8 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/RangeCoder/RangeCoderBit.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Settings/ScriptableSignleton.cs | 89 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/LICENSE.meta | 7 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Common/InBuffer.cs | 72 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/BinaryWriterExtensions.cs | 33 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Settings.meta | 8 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/UnityBinUtils.cs | 78 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Settings/HybridCLRSettings.cs | 54 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/RangeCoder/RangeCoder.cs | 234 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/ICoder.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Commands/CompileDllCommand.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Settings/MenuProvider.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Commands/Il2CppDefGeneratorCommand.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/AssemblySorter.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/Plugins/silicon.meta | 8 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/Plugins/x86_64.meta | 8 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Settings/HybridCLRSettings.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/Plugins/build_libMonoHookUtils_OSX.dylib.sh.meta | 7 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/RangeCoder/RangeCoderBitTree.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Link/Analyzer.cs | 49 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/GenericArgumentContext.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Installer.meta | 8 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Template.meta | 8 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/PathAssemblyResolver.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Link/LinkXmlWriter.cs | 53 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Data~/Templates/UnityVersion.h.tpl | 6 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/LZ/LzInWindow.cs | 132 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/AddLil2cppSourceCodeToXcodeproj2023OrNewer.cs.meta | 2 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/BundleFileReader.cs | 212 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/BundleFileInfo.cs | 24 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/ArchiveFlags.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/AOT/ConstraintContext.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Settings/HybridCLRSettingProvider.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/GenericClass.cs | 74 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ABI/PlatformABI.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ABI/ValueTypeSizeAligmentCalculator.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/AOT/AOTAssemblyMetadataStripper.cs | 56 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/UnityBinFileDefines.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ABI.meta | 8 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Commands/PrebuildCommand.cs | 39 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/StorageBlock.cs | 9 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/GlobalgamedatasPatcher.cs | 53 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Il2CppDef/Il2CppDefGenerator.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/HookUtils.cs | 272 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/LZ/IMatchFinder.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/LICENSE | 21 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Installer/InstallerController.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/StorageBlock.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Installer/BashUtil.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/Plugins/build_libMonoHookUtils_OSX.dylib.sh | 4 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/UnityBinFile.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/AddLil2cppSourceCodeToXcodeproj2022OrNewer.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/IAssemblyResolver.cs | 13 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor.meta | 8 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/MsvcStdextWorkaround.cs | 32 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/HashUtil.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/LZMA/LzmaDecoder.cs | 398 + Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Commands/MethodBridgeGeneratorCommand.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/HybridCLRHooks/GetIl2CppFolderHook.cs | 56 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/EndianBinaryReader.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/ScriptingAssembliesJsonPatcher.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/UnityBinUtils.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Runtime/HybridCLR.Runtime.asmdef.meta | 7 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Link/Analyzer.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/AOT/GenericReferenceWriter.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/AssemblyCacheBase.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/LZ/LzInWindow.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/HookUtils.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Commands/LinkGeneratorCommand.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ReversePInvokeWrap/Analyzer.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Common/CRC.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ABI/TypeCreator.cs | 102 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Plugins/dnlib.dll | 0 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS.meta | 8 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/StorageBlockFlags.cs | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/AddLil2cppSourceCodeToXcodeproj2023OrNewer.cs | 34 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/ScriptingAssembliesJsonPatcher.cs | 50 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Commands/LinkGeneratorCommand.cs | 39 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/HybridCLRHooks/PatchScriptingAssembliesJsonHook.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/package.json.meta | 7 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/StreamExtensions.cs | 32 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Runtime/HybridCLR.Runtime.asmdef | 14 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Data~/ModifiedUnityAssemblies/2019.4.40/Unity.IL2CPP-Mac.dll | 0 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ABI/TypeInfo.cs | 116 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/MethodBridge/CalliAnalyzer.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/SettingsUtil.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Settings/MenuProvider.cs | 39 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ABI/ABIUtil.cs | 23 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/MethodBridge/Generator.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/UnityBinFileDefines.cs | 397 + Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Commands/StripAOTDllCommand.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/MethodBridge/CalliAnalyzer.cs | 70 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/LZMA/LzmaBase.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/Header.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ABI/ABIUtil.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/StreamFile.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Plugins/dnlib.dll.meta | 87 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Common/CommandLineParser.cs.meta | 11 Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/Plugins/Utils.cpp.meta | 81 294 files changed, 17,968 insertions(+), 0 deletions(-) diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Data~/ModifiedUnityAssemblies/2019.4.40.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Data~/ModifiedUnityAssemblies/2019.4.40.meta new file mode 100644 index 0000000..e7f046c --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Data~/ModifiedUnityAssemblies/2019.4.40.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1cd43f2247d29084fa2b393c30648e64 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Data~/ModifiedUnityAssemblies/2019.4.40/Unity.IL2CPP-Mac.dll b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Data~/ModifiedUnityAssemblies/2019.4.40/Unity.IL2CPP-Mac.dll new file mode 100644 index 0000000..2cce7a7 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Data~/ModifiedUnityAssemblies/2019.4.40/Unity.IL2CPP-Mac.dll Binary files differ diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Data~/ModifiedUnityAssemblies/2019.4.40/Unity.IL2CPP-Win.dll b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Data~/ModifiedUnityAssemblies/2019.4.40/Unity.IL2CPP-Win.dll new file mode 100644 index 0000000..17135a1 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Data~/ModifiedUnityAssemblies/2019.4.40/Unity.IL2CPP-Win.dll Binary files differ diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Data~/NetStandard/netstandard2.0.dll b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Data~/NetStandard/netstandard2.0.dll new file mode 100644 index 0000000..250cf81 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Data~/NetStandard/netstandard2.0.dll Binary files differ diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Data~/NetStandard/netstandard2.1.dll b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Data~/NetStandard/netstandard2.1.dll new file mode 100644 index 0000000..99d1889 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Data~/NetStandard/netstandard2.1.dll Binary files differ diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Data~/Templates/AssemblyManifest.cpp.tpl b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Data~/Templates/AssemblyManifest.cpp.tpl new file mode 100644 index 0000000..d43977d --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Data~/Templates/AssemblyManifest.cpp.tpl @@ -0,0 +1,12 @@ +#include "../Il2CppCompatibleDef.h" + +namespace hybridclr +{ + const char* g_placeHolderAssemblies[] = + { + //!!!{{PLACE_HOLDER + + //!!!}}PLACE_HOLDER + nullptr, + }; +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Data~/Templates/MethodBridge.cpp.tpl b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Data~/Templates/MethodBridge.cpp.tpl new file mode 100644 index 0000000..b723a16 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Data~/Templates/MethodBridge.cpp.tpl @@ -0,0 +1,32 @@ +#include <codegen/il2cpp-codegen-metadata.h> +#if HYBRIDCLR_UNITY_2023_OR_NEW +#include <codegen/il2cpp-codegen.h> +#elif HYBRIDCLR_UNITY_2022 +#include <codegen/il2cpp-codegen-il2cpp.h> +#elif HYBRIDCLR_UNITY_2020 || HYBRIDCLR_UNITY_2021 +#include <codegen/il2cpp-codegen-common-big.h> +#else +#include <codegen/il2cpp-codegen-common.h> +#endif + +#include "vm/ClassInlines.h" +#include "vm/Object.h" +#include "vm/Class.h" +#include "vm/ScopedThreadAttacher.h" + +#include "../metadata/MetadataUtil.h" + + +#include "../interpreter/InterpreterModule.h" +#include "../interpreter/MethodBridge.h" +#include "../interpreter/Interpreter.h" +#include "../interpreter/MemoryUtil.h" +#include "../interpreter/InstrinctDef.h" + +using namespace hybridclr::interpreter; +using namespace hybridclr::metadata; + +//!!!{{CODE + + +//!!!}}CODE diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Data~/Templates/UnityVersion.h.tpl b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Data~/Templates/UnityVersion.h.tpl new file mode 100644 index 0000000..f0fddb8 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Data~/Templates/UnityVersion.h.tpl @@ -0,0 +1,6 @@ +#pragma once + +//!!!{{UNITY_VERSION + + +//!!!}}UNITY_VERSION \ No newline at end of file diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Data~/hybridclr_version.json b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Data~/hybridclr_version.json new file mode 100644 index 0000000..71e77c5 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Data~/hybridclr_version.json @@ -0,0 +1,39 @@ +{ + "versions": [ + { + "unity_version":"2019", + "hybridclr" : { "branch":"v7.8.1"}, + "il2cpp_plus": { "branch":"v2019-7.8.0"} + }, + { + "unity_version":"2020", + "hybridclr" : { "branch":"v7.8.1"}, + "il2cpp_plus": { "branch":"v2020-7.8.0"} + }, + { + "unity_version":"2021", + "hybridclr" : { "branch":"v7.8.1"}, + "il2cpp_plus": { "branch":"v2021-7.8.0"} + }, + { + "unity_version":"2022", + "hybridclr" : { "branch":"v7.8.1"}, + "il2cpp_plus": { "branch":"v2022-7.8.0"} + }, + { + "unity_version":"2022-tuanjie", + "hybridclr" : { "branch":"v7.8.1"}, + "il2cpp_plus": { "branch":"v2022-tuanjie-7.8.0"} + }, + { + "unity_version":"2023", + "hybridclr" : { "branch":"v7.8.1"}, + "il2cpp_plus": { "branch":"v2023-7.8.0"} + }, + { + "unity_version":"6000", + "hybridclr" : { "branch":"v7.8.1"}, + "il2cpp_plus": { "branch":"v6000-7.9.0"} + } + ] +} \ No newline at end of file diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor.meta new file mode 100644 index 0000000..003696a --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c3fabc41cf17c444995fc01a76c5dbe6 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds.meta new file mode 100644 index 0000000..5f5d553 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: daa1e09af240aae4da0741843cb2b3f3 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip.meta new file mode 100644 index 0000000..48fedff --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 08f44f6e8bfbc2c45afae7bdd2d7f21f +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Common.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Common.meta new file mode 100644 index 0000000..0e4cc9e --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Common.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 5cedddbfa873eb94496b496e2a3ce8aa +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Common/CRC.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Common/CRC.cs new file mode 100644 index 0000000..d03fcec --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Common/CRC.cs @@ -0,0 +1,55 @@ +// Common/CRC.cs + +namespace SevenZip +{ + public class CRC + { + public static readonly uint[] Table; + + static CRC() + { + Table = new uint[256]; + const uint kPoly = 0xEDB88320; + for (uint i = 0; i < 256; i++) + { + uint r = i; + for (int j = 0; j < 8; j++) + if ((r & 1) != 0) + r = (r >> 1) ^ kPoly; + else + r >>= 1; + Table[i] = r; + } + } + + uint _value = 0xFFFFFFFF; + + public void Init() { _value = 0xFFFFFFFF; } + + public void UpdateByte(byte b) + { + _value = Table[(((byte)(_value)) ^ b)] ^ (_value >> 8); + } + + public void Update(byte[] data, uint offset, uint size) + { + for (uint i = 0; i < size; i++) + _value = Table[(((byte)(_value)) ^ data[offset + i])] ^ (_value >> 8); + } + + public uint GetDigest() { return _value ^ 0xFFFFFFFF; } + + static uint CalculateDigest(byte[] data, uint offset, uint size) + { + CRC crc = new CRC(); + // crc.Init(); + crc.Update(data, offset, size); + return crc.GetDigest(); + } + + static bool VerifyDigest(uint digest, byte[] data, uint offset, uint size) + { + return (CalculateDigest(data, offset, size) == digest); + } + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Common/CRC.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Common/CRC.cs.meta new file mode 100644 index 0000000..e366fdf --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Common/CRC.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d0bb58ecc915d9d47b8567adaa2d0ca6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Common/CommandLineParser.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Common/CommandLineParser.cs new file mode 100644 index 0000000..8eabf59 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Common/CommandLineParser.cs @@ -0,0 +1,274 @@ +// CommandLineParser.cs + +using System; +using System.Collections; + +namespace SevenZip.CommandLineParser +{ + public enum SwitchType + { + Simple, + PostMinus, + LimitedPostString, + UnLimitedPostString, + PostChar + } + + public class SwitchForm + { + public string IDString; + public SwitchType Type; + public bool Multi; + public int MinLen; + public int MaxLen; + public string PostCharSet; + + public SwitchForm(string idString, SwitchType type, bool multi, + int minLen, int maxLen, string postCharSet) + { + IDString = idString; + Type = type; + Multi = multi; + MinLen = minLen; + MaxLen = maxLen; + PostCharSet = postCharSet; + } + public SwitchForm(string idString, SwitchType type, bool multi, int minLen): + this(idString, type, multi, minLen, 0, "") + { + } + public SwitchForm(string idString, SwitchType type, bool multi): + this(idString, type, multi, 0) + { + } + } + + public class SwitchResult + { + public bool ThereIs; + public bool WithMinus; + public ArrayList PostStrings = new ArrayList(); + public int PostCharIndex; + public SwitchResult() + { + ThereIs = false; + } + } + + public class Parser + { + public ArrayList NonSwitchStrings = new ArrayList(); + SwitchResult[] _switches; + + public Parser(int numSwitches) + { + _switches = new SwitchResult[numSwitches]; + for (int i = 0; i < numSwitches; i++) + _switches[i] = new SwitchResult(); + } + + bool ParseString(string srcString, SwitchForm[] switchForms) + { + int len = srcString.Length; + if (len == 0) + return false; + int pos = 0; + if (!IsItSwitchChar(srcString[pos])) + return false; + while (pos < len) + { + if (IsItSwitchChar(srcString[pos])) + pos++; + const int kNoLen = -1; + int matchedSwitchIndex = 0; + int maxLen = kNoLen; + for (int switchIndex = 0; switchIndex < _switches.Length; switchIndex++) + { + int switchLen = switchForms[switchIndex].IDString.Length; + if (switchLen <= maxLen || pos + switchLen > len) + continue; + if (String.Compare(switchForms[switchIndex].IDString, 0, + srcString, pos, switchLen, true) == 0) + { + matchedSwitchIndex = switchIndex; + maxLen = switchLen; + } + } + if (maxLen == kNoLen) + throw new Exception("maxLen == kNoLen"); + SwitchResult matchedSwitch = _switches[matchedSwitchIndex]; + SwitchForm switchForm = switchForms[matchedSwitchIndex]; + if ((!switchForm.Multi) && matchedSwitch.ThereIs) + throw new Exception("switch must be single"); + matchedSwitch.ThereIs = true; + pos += maxLen; + int tailSize = len - pos; + SwitchType type = switchForm.Type; + switch (type) + { + case SwitchType.PostMinus: + { + if (tailSize == 0) + matchedSwitch.WithMinus = false; + else + { + matchedSwitch.WithMinus = (srcString[pos] == kSwitchMinus); + if (matchedSwitch.WithMinus) + pos++; + } + break; + } + case SwitchType.PostChar: + { + if (tailSize < switchForm.MinLen) + throw new Exception("switch is not full"); + string charSet = switchForm.PostCharSet; + const int kEmptyCharValue = -1; + if (tailSize == 0) + matchedSwitch.PostCharIndex = kEmptyCharValue; + else + { + int index = charSet.IndexOf(srcString[pos]); + if (index < 0) + matchedSwitch.PostCharIndex = kEmptyCharValue; + else + { + matchedSwitch.PostCharIndex = index; + pos++; + } + } + break; + } + case SwitchType.LimitedPostString: + case SwitchType.UnLimitedPostString: + { + int minLen = switchForm.MinLen; + if (tailSize < minLen) + throw new Exception("switch is not full"); + if (type == SwitchType.UnLimitedPostString) + { + matchedSwitch.PostStrings.Add(srcString.Substring(pos)); + return true; + } + String stringSwitch = srcString.Substring(pos, minLen); + pos += minLen; + for (int i = minLen; i < switchForm.MaxLen && pos < len; i++, pos++) + { + char c = srcString[pos]; + if (IsItSwitchChar(c)) + break; + stringSwitch += c; + } + matchedSwitch.PostStrings.Add(stringSwitch); + break; + } + } + } + return true; + + } + + public void ParseStrings(SwitchForm[] switchForms, string[] commandStrings) + { + int numCommandStrings = commandStrings.Length; + bool stopSwitch = false; + for (int i = 0; i < numCommandStrings; i++) + { + string s = commandStrings[i]; + if (stopSwitch) + NonSwitchStrings.Add(s); + else + if (s == kStopSwitchParsing) + stopSwitch = true; + else + if (!ParseString(s, switchForms)) + NonSwitchStrings.Add(s); + } + } + + public SwitchResult this[int index] { get { return _switches[index]; } } + + public static int ParseCommand(CommandForm[] commandForms, string commandString, + out string postString) + { + for (int i = 0; i < commandForms.Length; i++) + { + string id = commandForms[i].IDString; + if (commandForms[i].PostStringMode) + { + if (commandString.IndexOf(id) == 0) + { + postString = commandString.Substring(id.Length); + return i; + } + } + else + if (commandString == id) + { + postString = ""; + return i; + } + } + postString = ""; + return -1; + } + + static bool ParseSubCharsCommand(int numForms, CommandSubCharsSet[] forms, + string commandString, ArrayList indices) + { + indices.Clear(); + int numUsedChars = 0; + for (int i = 0; i < numForms; i++) + { + CommandSubCharsSet charsSet = forms[i]; + int currentIndex = -1; + int len = charsSet.Chars.Length; + for (int j = 0; j < len; j++) + { + char c = charsSet.Chars[j]; + int newIndex = commandString.IndexOf(c); + if (newIndex >= 0) + { + if (currentIndex >= 0) + return false; + if (commandString.IndexOf(c, newIndex + 1) >= 0) + return false; + currentIndex = j; + numUsedChars++; + } + } + if (currentIndex == -1 && !charsSet.EmptyAllowed) + return false; + indices.Add(currentIndex); + } + return (numUsedChars == commandString.Length); + } + const char kSwitchID1 = '-'; + const char kSwitchID2 = '/'; + + const char kSwitchMinus = '-'; + const string kStopSwitchParsing = "--"; + + static bool IsItSwitchChar(char c) + { + return (c == kSwitchID1 || c == kSwitchID2); + } + } + + public class CommandForm + { + public string IDString = ""; + public bool PostStringMode = false; + public CommandForm(string idString, bool postStringMode) + { + IDString = idString; + PostStringMode = postStringMode; + } + } + + class CommandSubCharsSet + { + public string Chars = ""; + public bool EmptyAllowed = false; + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Common/CommandLineParser.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Common/CommandLineParser.cs.meta new file mode 100644 index 0000000..a35c292 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Common/CommandLineParser.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: dc0b3921c07ef224cb3656391f4317c3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Common/InBuffer.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Common/InBuffer.cs new file mode 100644 index 0000000..7c51f0b --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Common/InBuffer.cs @@ -0,0 +1,72 @@ +// InBuffer.cs + +namespace SevenZip.Buffer +{ + public class InBuffer + { + byte[] m_Buffer; + uint m_Pos; + uint m_Limit; + uint m_BufferSize; + System.IO.Stream m_Stream; + bool m_StreamWasExhausted; + ulong m_ProcessedSize; + + public InBuffer(uint bufferSize) + { + m_Buffer = new byte[bufferSize]; + m_BufferSize = bufferSize; + } + + public void Init(System.IO.Stream stream) + { + m_Stream = stream; + m_ProcessedSize = 0; + m_Limit = 0; + m_Pos = 0; + m_StreamWasExhausted = false; + } + + public bool ReadBlock() + { + if (m_StreamWasExhausted) + return false; + m_ProcessedSize += m_Pos; + int aNumProcessedBytes = m_Stream.Read(m_Buffer, 0, (int)m_BufferSize); + m_Pos = 0; + m_Limit = (uint)aNumProcessedBytes; + m_StreamWasExhausted = (aNumProcessedBytes == 0); + return (!m_StreamWasExhausted); + } + + + public void ReleaseStream() + { + // m_Stream.Close(); + m_Stream = null; + } + + public bool ReadByte(byte b) // check it + { + if (m_Pos >= m_Limit) + if (!ReadBlock()) + return false; + b = m_Buffer[m_Pos++]; + return true; + } + + public byte ReadByte() + { + // return (byte)m_Stream.ReadByte(); + if (m_Pos >= m_Limit) + if (!ReadBlock()) + return 0xFF; + return m_Buffer[m_Pos++]; + } + + public ulong GetProcessedSize() + { + return m_ProcessedSize + m_Pos; + } + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Common/InBuffer.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Common/InBuffer.cs.meta new file mode 100644 index 0000000..843e5cf --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Common/InBuffer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6ea025f5b275726479ba55e956574898 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Common/OutBuffer.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Common/OutBuffer.cs new file mode 100644 index 0000000..2da16e1 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Common/OutBuffer.cs @@ -0,0 +1,47 @@ +// OutBuffer.cs + +namespace SevenZip.Buffer +{ + public class OutBuffer + { + byte[] m_Buffer; + uint m_Pos; + uint m_BufferSize; + System.IO.Stream m_Stream; + ulong m_ProcessedSize; + + public OutBuffer(uint bufferSize) + { + m_Buffer = new byte[bufferSize]; + m_BufferSize = bufferSize; + } + + public void SetStream(System.IO.Stream stream) { m_Stream = stream; } + public void FlushStream() { m_Stream.Flush(); } + public void CloseStream() { m_Stream.Close(); } + public void ReleaseStream() { m_Stream = null; } + + public void Init() + { + m_ProcessedSize = 0; + m_Pos = 0; + } + + public void WriteByte(byte b) + { + m_Buffer[m_Pos++] = b; + if (m_Pos >= m_BufferSize) + FlushData(); + } + + public void FlushData() + { + if (m_Pos == 0) + return; + m_Stream.Write(m_Buffer, 0, (int)m_Pos); + m_Pos = 0; + } + + public ulong GetProcessedSize() { return m_ProcessedSize + m_Pos; } + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Common/OutBuffer.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Common/OutBuffer.cs.meta new file mode 100644 index 0000000..38af8c8 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Common/OutBuffer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5d61847c152e7384ab15aea89a942f54 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress.meta new file mode 100644 index 0000000..b67e6ba --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4b6765bf0d03fd243b47d74c9b73c38b +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/LZ.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/LZ.meta new file mode 100644 index 0000000..c303414 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/LZ.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a83572c42056f474db56e761a4f35e38 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/LZ/IMatchFinder.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/LZ/IMatchFinder.cs new file mode 100644 index 0000000..10ca2b3 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/LZ/IMatchFinder.cs @@ -0,0 +1,24 @@ +// IMatchFinder.cs + +using System; + +namespace SevenZip.Compression.LZ +{ + interface IInWindowStream + { + void SetStream(System.IO.Stream inStream); + void Init(); + void ReleaseStream(); + Byte GetIndexByte(Int32 index); + UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit); + UInt32 GetNumAvailableBytes(); + } + + interface IMatchFinder : IInWindowStream + { + void Create(UInt32 historySize, UInt32 keepAddBufferBefore, + UInt32 matchMaxLen, UInt32 keepAddBufferAfter); + UInt32 GetMatches(UInt32[] distances); + void Skip(UInt32 num); + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/LZ/IMatchFinder.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/LZ/IMatchFinder.cs.meta new file mode 100644 index 0000000..88c6d3d --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/LZ/IMatchFinder.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: bfd1ee430d8108042a2607d92d7f58ad +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/LZ/LzBinTree.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/LZ/LzBinTree.cs new file mode 100644 index 0000000..c1c006b --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/LZ/LzBinTree.cs @@ -0,0 +1,367 @@ +// LzBinTree.cs + +using System; + +namespace SevenZip.Compression.LZ +{ + public class BinTree : InWindow, IMatchFinder + { + UInt32 _cyclicBufferPos; + UInt32 _cyclicBufferSize = 0; + UInt32 _matchMaxLen; + + UInt32[] _son; + UInt32[] _hash; + + UInt32 _cutValue = 0xFF; + UInt32 _hashMask; + UInt32 _hashSizeSum = 0; + + bool HASH_ARRAY = true; + + const UInt32 kHash2Size = 1 << 10; + const UInt32 kHash3Size = 1 << 16; + const UInt32 kBT2HashSize = 1 << 16; + const UInt32 kStartMaxLen = 1; + const UInt32 kHash3Offset = kHash2Size; + const UInt32 kEmptyHashValue = 0; + const UInt32 kMaxValForNormalize = ((UInt32)1 << 31) - 1; + + UInt32 kNumHashDirectBytes = 0; + UInt32 kMinMatchCheck = 4; + UInt32 kFixHashSize = kHash2Size + kHash3Size; + + public void SetType(int numHashBytes) + { + HASH_ARRAY = (numHashBytes > 2); + if (HASH_ARRAY) + { + kNumHashDirectBytes = 0; + kMinMatchCheck = 4; + kFixHashSize = kHash2Size + kHash3Size; + } + else + { + kNumHashDirectBytes = 2; + kMinMatchCheck = 2 + 1; + kFixHashSize = 0; + } + } + + public new void SetStream(System.IO.Stream stream) { base.SetStream(stream); } + public new void ReleaseStream() { base.ReleaseStream(); } + + public new void Init() + { + base.Init(); + for (UInt32 i = 0; i < _hashSizeSum; i++) + _hash[i] = kEmptyHashValue; + _cyclicBufferPos = 0; + ReduceOffsets(-1); + } + + public new void MovePos() + { + if (++_cyclicBufferPos >= _cyclicBufferSize) + _cyclicBufferPos = 0; + base.MovePos(); + if (_pos == kMaxValForNormalize) + Normalize(); + } + + public new Byte GetIndexByte(Int32 index) { return base.GetIndexByte(index); } + + public new UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit) + { return base.GetMatchLen(index, distance, limit); } + + public new UInt32 GetNumAvailableBytes() { return base.GetNumAvailableBytes(); } + + public void Create(UInt32 historySize, UInt32 keepAddBufferBefore, + UInt32 matchMaxLen, UInt32 keepAddBufferAfter) + { + if (historySize > kMaxValForNormalize - 256) + throw new Exception(); + _cutValue = 16 + (matchMaxLen >> 1); + + UInt32 windowReservSize = (historySize + keepAddBufferBefore + + matchMaxLen + keepAddBufferAfter) / 2 + 256; + + base.Create(historySize + keepAddBufferBefore, matchMaxLen + keepAddBufferAfter, windowReservSize); + + _matchMaxLen = matchMaxLen; + + UInt32 cyclicBufferSize = historySize + 1; + if (_cyclicBufferSize != cyclicBufferSize) + _son = new UInt32[(_cyclicBufferSize = cyclicBufferSize) * 2]; + + UInt32 hs = kBT2HashSize; + + if (HASH_ARRAY) + { + hs = historySize - 1; + hs |= (hs >> 1); + hs |= (hs >> 2); + hs |= (hs >> 4); + hs |= (hs >> 8); + hs >>= 1; + hs |= 0xFFFF; + if (hs > (1 << 24)) + hs >>= 1; + _hashMask = hs; + hs++; + hs += kFixHashSize; + } + if (hs != _hashSizeSum) + _hash = new UInt32[_hashSizeSum = hs]; + } + + public UInt32 GetMatches(UInt32[] distances) + { + UInt32 lenLimit; + if (_pos + _matchMaxLen <= _streamPos) + lenLimit = _matchMaxLen; + else + { + lenLimit = _streamPos - _pos; + if (lenLimit < kMinMatchCheck) + { + MovePos(); + return 0; + } + } + + UInt32 offset = 0; + UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0; + UInt32 cur = _bufferOffset + _pos; + UInt32 maxLen = kStartMaxLen; // to avoid items for len < hashSize; + UInt32 hashValue, hash2Value = 0, hash3Value = 0; + + if (HASH_ARRAY) + { + UInt32 temp = CRC.Table[_bufferBase[cur]] ^ _bufferBase[cur + 1]; + hash2Value = temp & (kHash2Size - 1); + temp ^= ((UInt32)(_bufferBase[cur + 2]) << 8); + hash3Value = temp & (kHash3Size - 1); + hashValue = (temp ^ (CRC.Table[_bufferBase[cur + 3]] << 5)) & _hashMask; + } + else + hashValue = _bufferBase[cur] ^ ((UInt32)(_bufferBase[cur + 1]) << 8); + + UInt32 curMatch = _hash[kFixHashSize + hashValue]; + if (HASH_ARRAY) + { + UInt32 curMatch2 = _hash[hash2Value]; + UInt32 curMatch3 = _hash[kHash3Offset + hash3Value]; + _hash[hash2Value] = _pos; + _hash[kHash3Offset + hash3Value] = _pos; + if (curMatch2 > matchMinPos) + if (_bufferBase[_bufferOffset + curMatch2] == _bufferBase[cur]) + { + distances[offset++] = maxLen = 2; + distances[offset++] = _pos - curMatch2 - 1; + } + if (curMatch3 > matchMinPos) + if (_bufferBase[_bufferOffset + curMatch3] == _bufferBase[cur]) + { + if (curMatch3 == curMatch2) + offset -= 2; + distances[offset++] = maxLen = 3; + distances[offset++] = _pos - curMatch3 - 1; + curMatch2 = curMatch3; + } + if (offset != 0 && curMatch2 == curMatch) + { + offset -= 2; + maxLen = kStartMaxLen; + } + } + + _hash[kFixHashSize + hashValue] = _pos; + + UInt32 ptr0 = (_cyclicBufferPos << 1) + 1; + UInt32 ptr1 = (_cyclicBufferPos << 1); + + UInt32 len0, len1; + len0 = len1 = kNumHashDirectBytes; + + if (kNumHashDirectBytes != 0) + { + if (curMatch > matchMinPos) + { + if (_bufferBase[_bufferOffset + curMatch + kNumHashDirectBytes] != + _bufferBase[cur + kNumHashDirectBytes]) + { + distances[offset++] = maxLen = kNumHashDirectBytes; + distances[offset++] = _pos - curMatch - 1; + } + } + } + + UInt32 count = _cutValue; + + while(true) + { + if(curMatch <= matchMinPos || count-- == 0) + { + _son[ptr0] = _son[ptr1] = kEmptyHashValue; + break; + } + UInt32 delta = _pos - curMatch; + UInt32 cyclicPos = ((delta <= _cyclicBufferPos) ? + (_cyclicBufferPos - delta) : + (_cyclicBufferPos - delta + _cyclicBufferSize)) << 1; + + UInt32 pby1 = _bufferOffset + curMatch; + UInt32 len = Math.Min(len0, len1); + if (_bufferBase[pby1 + len] == _bufferBase[cur + len]) + { + while(++len != lenLimit) + if (_bufferBase[pby1 + len] != _bufferBase[cur + len]) + break; + if (maxLen < len) + { + distances[offset++] = maxLen = len; + distances[offset++] = delta - 1; + if (len == lenLimit) + { + _son[ptr1] = _son[cyclicPos]; + _son[ptr0] = _son[cyclicPos + 1]; + break; + } + } + } + if (_bufferBase[pby1 + len] < _bufferBase[cur + len]) + { + _son[ptr1] = curMatch; + ptr1 = cyclicPos + 1; + curMatch = _son[ptr1]; + len1 = len; + } + else + { + _son[ptr0] = curMatch; + ptr0 = cyclicPos; + curMatch = _son[ptr0]; + len0 = len; + } + } + MovePos(); + return offset; + } + + public void Skip(UInt32 num) + { + do + { + UInt32 lenLimit; + if (_pos + _matchMaxLen <= _streamPos) + lenLimit = _matchMaxLen; + else + { + lenLimit = _streamPos - _pos; + if (lenLimit < kMinMatchCheck) + { + MovePos(); + continue; + } + } + + UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0; + UInt32 cur = _bufferOffset + _pos; + + UInt32 hashValue; + + if (HASH_ARRAY) + { + UInt32 temp = CRC.Table[_bufferBase[cur]] ^ _bufferBase[cur + 1]; + UInt32 hash2Value = temp & (kHash2Size - 1); + _hash[hash2Value] = _pos; + temp ^= ((UInt32)(_bufferBase[cur + 2]) << 8); + UInt32 hash3Value = temp & (kHash3Size - 1); + _hash[kHash3Offset + hash3Value] = _pos; + hashValue = (temp ^ (CRC.Table[_bufferBase[cur + 3]] << 5)) & _hashMask; + } + else + hashValue = _bufferBase[cur] ^ ((UInt32)(_bufferBase[cur + 1]) << 8); + + UInt32 curMatch = _hash[kFixHashSize + hashValue]; + _hash[kFixHashSize + hashValue] = _pos; + + UInt32 ptr0 = (_cyclicBufferPos << 1) + 1; + UInt32 ptr1 = (_cyclicBufferPos << 1); + + UInt32 len0, len1; + len0 = len1 = kNumHashDirectBytes; + + UInt32 count = _cutValue; + while (true) + { + if (curMatch <= matchMinPos || count-- == 0) + { + _son[ptr0] = _son[ptr1] = kEmptyHashValue; + break; + } + + UInt32 delta = _pos - curMatch; + UInt32 cyclicPos = ((delta <= _cyclicBufferPos) ? + (_cyclicBufferPos - delta) : + (_cyclicBufferPos - delta + _cyclicBufferSize)) << 1; + + UInt32 pby1 = _bufferOffset + curMatch; + UInt32 len = Math.Min(len0, len1); + if (_bufferBase[pby1 + len] == _bufferBase[cur + len]) + { + while (++len != lenLimit) + if (_bufferBase[pby1 + len] != _bufferBase[cur + len]) + break; + if (len == lenLimit) + { + _son[ptr1] = _son[cyclicPos]; + _son[ptr0] = _son[cyclicPos + 1]; + break; + } + } + if (_bufferBase[pby1 + len] < _bufferBase[cur + len]) + { + _son[ptr1] = curMatch; + ptr1 = cyclicPos + 1; + curMatch = _son[ptr1]; + len1 = len; + } + else + { + _son[ptr0] = curMatch; + ptr0 = cyclicPos; + curMatch = _son[ptr0]; + len0 = len; + } + } + MovePos(); + } + while (--num != 0); + } + + void NormalizeLinks(UInt32[] items, UInt32 numItems, UInt32 subValue) + { + for (UInt32 i = 0; i < numItems; i++) + { + UInt32 value = items[i]; + if (value <= subValue) + value = kEmptyHashValue; + else + value -= subValue; + items[i] = value; + } + } + + void Normalize() + { + UInt32 subValue = _pos - _cyclicBufferSize; + NormalizeLinks(_son, _cyclicBufferSize * 2, subValue); + NormalizeLinks(_hash, _hashSizeSum, subValue); + ReduceOffsets((Int32)subValue); + } + + public void SetCutValue(UInt32 cutValue) { _cutValue = cutValue; } + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/LZ/LzBinTree.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/LZ/LzBinTree.cs.meta new file mode 100644 index 0000000..49637e8 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/LZ/LzBinTree.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3ba8015d2d5df3a459615ffc06635e6d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/LZ/LzInWindow.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/LZ/LzInWindow.cs new file mode 100644 index 0000000..52d23ce --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/LZ/LzInWindow.cs @@ -0,0 +1,132 @@ +// LzInWindow.cs + +using System; + +namespace SevenZip.Compression.LZ +{ + public class InWindow + { + public Byte[] _bufferBase = null; // pointer to buffer with data + System.IO.Stream _stream; + UInt32 _posLimit; // offset (from _buffer) of first byte when new block reading must be done + bool _streamEndWasReached; // if (true) then _streamPos shows real end of stream + + UInt32 _pointerToLastSafePosition; + + public UInt32 _bufferOffset; + + public UInt32 _blockSize; // Size of Allocated memory block + public UInt32 _pos; // offset (from _buffer) of curent byte + UInt32 _keepSizeBefore; // how many BYTEs must be kept in buffer before _pos + UInt32 _keepSizeAfter; // how many BYTEs must be kept buffer after _pos + public UInt32 _streamPos; // offset (from _buffer) of first not read byte from Stream + + public void MoveBlock() + { + UInt32 offset = (UInt32)(_bufferOffset) + _pos - _keepSizeBefore; + // we need one additional byte, since MovePos moves on 1 byte. + if (offset > 0) + offset--; + + UInt32 numBytes = (UInt32)(_bufferOffset) + _streamPos - offset; + + // check negative offset ???? + for (UInt32 i = 0; i < numBytes; i++) + _bufferBase[i] = _bufferBase[offset + i]; + _bufferOffset -= offset; + } + + public virtual void ReadBlock() + { + if (_streamEndWasReached) + return; + while (true) + { + int size = (int)((0 - _bufferOffset) + _blockSize - _streamPos); + if (size == 0) + return; + int numReadBytes = _stream.Read(_bufferBase, (int)(_bufferOffset + _streamPos), size); + if (numReadBytes == 0) + { + _posLimit = _streamPos; + UInt32 pointerToPostion = _bufferOffset + _posLimit; + if (pointerToPostion > _pointerToLastSafePosition) + _posLimit = (UInt32)(_pointerToLastSafePosition - _bufferOffset); + + _streamEndWasReached = true; + return; + } + _streamPos += (UInt32)numReadBytes; + if (_streamPos >= _pos + _keepSizeAfter) + _posLimit = _streamPos - _keepSizeAfter; + } + } + + void Free() { _bufferBase = null; } + + public void Create(UInt32 keepSizeBefore, UInt32 keepSizeAfter, UInt32 keepSizeReserv) + { + _keepSizeBefore = keepSizeBefore; + _keepSizeAfter = keepSizeAfter; + UInt32 blockSize = keepSizeBefore + keepSizeAfter + keepSizeReserv; + if (_bufferBase == null || _blockSize != blockSize) + { + Free(); + _blockSize = blockSize; + _bufferBase = new Byte[_blockSize]; + } + _pointerToLastSafePosition = _blockSize - keepSizeAfter; + } + + public void SetStream(System.IO.Stream stream) { _stream = stream; } + public void ReleaseStream() { _stream = null; } + + public void Init() + { + _bufferOffset = 0; + _pos = 0; + _streamPos = 0; + _streamEndWasReached = false; + ReadBlock(); + } + + public void MovePos() + { + _pos++; + if (_pos > _posLimit) + { + UInt32 pointerToPostion = _bufferOffset + _pos; + if (pointerToPostion > _pointerToLastSafePosition) + MoveBlock(); + ReadBlock(); + } + } + + public Byte GetIndexByte(Int32 index) { return _bufferBase[_bufferOffset + _pos + index]; } + + // index + limit have not to exceed _keepSizeAfter; + public UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit) + { + if (_streamEndWasReached) + if ((_pos + index) + limit > _streamPos) + limit = _streamPos - (UInt32)(_pos + index); + distance++; + // Byte *pby = _buffer + (size_t)_pos + index; + UInt32 pby = _bufferOffset + _pos + (UInt32)index; + + UInt32 i; + for (i = 0; i < limit && _bufferBase[pby + i] == _bufferBase[pby + i - distance]; i++); + return i; + } + + public UInt32 GetNumAvailableBytes() { return _streamPos - _pos; } + + public void ReduceOffsets(Int32 subValue) + { + _bufferOffset += (UInt32)subValue; + _posLimit -= (UInt32)subValue; + _pos -= (UInt32)subValue; + _streamPos -= (UInt32)subValue; + } + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/LZ/LzInWindow.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/LZ/LzInWindow.cs.meta new file mode 100644 index 0000000..f1e45d6 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/LZ/LzInWindow.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 333112c3785a6ec4cbbfec8515081cac +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/LZ/LzOutWindow.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/LZ/LzOutWindow.cs new file mode 100644 index 0000000..c998584 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/LZ/LzOutWindow.cs @@ -0,0 +1,110 @@ +// LzOutWindow.cs + +namespace SevenZip.Compression.LZ +{ + public class OutWindow + { + byte[] _buffer = null; + uint _pos; + uint _windowSize = 0; + uint _streamPos; + System.IO.Stream _stream; + + public uint TrainSize = 0; + + public void Create(uint windowSize) + { + if (_windowSize != windowSize) + { + // System.GC.Collect(); + _buffer = new byte[windowSize]; + } + _windowSize = windowSize; + _pos = 0; + _streamPos = 0; + } + + public void Init(System.IO.Stream stream, bool solid) + { + ReleaseStream(); + _stream = stream; + if (!solid) + { + _streamPos = 0; + _pos = 0; + TrainSize = 0; + } + } + + public bool Train(System.IO.Stream stream) + { + long len = stream.Length; + uint size = (len < _windowSize) ? (uint)len : _windowSize; + TrainSize = size; + stream.Position = len - size; + _streamPos = _pos = 0; + while (size > 0) + { + uint curSize = _windowSize - _pos; + if (size < curSize) + curSize = size; + int numReadBytes = stream.Read(_buffer, (int)_pos, (int)curSize); + if (numReadBytes == 0) + return false; + size -= (uint)numReadBytes; + _pos += (uint)numReadBytes; + _streamPos += (uint)numReadBytes; + if (_pos == _windowSize) + _streamPos = _pos = 0; + } + return true; + } + + public void ReleaseStream() + { + Flush(); + _stream = null; + } + + public void Flush() + { + uint size = _pos - _streamPos; + if (size == 0) + return; + _stream.Write(_buffer, (int)_streamPos, (int)size); + if (_pos >= _windowSize) + _pos = 0; + _streamPos = _pos; + } + + public void CopyBlock(uint distance, uint len) + { + uint pos = _pos - distance - 1; + if (pos >= _windowSize) + pos += _windowSize; + for (; len > 0; len--) + { + if (pos >= _windowSize) + pos = 0; + _buffer[_pos++] = _buffer[pos++]; + if (_pos >= _windowSize) + Flush(); + } + } + + public void PutByte(byte b) + { + _buffer[_pos++] = b; + if (_pos >= _windowSize) + Flush(); + } + + public byte GetByte(uint distance) + { + uint pos = _pos - distance - 1; + if (pos >= _windowSize) + pos += _windowSize; + return _buffer[pos]; + } + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/LZ/LzOutWindow.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/LZ/LzOutWindow.cs.meta new file mode 100644 index 0000000..7b3f534 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/LZ/LzOutWindow.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: bb296a6e14ab7c44cb6388693d581a62 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/LZMA.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/LZMA.meta new file mode 100644 index 0000000..5c45968 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/LZMA.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 5fcd2f5c8b724164a8a01cee73896d1a +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/LZMA/LzmaBase.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/LZMA/LzmaBase.cs new file mode 100644 index 0000000..c7bca86 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/LZMA/LzmaBase.cs @@ -0,0 +1,76 @@ +// LzmaBase.cs + +namespace SevenZip.Compression.LZMA +{ + internal abstract class Base + { + public const uint kNumRepDistances = 4; + public const uint kNumStates = 12; + + // static byte []kLiteralNextStates = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5}; + // static byte []kMatchNextStates = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10}; + // static byte []kRepNextStates = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11}; + // static byte []kShortRepNextStates = {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11}; + + public struct State + { + public uint Index; + public void Init() { Index = 0; } + public void UpdateChar() + { + if (Index < 4) Index = 0; + else if (Index < 10) Index -= 3; + else Index -= 6; + } + public void UpdateMatch() { Index = (uint)(Index < 7 ? 7 : 10); } + public void UpdateRep() { Index = (uint)(Index < 7 ? 8 : 11); } + public void UpdateShortRep() { Index = (uint)(Index < 7 ? 9 : 11); } + public bool IsCharState() { return Index < 7; } + } + + public const int kNumPosSlotBits = 6; + public const int kDicLogSizeMin = 0; + // public const int kDicLogSizeMax = 30; + // public const uint kDistTableSizeMax = kDicLogSizeMax * 2; + + public const int kNumLenToPosStatesBits = 2; // it's for speed optimization + public const uint kNumLenToPosStates = 1 << kNumLenToPosStatesBits; + + public const uint kMatchMinLen = 2; + + public static uint GetLenToPosState(uint len) + { + len -= kMatchMinLen; + if (len < kNumLenToPosStates) + return len; + return (uint)(kNumLenToPosStates - 1); + } + + public const int kNumAlignBits = 4; + public const uint kAlignTableSize = 1 << kNumAlignBits; + public const uint kAlignMask = (kAlignTableSize - 1); + + public const uint kStartPosModelIndex = 4; + public const uint kEndPosModelIndex = 14; + public const uint kNumPosModels = kEndPosModelIndex - kStartPosModelIndex; + + public const uint kNumFullDistances = 1 << ((int)kEndPosModelIndex / 2); + + public const uint kNumLitPosStatesBitsEncodingMax = 4; + public const uint kNumLitContextBitsMax = 8; + + public const int kNumPosStatesBitsMax = 4; + public const uint kNumPosStatesMax = (1 << kNumPosStatesBitsMax); + public const int kNumPosStatesBitsEncodingMax = 4; + public const uint kNumPosStatesEncodingMax = (1 << kNumPosStatesBitsEncodingMax); + + public const int kNumLowLenBits = 3; + public const int kNumMidLenBits = 3; + public const int kNumHighLenBits = 8; + public const uint kNumLowLenSymbols = 1 << kNumLowLenBits; + public const uint kNumMidLenSymbols = 1 << kNumMidLenBits; + public const uint kNumLenSymbols = kNumLowLenSymbols + kNumMidLenSymbols + + (1 << kNumHighLenBits); + public const uint kMatchMaxLen = kMatchMinLen + kNumLenSymbols - 1; + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/LZMA/LzmaBase.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/LZMA/LzmaBase.cs.meta new file mode 100644 index 0000000..10b16ed --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/LZMA/LzmaBase.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 62f365191077342479f8227edadf57e3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/LZMA/LzmaDecoder.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/LZMA/LzmaDecoder.cs new file mode 100644 index 0000000..a9be39f --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/LZMA/LzmaDecoder.cs @@ -0,0 +1,398 @@ +// LzmaDecoder.cs + +using System; + +namespace SevenZip.Compression.LZMA +{ + using RangeCoder; + + public class Decoder : ICoder, ISetDecoderProperties // ,System.IO.Stream + { + class LenDecoder + { + BitDecoder m_Choice = new BitDecoder(); + BitDecoder m_Choice2 = new BitDecoder(); + BitTreeDecoder[] m_LowCoder = new BitTreeDecoder[Base.kNumPosStatesMax]; + BitTreeDecoder[] m_MidCoder = new BitTreeDecoder[Base.kNumPosStatesMax]; + BitTreeDecoder m_HighCoder = new BitTreeDecoder(Base.kNumHighLenBits); + uint m_NumPosStates = 0; + + public void Create(uint numPosStates) + { + for (uint posState = m_NumPosStates; posState < numPosStates; posState++) + { + m_LowCoder[posState] = new BitTreeDecoder(Base.kNumLowLenBits); + m_MidCoder[posState] = new BitTreeDecoder(Base.kNumMidLenBits); + } + m_NumPosStates = numPosStates; + } + + public void Init() + { + m_Choice.Init(); + for (uint posState = 0; posState < m_NumPosStates; posState++) + { + m_LowCoder[posState].Init(); + m_MidCoder[posState].Init(); + } + m_Choice2.Init(); + m_HighCoder.Init(); + } + + public uint Decode(RangeCoder.Decoder rangeDecoder, uint posState) + { + if (m_Choice.Decode(rangeDecoder) == 0) + return m_LowCoder[posState].Decode(rangeDecoder); + else + { + uint symbol = Base.kNumLowLenSymbols; + if (m_Choice2.Decode(rangeDecoder) == 0) + symbol += m_MidCoder[posState].Decode(rangeDecoder); + else + { + symbol += Base.kNumMidLenSymbols; + symbol += m_HighCoder.Decode(rangeDecoder); + } + return symbol; + } + } + } + + class LiteralDecoder + { + struct Decoder2 + { + BitDecoder[] m_Decoders; + public void Create() { m_Decoders = new BitDecoder[0x300]; } + public void Init() { for (int i = 0; i < 0x300; i++) m_Decoders[i].Init(); } + + public byte DecodeNormal(RangeCoder.Decoder rangeDecoder) + { + uint symbol = 1; + do + symbol = (symbol << 1) | m_Decoders[symbol].Decode(rangeDecoder); + while (symbol < 0x100); + return (byte)symbol; + } + + public byte DecodeWithMatchByte(RangeCoder.Decoder rangeDecoder, byte matchByte) + { + uint symbol = 1; + do + { + uint matchBit = (uint)(matchByte >> 7) & 1; + matchByte <<= 1; + uint bit = m_Decoders[((1 + matchBit) << 8) + symbol].Decode(rangeDecoder); + symbol = (symbol << 1) | bit; + if (matchBit != bit) + { + while (symbol < 0x100) + symbol = (symbol << 1) | m_Decoders[symbol].Decode(rangeDecoder); + break; + } + } + while (symbol < 0x100); + return (byte)symbol; + } + } + + Decoder2[] m_Coders; + int m_NumPrevBits; + int m_NumPosBits; + uint m_PosMask; + + public void Create(int numPosBits, int numPrevBits) + { + if (m_Coders != null && m_NumPrevBits == numPrevBits && + m_NumPosBits == numPosBits) + return; + m_NumPosBits = numPosBits; + m_PosMask = ((uint)1 << numPosBits) - 1; + m_NumPrevBits = numPrevBits; + uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits); + m_Coders = new Decoder2[numStates]; + for (uint i = 0; i < numStates; i++) + m_Coders[i].Create(); + } + + public void Init() + { + uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits); + for (uint i = 0; i < numStates; i++) + m_Coders[i].Init(); + } + + uint GetState(uint pos, byte prevByte) + { return ((pos & m_PosMask) << m_NumPrevBits) + (uint)(prevByte >> (8 - m_NumPrevBits)); } + + public byte DecodeNormal(RangeCoder.Decoder rangeDecoder, uint pos, byte prevByte) + { return m_Coders[GetState(pos, prevByte)].DecodeNormal(rangeDecoder); } + + public byte DecodeWithMatchByte(RangeCoder.Decoder rangeDecoder, uint pos, byte prevByte, byte matchByte) + { return m_Coders[GetState(pos, prevByte)].DecodeWithMatchByte(rangeDecoder, matchByte); } + }; + + LZ.OutWindow m_OutWindow = new LZ.OutWindow(); + RangeCoder.Decoder m_RangeDecoder = new RangeCoder.Decoder(); + + BitDecoder[] m_IsMatchDecoders = new BitDecoder[Base.kNumStates << Base.kNumPosStatesBitsMax]; + BitDecoder[] m_IsRepDecoders = new BitDecoder[Base.kNumStates]; + BitDecoder[] m_IsRepG0Decoders = new BitDecoder[Base.kNumStates]; + BitDecoder[] m_IsRepG1Decoders = new BitDecoder[Base.kNumStates]; + BitDecoder[] m_IsRepG2Decoders = new BitDecoder[Base.kNumStates]; + BitDecoder[] m_IsRep0LongDecoders = new BitDecoder[Base.kNumStates << Base.kNumPosStatesBitsMax]; + + BitTreeDecoder[] m_PosSlotDecoder = new BitTreeDecoder[Base.kNumLenToPosStates]; + BitDecoder[] m_PosDecoders = new BitDecoder[Base.kNumFullDistances - Base.kEndPosModelIndex]; + + BitTreeDecoder m_PosAlignDecoder = new BitTreeDecoder(Base.kNumAlignBits); + + LenDecoder m_LenDecoder = new LenDecoder(); + LenDecoder m_RepLenDecoder = new LenDecoder(); + + LiteralDecoder m_LiteralDecoder = new LiteralDecoder(); + + uint m_DictionarySize; + uint m_DictionarySizeCheck; + + uint m_PosStateMask; + + public Decoder() + { + m_DictionarySize = 0xFFFFFFFF; + for (int i = 0; i < Base.kNumLenToPosStates; i++) + m_PosSlotDecoder[i] = new BitTreeDecoder(Base.kNumPosSlotBits); + } + + void SetDictionarySize(uint dictionarySize) + { + if (m_DictionarySize != dictionarySize) + { + m_DictionarySize = dictionarySize; + m_DictionarySizeCheck = Math.Max(m_DictionarySize, 1); + uint blockSize = Math.Max(m_DictionarySizeCheck, (1 << 12)); + m_OutWindow.Create(blockSize); + } + } + + void SetLiteralProperties(int lp, int lc) + { + if (lp > 8) + throw new InvalidParamException(); + if (lc > 8) + throw new InvalidParamException(); + m_LiteralDecoder.Create(lp, lc); + } + + void SetPosBitsProperties(int pb) + { + if (pb > Base.kNumPosStatesBitsMax) + throw new InvalidParamException(); + uint numPosStates = (uint)1 << pb; + m_LenDecoder.Create(numPosStates); + m_RepLenDecoder.Create(numPosStates); + m_PosStateMask = numPosStates - 1; + } + + bool _solid = false; + void Init(System.IO.Stream inStream, System.IO.Stream outStream) + { + m_RangeDecoder.Init(inStream); + m_OutWindow.Init(outStream, _solid); + + uint i; + for (i = 0; i < Base.kNumStates; i++) + { + for (uint j = 0; j <= m_PosStateMask; j++) + { + uint index = (i << Base.kNumPosStatesBitsMax) + j; + m_IsMatchDecoders[index].Init(); + m_IsRep0LongDecoders[index].Init(); + } + m_IsRepDecoders[i].Init(); + m_IsRepG0Decoders[i].Init(); + m_IsRepG1Decoders[i].Init(); + m_IsRepG2Decoders[i].Init(); + } + + m_LiteralDecoder.Init(); + for (i = 0; i < Base.kNumLenToPosStates; i++) + m_PosSlotDecoder[i].Init(); + // m_PosSpecDecoder.Init(); + for (i = 0; i < Base.kNumFullDistances - Base.kEndPosModelIndex; i++) + m_PosDecoders[i].Init(); + + m_LenDecoder.Init(); + m_RepLenDecoder.Init(); + m_PosAlignDecoder.Init(); + } + + public void Code(System.IO.Stream inStream, System.IO.Stream outStream, + Int64 inSize, Int64 outSize, ICodeProgress progress) + { + Init(inStream, outStream); + + Base.State state = new Base.State(); + state.Init(); + uint rep0 = 0, rep1 = 0, rep2 = 0, rep3 = 0; + + UInt64 nowPos64 = 0; + UInt64 outSize64 = (UInt64)outSize; + if (nowPos64 < outSize64) + { + if (m_IsMatchDecoders[state.Index << Base.kNumPosStatesBitsMax].Decode(m_RangeDecoder) != 0) + throw new DataErrorException(); + state.UpdateChar(); + byte b = m_LiteralDecoder.DecodeNormal(m_RangeDecoder, 0, 0); + m_OutWindow.PutByte(b); + nowPos64++; + } + while (nowPos64 < outSize64) + { + // UInt64 next = Math.Min(nowPos64 + (1 << 18), outSize64); + // while(nowPos64 < next) + { + uint posState = (uint)nowPos64 & m_PosStateMask; + if (m_IsMatchDecoders[(state.Index << Base.kNumPosStatesBitsMax) + posState].Decode(m_RangeDecoder) == 0) + { + byte b; + byte prevByte = m_OutWindow.GetByte(0); + if (!state.IsCharState()) + b = m_LiteralDecoder.DecodeWithMatchByte(m_RangeDecoder, + (uint)nowPos64, prevByte, m_OutWindow.GetByte(rep0)); + else + b = m_LiteralDecoder.DecodeNormal(m_RangeDecoder, (uint)nowPos64, prevByte); + m_OutWindow.PutByte(b); + state.UpdateChar(); + nowPos64++; + } + else + { + uint len; + if (m_IsRepDecoders[state.Index].Decode(m_RangeDecoder) == 1) + { + if (m_IsRepG0Decoders[state.Index].Decode(m_RangeDecoder) == 0) + { + if (m_IsRep0LongDecoders[(state.Index << Base.kNumPosStatesBitsMax) + posState].Decode(m_RangeDecoder) == 0) + { + state.UpdateShortRep(); + m_OutWindow.PutByte(m_OutWindow.GetByte(rep0)); + nowPos64++; + continue; + } + } + else + { + UInt32 distance; + if (m_IsRepG1Decoders[state.Index].Decode(m_RangeDecoder) == 0) + { + distance = rep1; + } + else + { + if (m_IsRepG2Decoders[state.Index].Decode(m_RangeDecoder) == 0) + distance = rep2; + else + { + distance = rep3; + rep3 = rep2; + } + rep2 = rep1; + } + rep1 = rep0; + rep0 = distance; + } + len = m_RepLenDecoder.Decode(m_RangeDecoder, posState) + Base.kMatchMinLen; + state.UpdateRep(); + } + else + { + rep3 = rep2; + rep2 = rep1; + rep1 = rep0; + len = Base.kMatchMinLen + m_LenDecoder.Decode(m_RangeDecoder, posState); + state.UpdateMatch(); + uint posSlot = m_PosSlotDecoder[Base.GetLenToPosState(len)].Decode(m_RangeDecoder); + if (posSlot >= Base.kStartPosModelIndex) + { + int numDirectBits = (int)((posSlot >> 1) - 1); + rep0 = ((2 | (posSlot & 1)) << numDirectBits); + if (posSlot < Base.kEndPosModelIndex) + rep0 += BitTreeDecoder.ReverseDecode(m_PosDecoders, + rep0 - posSlot - 1, m_RangeDecoder, numDirectBits); + else + { + rep0 += (m_RangeDecoder.DecodeDirectBits( + numDirectBits - Base.kNumAlignBits) << Base.kNumAlignBits); + rep0 += m_PosAlignDecoder.ReverseDecode(m_RangeDecoder); + } + } + else + rep0 = posSlot; + } + if (rep0 >= m_OutWindow.TrainSize + nowPos64 || rep0 >= m_DictionarySizeCheck) + { + if (rep0 == 0xFFFFFFFF) + break; + throw new DataErrorException(); + } + m_OutWindow.CopyBlock(rep0, len); + nowPos64 += len; + } + } + } + m_OutWindow.Flush(); + m_OutWindow.ReleaseStream(); + m_RangeDecoder.ReleaseStream(); + } + + public void SetDecoderProperties(byte[] properties) + { + if (properties.Length < 5) + throw new InvalidParamException(); + int lc = properties[0] % 9; + int remainder = properties[0] / 9; + int lp = remainder % 5; + int pb = remainder / 5; + if (pb > Base.kNumPosStatesBitsMax) + throw new InvalidParamException(); + UInt32 dictionarySize = 0; + for (int i = 0; i < 4; i++) + dictionarySize += ((UInt32)(properties[1 + i])) << (i * 8); + SetDictionarySize(dictionarySize); + SetLiteralProperties(lp, lc); + SetPosBitsProperties(pb); + } + + public bool Train(System.IO.Stream stream) + { + _solid = true; + return m_OutWindow.Train(stream); + } + + /* + public override bool CanRead { get { return true; }} + public override bool CanWrite { get { return true; }} + public override bool CanSeek { get { return true; }} + public override long Length { get { return 0; }} + public override long Position + { + get { return 0; } + set { } + } + public override void Flush() { } + public override int Read(byte[] buffer, int offset, int count) + { + return 0; + } + public override void Write(byte[] buffer, int offset, int count) + { + } + public override long Seek(long offset, System.IO.SeekOrigin origin) + { + return 0; + } + public override void SetLength(long value) {} + */ + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/LZMA/LzmaDecoder.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/LZMA/LzmaDecoder.cs.meta new file mode 100644 index 0000000..2725167 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/LZMA/LzmaDecoder.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c60a9ce2c6df6774498e337ad69a356b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/LZMA/LzmaEncoder.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/LZMA/LzmaEncoder.cs new file mode 100644 index 0000000..0237c51 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/LZMA/LzmaEncoder.cs @@ -0,0 +1,1480 @@ +// LzmaEncoder.cs + +using System; + +namespace SevenZip.Compression.LZMA +{ + using RangeCoder; + + public class Encoder : ICoder, ISetCoderProperties, IWriteCoderProperties + { + enum EMatchFinderType + { + BT2, + BT4, + }; + + const UInt32 kIfinityPrice = 0xFFFFFFF; + + static Byte[] g_FastPos = new Byte[1 << 11]; + + static Encoder() + { + const Byte kFastSlots = 22; + int c = 2; + g_FastPos[0] = 0; + g_FastPos[1] = 1; + for (Byte slotFast = 2; slotFast < kFastSlots; slotFast++) + { + UInt32 k = ((UInt32)1 << ((slotFast >> 1) - 1)); + for (UInt32 j = 0; j < k; j++, c++) + g_FastPos[c] = slotFast; + } + } + + static UInt32 GetPosSlot(UInt32 pos) + { + if (pos < (1 << 11)) + return g_FastPos[pos]; + if (pos < (1 << 21)) + return (UInt32)(g_FastPos[pos >> 10] + 20); + return (UInt32)(g_FastPos[pos >> 20] + 40); + } + + static UInt32 GetPosSlot2(UInt32 pos) + { + if (pos < (1 << 17)) + return (UInt32)(g_FastPos[pos >> 6] + 12); + if (pos < (1 << 27)) + return (UInt32)(g_FastPos[pos >> 16] + 32); + return (UInt32)(g_FastPos[pos >> 26] + 52); + } + + Base.State _state = new Base.State(); + Byte _previousByte; + UInt32[] _repDistances = new UInt32[Base.kNumRepDistances]; + + void BaseInit() + { + _state.Init(); + _previousByte = 0; + for (UInt32 i = 0; i < Base.kNumRepDistances; i++) + _repDistances[i] = 0; + } + + const int kDefaultDictionaryLogSize = 22; + const UInt32 kNumFastBytesDefault = 0x20; + + class LiteralEncoder + { + public struct Encoder2 + { + BitEncoder[] m_Encoders; + + public void Create() { m_Encoders = new BitEncoder[0x300]; } + + public void Init() { for (int i = 0; i < 0x300; i++) m_Encoders[i].Init(); } + + public void Encode(RangeCoder.Encoder rangeEncoder, byte symbol) + { + uint context = 1; + for (int i = 7; i >= 0; i--) + { + uint bit = (uint)((symbol >> i) & 1); + m_Encoders[context].Encode(rangeEncoder, bit); + context = (context << 1) | bit; + } + } + + public void EncodeMatched(RangeCoder.Encoder rangeEncoder, byte matchByte, byte symbol) + { + uint context = 1; + bool same = true; + for (int i = 7; i >= 0; i--) + { + uint bit = (uint)((symbol >> i) & 1); + uint state = context; + if (same) + { + uint matchBit = (uint)((matchByte >> i) & 1); + state += ((1 + matchBit) << 8); + same = (matchBit == bit); + } + m_Encoders[state].Encode(rangeEncoder, bit); + context = (context << 1) | bit; + } + } + + public uint GetPrice(bool matchMode, byte matchByte, byte symbol) + { + uint price = 0; + uint context = 1; + int i = 7; + if (matchMode) + { + for (; i >= 0; i--) + { + uint matchBit = (uint)(matchByte >> i) & 1; + uint bit = (uint)(symbol >> i) & 1; + price += m_Encoders[((1 + matchBit) << 8) + context].GetPrice(bit); + context = (context << 1) | bit; + if (matchBit != bit) + { + i--; + break; + } + } + } + for (; i >= 0; i--) + { + uint bit = (uint)(symbol >> i) & 1; + price += m_Encoders[context].GetPrice(bit); + context = (context << 1) | bit; + } + return price; + } + } + + Encoder2[] m_Coders; + int m_NumPrevBits; + int m_NumPosBits; + uint m_PosMask; + + public void Create(int numPosBits, int numPrevBits) + { + if (m_Coders != null && m_NumPrevBits == numPrevBits && m_NumPosBits == numPosBits) + return; + m_NumPosBits = numPosBits; + m_PosMask = ((uint)1 << numPosBits) - 1; + m_NumPrevBits = numPrevBits; + uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits); + m_Coders = new Encoder2[numStates]; + for (uint i = 0; i < numStates; i++) + m_Coders[i].Create(); + } + + public void Init() + { + uint numStates = (uint)1 << (m_NumPrevBits + m_NumPosBits); + for (uint i = 0; i < numStates; i++) + m_Coders[i].Init(); + } + + public Encoder2 GetSubCoder(UInt32 pos, Byte prevByte) + { return m_Coders[((pos & m_PosMask) << m_NumPrevBits) + (uint)(prevByte >> (8 - m_NumPrevBits))]; } + } + + class LenEncoder + { + RangeCoder.BitEncoder _choice = new RangeCoder.BitEncoder(); + RangeCoder.BitEncoder _choice2 = new RangeCoder.BitEncoder(); + RangeCoder.BitTreeEncoder[] _lowCoder = new RangeCoder.BitTreeEncoder[Base.kNumPosStatesEncodingMax]; + RangeCoder.BitTreeEncoder[] _midCoder = new RangeCoder.BitTreeEncoder[Base.kNumPosStatesEncodingMax]; + RangeCoder.BitTreeEncoder _highCoder = new RangeCoder.BitTreeEncoder(Base.kNumHighLenBits); + + public LenEncoder() + { + for (UInt32 posState = 0; posState < Base.kNumPosStatesEncodingMax; posState++) + { + _lowCoder[posState] = new RangeCoder.BitTreeEncoder(Base.kNumLowLenBits); + _midCoder[posState] = new RangeCoder.BitTreeEncoder(Base.kNumMidLenBits); + } + } + + public void Init(UInt32 numPosStates) + { + _choice.Init(); + _choice2.Init(); + for (UInt32 posState = 0; posState < numPosStates; posState++) + { + _lowCoder[posState].Init(); + _midCoder[posState].Init(); + } + _highCoder.Init(); + } + + public void Encode(RangeCoder.Encoder rangeEncoder, UInt32 symbol, UInt32 posState) + { + if (symbol < Base.kNumLowLenSymbols) + { + _choice.Encode(rangeEncoder, 0); + _lowCoder[posState].Encode(rangeEncoder, symbol); + } + else + { + symbol -= Base.kNumLowLenSymbols; + _choice.Encode(rangeEncoder, 1); + if (symbol < Base.kNumMidLenSymbols) + { + _choice2.Encode(rangeEncoder, 0); + _midCoder[posState].Encode(rangeEncoder, symbol); + } + else + { + _choice2.Encode(rangeEncoder, 1); + _highCoder.Encode(rangeEncoder, symbol - Base.kNumMidLenSymbols); + } + } + } + + public void SetPrices(UInt32 posState, UInt32 numSymbols, UInt32[] prices, UInt32 st) + { + UInt32 a0 = _choice.GetPrice0(); + UInt32 a1 = _choice.GetPrice1(); + UInt32 b0 = a1 + _choice2.GetPrice0(); + UInt32 b1 = a1 + _choice2.GetPrice1(); + UInt32 i = 0; + for (i = 0; i < Base.kNumLowLenSymbols; i++) + { + if (i >= numSymbols) + return; + prices[st + i] = a0 + _lowCoder[posState].GetPrice(i); + } + for (; i < Base.kNumLowLenSymbols + Base.kNumMidLenSymbols; i++) + { + if (i >= numSymbols) + return; + prices[st + i] = b0 + _midCoder[posState].GetPrice(i - Base.kNumLowLenSymbols); + } + for (; i < numSymbols; i++) + prices[st + i] = b1 + _highCoder.GetPrice(i - Base.kNumLowLenSymbols - Base.kNumMidLenSymbols); + } + }; + + const UInt32 kNumLenSpecSymbols = Base.kNumLowLenSymbols + Base.kNumMidLenSymbols; + + class LenPriceTableEncoder : LenEncoder + { + UInt32[] _prices = new UInt32[Base.kNumLenSymbols << Base.kNumPosStatesBitsEncodingMax]; + UInt32 _tableSize; + UInt32[] _counters = new UInt32[Base.kNumPosStatesEncodingMax]; + + public void SetTableSize(UInt32 tableSize) { _tableSize = tableSize; } + + public UInt32 GetPrice(UInt32 symbol, UInt32 posState) + { + return _prices[posState * Base.kNumLenSymbols + symbol]; + } + + void UpdateTable(UInt32 posState) + { + SetPrices(posState, _tableSize, _prices, posState * Base.kNumLenSymbols); + _counters[posState] = _tableSize; + } + + public void UpdateTables(UInt32 numPosStates) + { + for (UInt32 posState = 0; posState < numPosStates; posState++) + UpdateTable(posState); + } + + public new void Encode(RangeCoder.Encoder rangeEncoder, UInt32 symbol, UInt32 posState) + { + base.Encode(rangeEncoder, symbol, posState); + if (--_counters[posState] == 0) + UpdateTable(posState); + } + } + + const UInt32 kNumOpts = 1 << 12; + class Optimal + { + public Base.State State; + + public bool Prev1IsChar; + public bool Prev2; + + public UInt32 PosPrev2; + public UInt32 BackPrev2; + + public UInt32 Price; + public UInt32 PosPrev; + public UInt32 BackPrev; + + public UInt32 Backs0; + public UInt32 Backs1; + public UInt32 Backs2; + public UInt32 Backs3; + + public void MakeAsChar() { BackPrev = 0xFFFFFFFF; Prev1IsChar = false; } + public void MakeAsShortRep() { BackPrev = 0; ; Prev1IsChar = false; } + public bool IsShortRep() { return (BackPrev == 0); } + }; + Optimal[] _optimum = new Optimal[kNumOpts]; + LZ.IMatchFinder _matchFinder = null; + RangeCoder.Encoder _rangeEncoder = new RangeCoder.Encoder(); + + RangeCoder.BitEncoder[] _isMatch = new RangeCoder.BitEncoder[Base.kNumStates << Base.kNumPosStatesBitsMax]; + RangeCoder.BitEncoder[] _isRep = new RangeCoder.BitEncoder[Base.kNumStates]; + RangeCoder.BitEncoder[] _isRepG0 = new RangeCoder.BitEncoder[Base.kNumStates]; + RangeCoder.BitEncoder[] _isRepG1 = new RangeCoder.BitEncoder[Base.kNumStates]; + RangeCoder.BitEncoder[] _isRepG2 = new RangeCoder.BitEncoder[Base.kNumStates]; + RangeCoder.BitEncoder[] _isRep0Long = new RangeCoder.BitEncoder[Base.kNumStates << Base.kNumPosStatesBitsMax]; + + RangeCoder.BitTreeEncoder[] _posSlotEncoder = new RangeCoder.BitTreeEncoder[Base.kNumLenToPosStates]; + + RangeCoder.BitEncoder[] _posEncoders = new RangeCoder.BitEncoder[Base.kNumFullDistances - Base.kEndPosModelIndex]; + RangeCoder.BitTreeEncoder _posAlignEncoder = new RangeCoder.BitTreeEncoder(Base.kNumAlignBits); + + LenPriceTableEncoder _lenEncoder = new LenPriceTableEncoder(); + LenPriceTableEncoder _repMatchLenEncoder = new LenPriceTableEncoder(); + + LiteralEncoder _literalEncoder = new LiteralEncoder(); + + UInt32[] _matchDistances = new UInt32[Base.kMatchMaxLen * 2 + 2]; + + UInt32 _numFastBytes = kNumFastBytesDefault; + UInt32 _longestMatchLength; + UInt32 _numDistancePairs; + + UInt32 _additionalOffset; + + UInt32 _optimumEndIndex; + UInt32 _optimumCurrentIndex; + + bool _longestMatchWasFound; + + UInt32[] _posSlotPrices = new UInt32[1 << (Base.kNumPosSlotBits + Base.kNumLenToPosStatesBits)]; + UInt32[] _distancesPrices = new UInt32[Base.kNumFullDistances << Base.kNumLenToPosStatesBits]; + UInt32[] _alignPrices = new UInt32[Base.kAlignTableSize]; + UInt32 _alignPriceCount; + + UInt32 _distTableSize = (kDefaultDictionaryLogSize * 2); + + int _posStateBits = 2; + UInt32 _posStateMask = (4 - 1); + int _numLiteralPosStateBits = 0; + int _numLiteralContextBits = 3; + + UInt32 _dictionarySize = (1 << kDefaultDictionaryLogSize); + UInt32 _dictionarySizePrev = 0xFFFFFFFF; + UInt32 _numFastBytesPrev = 0xFFFFFFFF; + + Int64 nowPos64; + bool _finished; + System.IO.Stream _inStream; + + EMatchFinderType _matchFinderType = EMatchFinderType.BT4; + bool _writeEndMark = false; + + bool _needReleaseMFStream; + + void Create() + { + if (_matchFinder == null) + { + LZ.BinTree bt = new LZ.BinTree(); + int numHashBytes = 4; + if (_matchFinderType == EMatchFinderType.BT2) + numHashBytes = 2; + bt.SetType(numHashBytes); + _matchFinder = bt; + } + _literalEncoder.Create(_numLiteralPosStateBits, _numLiteralContextBits); + + if (_dictionarySize == _dictionarySizePrev && _numFastBytesPrev == _numFastBytes) + return; + _matchFinder.Create(_dictionarySize, kNumOpts, _numFastBytes, Base.kMatchMaxLen + 1); + _dictionarySizePrev = _dictionarySize; + _numFastBytesPrev = _numFastBytes; + } + + public Encoder() + { + for (int i = 0; i < kNumOpts; i++) + _optimum[i] = new Optimal(); + for (int i = 0; i < Base.kNumLenToPosStates; i++) + _posSlotEncoder[i] = new RangeCoder.BitTreeEncoder(Base.kNumPosSlotBits); + } + + void SetWriteEndMarkerMode(bool writeEndMarker) + { + _writeEndMark = writeEndMarker; + } + + void Init() + { + BaseInit(); + _rangeEncoder.Init(); + + uint i; + for (i = 0; i < Base.kNumStates; i++) + { + for (uint j = 0; j <= _posStateMask; j++) + { + uint complexState = (i << Base.kNumPosStatesBitsMax) + j; + _isMatch[complexState].Init(); + _isRep0Long[complexState].Init(); + } + _isRep[i].Init(); + _isRepG0[i].Init(); + _isRepG1[i].Init(); + _isRepG2[i].Init(); + } + _literalEncoder.Init(); + for (i = 0; i < Base.kNumLenToPosStates; i++) + _posSlotEncoder[i].Init(); + for (i = 0; i < Base.kNumFullDistances - Base.kEndPosModelIndex; i++) + _posEncoders[i].Init(); + + _lenEncoder.Init((UInt32)1 << _posStateBits); + _repMatchLenEncoder.Init((UInt32)1 << _posStateBits); + + _posAlignEncoder.Init(); + + _longestMatchWasFound = false; + _optimumEndIndex = 0; + _optimumCurrentIndex = 0; + _additionalOffset = 0; + } + + void ReadMatchDistances(out UInt32 lenRes, out UInt32 numDistancePairs) + { + lenRes = 0; + numDistancePairs = _matchFinder.GetMatches(_matchDistances); + if (numDistancePairs > 0) + { + lenRes = _matchDistances[numDistancePairs - 2]; + if (lenRes == _numFastBytes) + lenRes += _matchFinder.GetMatchLen((int)lenRes - 1, _matchDistances[numDistancePairs - 1], + Base.kMatchMaxLen - lenRes); + } + _additionalOffset++; + } + + + void MovePos(UInt32 num) + { + if (num > 0) + { + _matchFinder.Skip(num); + _additionalOffset += num; + } + } + + UInt32 GetRepLen1Price(Base.State state, UInt32 posState) + { + return _isRepG0[state.Index].GetPrice0() + + _isRep0Long[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0(); + } + + UInt32 GetPureRepPrice(UInt32 repIndex, Base.State state, UInt32 posState) + { + UInt32 price; + if (repIndex == 0) + { + price = _isRepG0[state.Index].GetPrice0(); + price += _isRep0Long[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1(); + } + else + { + price = _isRepG0[state.Index].GetPrice1(); + if (repIndex == 1) + price += _isRepG1[state.Index].GetPrice0(); + else + { + price += _isRepG1[state.Index].GetPrice1(); + price += _isRepG2[state.Index].GetPrice(repIndex - 2); + } + } + return price; + } + + UInt32 GetRepPrice(UInt32 repIndex, UInt32 len, Base.State state, UInt32 posState) + { + UInt32 price = _repMatchLenEncoder.GetPrice(len - Base.kMatchMinLen, posState); + return price + GetPureRepPrice(repIndex, state, posState); + } + + UInt32 GetPosLenPrice(UInt32 pos, UInt32 len, UInt32 posState) + { + UInt32 price; + UInt32 lenToPosState = Base.GetLenToPosState(len); + if (pos < Base.kNumFullDistances) + price = _distancesPrices[(lenToPosState * Base.kNumFullDistances) + pos]; + else + price = _posSlotPrices[(lenToPosState << Base.kNumPosSlotBits) + GetPosSlot2(pos)] + + _alignPrices[pos & Base.kAlignMask]; + return price + _lenEncoder.GetPrice(len - Base.kMatchMinLen, posState); + } + + UInt32 Backward(out UInt32 backRes, UInt32 cur) + { + _optimumEndIndex = cur; + UInt32 posMem = _optimum[cur].PosPrev; + UInt32 backMem = _optimum[cur].BackPrev; + do + { + if (_optimum[cur].Prev1IsChar) + { + _optimum[posMem].MakeAsChar(); + _optimum[posMem].PosPrev = posMem - 1; + if (_optimum[cur].Prev2) + { + _optimum[posMem - 1].Prev1IsChar = false; + _optimum[posMem - 1].PosPrev = _optimum[cur].PosPrev2; + _optimum[posMem - 1].BackPrev = _optimum[cur].BackPrev2; + } + } + UInt32 posPrev = posMem; + UInt32 backCur = backMem; + + backMem = _optimum[posPrev].BackPrev; + posMem = _optimum[posPrev].PosPrev; + + _optimum[posPrev].BackPrev = backCur; + _optimum[posPrev].PosPrev = cur; + cur = posPrev; + } + while (cur > 0); + backRes = _optimum[0].BackPrev; + _optimumCurrentIndex = _optimum[0].PosPrev; + return _optimumCurrentIndex; + } + + UInt32[] reps = new UInt32[Base.kNumRepDistances]; + UInt32[] repLens = new UInt32[Base.kNumRepDistances]; + + + UInt32 GetOptimum(UInt32 position, out UInt32 backRes) + { + if (_optimumEndIndex != _optimumCurrentIndex) + { + UInt32 lenRes = _optimum[_optimumCurrentIndex].PosPrev - _optimumCurrentIndex; + backRes = _optimum[_optimumCurrentIndex].BackPrev; + _optimumCurrentIndex = _optimum[_optimumCurrentIndex].PosPrev; + return lenRes; + } + _optimumCurrentIndex = _optimumEndIndex = 0; + + UInt32 lenMain, numDistancePairs; + if (!_longestMatchWasFound) + { + ReadMatchDistances(out lenMain, out numDistancePairs); + } + else + { + lenMain = _longestMatchLength; + numDistancePairs = _numDistancePairs; + _longestMatchWasFound = false; + } + + UInt32 numAvailableBytes = _matchFinder.GetNumAvailableBytes() + 1; + if (numAvailableBytes < 2) + { + backRes = 0xFFFFFFFF; + return 1; + } + if (numAvailableBytes > Base.kMatchMaxLen) + numAvailableBytes = Base.kMatchMaxLen; + + UInt32 repMaxIndex = 0; + UInt32 i; + for (i = 0; i < Base.kNumRepDistances; i++) + { + reps[i] = _repDistances[i]; + repLens[i] = _matchFinder.GetMatchLen(0 - 1, reps[i], Base.kMatchMaxLen); + if (repLens[i] > repLens[repMaxIndex]) + repMaxIndex = i; + } + if (repLens[repMaxIndex] >= _numFastBytes) + { + backRes = repMaxIndex; + UInt32 lenRes = repLens[repMaxIndex]; + MovePos(lenRes - 1); + return lenRes; + } + + if (lenMain >= _numFastBytes) + { + backRes = _matchDistances[numDistancePairs - 1] + Base.kNumRepDistances; + MovePos(lenMain - 1); + return lenMain; + } + + Byte currentByte = _matchFinder.GetIndexByte(0 - 1); + Byte matchByte = _matchFinder.GetIndexByte((Int32)(0 - _repDistances[0] - 1 - 1)); + + if (lenMain < 2 && currentByte != matchByte && repLens[repMaxIndex] < 2) + { + backRes = (UInt32)0xFFFFFFFF; + return 1; + } + + _optimum[0].State = _state; + + UInt32 posState = (position & _posStateMask); + + _optimum[1].Price = _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0() + + _literalEncoder.GetSubCoder(position, _previousByte).GetPrice(!_state.IsCharState(), matchByte, currentByte); + _optimum[1].MakeAsChar(); + + UInt32 matchPrice = _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1(); + UInt32 repMatchPrice = matchPrice + _isRep[_state.Index].GetPrice1(); + + if (matchByte == currentByte) + { + UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(_state, posState); + if (shortRepPrice < _optimum[1].Price) + { + _optimum[1].Price = shortRepPrice; + _optimum[1].MakeAsShortRep(); + } + } + + UInt32 lenEnd = ((lenMain >= repLens[repMaxIndex]) ? lenMain : repLens[repMaxIndex]); + + if(lenEnd < 2) + { + backRes = _optimum[1].BackPrev; + return 1; + } + + _optimum[1].PosPrev = 0; + + _optimum[0].Backs0 = reps[0]; + _optimum[0].Backs1 = reps[1]; + _optimum[0].Backs2 = reps[2]; + _optimum[0].Backs3 = reps[3]; + + UInt32 len = lenEnd; + do + _optimum[len--].Price = kIfinityPrice; + while (len >= 2); + + for (i = 0; i < Base.kNumRepDistances; i++) + { + UInt32 repLen = repLens[i]; + if (repLen < 2) + continue; + UInt32 price = repMatchPrice + GetPureRepPrice(i, _state, posState); + do + { + UInt32 curAndLenPrice = price + _repMatchLenEncoder.GetPrice(repLen - 2, posState); + Optimal optimum = _optimum[repLen]; + if (curAndLenPrice < optimum.Price) + { + optimum.Price = curAndLenPrice; + optimum.PosPrev = 0; + optimum.BackPrev = i; + optimum.Prev1IsChar = false; + } + } + while (--repLen >= 2); + } + + UInt32 normalMatchPrice = matchPrice + _isRep[_state.Index].GetPrice0(); + + len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2); + if (len <= lenMain) + { + UInt32 offs = 0; + while (len > _matchDistances[offs]) + offs += 2; + for (; ; len++) + { + UInt32 distance = _matchDistances[offs + 1]; + UInt32 curAndLenPrice = normalMatchPrice + GetPosLenPrice(distance, len, posState); + Optimal optimum = _optimum[len]; + if (curAndLenPrice < optimum.Price) + { + optimum.Price = curAndLenPrice; + optimum.PosPrev = 0; + optimum.BackPrev = distance + Base.kNumRepDistances; + optimum.Prev1IsChar = false; + } + if (len == _matchDistances[offs]) + { + offs += 2; + if (offs == numDistancePairs) + break; + } + } + } + + UInt32 cur = 0; + + while (true) + { + cur++; + if (cur == lenEnd) + return Backward(out backRes, cur); + UInt32 newLen; + ReadMatchDistances(out newLen, out numDistancePairs); + if (newLen >= _numFastBytes) + { + _numDistancePairs = numDistancePairs; + _longestMatchLength = newLen; + _longestMatchWasFound = true; + return Backward(out backRes, cur); + } + position++; + UInt32 posPrev = _optimum[cur].PosPrev; + Base.State state; + if (_optimum[cur].Prev1IsChar) + { + posPrev--; + if (_optimum[cur].Prev2) + { + state = _optimum[_optimum[cur].PosPrev2].State; + if (_optimum[cur].BackPrev2 < Base.kNumRepDistances) + state.UpdateRep(); + else + state.UpdateMatch(); + } + else + state = _optimum[posPrev].State; + state.UpdateChar(); + } + else + state = _optimum[posPrev].State; + if (posPrev == cur - 1) + { + if (_optimum[cur].IsShortRep()) + state.UpdateShortRep(); + else + state.UpdateChar(); + } + else + { + UInt32 pos; + if (_optimum[cur].Prev1IsChar && _optimum[cur].Prev2) + { + posPrev = _optimum[cur].PosPrev2; + pos = _optimum[cur].BackPrev2; + state.UpdateRep(); + } + else + { + pos = _optimum[cur].BackPrev; + if (pos < Base.kNumRepDistances) + state.UpdateRep(); + else + state.UpdateMatch(); + } + Optimal opt = _optimum[posPrev]; + if (pos < Base.kNumRepDistances) + { + if (pos == 0) + { + reps[0] = opt.Backs0; + reps[1] = opt.Backs1; + reps[2] = opt.Backs2; + reps[3] = opt.Backs3; + } + else if (pos == 1) + { + reps[0] = opt.Backs1; + reps[1] = opt.Backs0; + reps[2] = opt.Backs2; + reps[3] = opt.Backs3; + } + else if (pos == 2) + { + reps[0] = opt.Backs2; + reps[1] = opt.Backs0; + reps[2] = opt.Backs1; + reps[3] = opt.Backs3; + } + else + { + reps[0] = opt.Backs3; + reps[1] = opt.Backs0; + reps[2] = opt.Backs1; + reps[3] = opt.Backs2; + } + } + else + { + reps[0] = (pos - Base.kNumRepDistances); + reps[1] = opt.Backs0; + reps[2] = opt.Backs1; + reps[3] = opt.Backs2; + } + } + _optimum[cur].State = state; + _optimum[cur].Backs0 = reps[0]; + _optimum[cur].Backs1 = reps[1]; + _optimum[cur].Backs2 = reps[2]; + _optimum[cur].Backs3 = reps[3]; + UInt32 curPrice = _optimum[cur].Price; + + currentByte = _matchFinder.GetIndexByte(0 - 1); + matchByte = _matchFinder.GetIndexByte((Int32)(0 - reps[0] - 1 - 1)); + + posState = (position & _posStateMask); + + UInt32 curAnd1Price = curPrice + + _isMatch[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0() + + _literalEncoder.GetSubCoder(position, _matchFinder.GetIndexByte(0 - 2)). + GetPrice(!state.IsCharState(), matchByte, currentByte); + + Optimal nextOptimum = _optimum[cur + 1]; + + bool nextIsChar = false; + if (curAnd1Price < nextOptimum.Price) + { + nextOptimum.Price = curAnd1Price; + nextOptimum.PosPrev = cur; + nextOptimum.MakeAsChar(); + nextIsChar = true; + } + + matchPrice = curPrice + _isMatch[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1(); + repMatchPrice = matchPrice + _isRep[state.Index].GetPrice1(); + + if (matchByte == currentByte && + !(nextOptimum.PosPrev < cur && nextOptimum.BackPrev == 0)) + { + UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(state, posState); + if (shortRepPrice <= nextOptimum.Price) + { + nextOptimum.Price = shortRepPrice; + nextOptimum.PosPrev = cur; + nextOptimum.MakeAsShortRep(); + nextIsChar = true; + } + } + + UInt32 numAvailableBytesFull = _matchFinder.GetNumAvailableBytes() + 1; + numAvailableBytesFull = Math.Min(kNumOpts - 1 - cur, numAvailableBytesFull); + numAvailableBytes = numAvailableBytesFull; + + if (numAvailableBytes < 2) + continue; + if (numAvailableBytes > _numFastBytes) + numAvailableBytes = _numFastBytes; + if (!nextIsChar && matchByte != currentByte) + { + // try Literal + rep0 + UInt32 t = Math.Min(numAvailableBytesFull - 1, _numFastBytes); + UInt32 lenTest2 = _matchFinder.GetMatchLen(0, reps[0], t); + if (lenTest2 >= 2) + { + Base.State state2 = state; + state2.UpdateChar(); + UInt32 posStateNext = (position + 1) & _posStateMask; + UInt32 nextRepMatchPrice = curAnd1Price + + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice1() + + _isRep[state2.Index].GetPrice1(); + { + UInt32 offset = cur + 1 + lenTest2; + while (lenEnd < offset) + _optimum[++lenEnd].Price = kIfinityPrice; + UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice( + 0, lenTest2, state2, posStateNext); + Optimal optimum = _optimum[offset]; + if (curAndLenPrice < optimum.Price) + { + optimum.Price = curAndLenPrice; + optimum.PosPrev = cur + 1; + optimum.BackPrev = 0; + optimum.Prev1IsChar = true; + optimum.Prev2 = false; + } + } + } + } + + UInt32 startLen = 2; // speed optimization + + for (UInt32 repIndex = 0; repIndex < Base.kNumRepDistances; repIndex++) + { + UInt32 lenTest = _matchFinder.GetMatchLen(0 - 1, reps[repIndex], numAvailableBytes); + if (lenTest < 2) + continue; + UInt32 lenTestTemp = lenTest; + do + { + while (lenEnd < cur + lenTest) + _optimum[++lenEnd].Price = kIfinityPrice; + UInt32 curAndLenPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState); + Optimal optimum = _optimum[cur + lenTest]; + if (curAndLenPrice < optimum.Price) + { + optimum.Price = curAndLenPrice; + optimum.PosPrev = cur; + optimum.BackPrev = repIndex; + optimum.Prev1IsChar = false; + } + } + while(--lenTest >= 2); + lenTest = lenTestTemp; + + if (repIndex == 0) + startLen = lenTest + 1; + + // if (_maxMode) + if (lenTest < numAvailableBytesFull) + { + UInt32 t = Math.Min(numAvailableBytesFull - 1 - lenTest, _numFastBytes); + UInt32 lenTest2 = _matchFinder.GetMatchLen((Int32)lenTest, reps[repIndex], t); + if (lenTest2 >= 2) + { + Base.State state2 = state; + state2.UpdateRep(); + UInt32 posStateNext = (position + lenTest) & _posStateMask; + UInt32 curAndLenCharPrice = + repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState) + + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice0() + + _literalEncoder.GetSubCoder(position + lenTest, + _matchFinder.GetIndexByte((Int32)lenTest - 1 - 1)).GetPrice(true, + _matchFinder.GetIndexByte((Int32)((Int32)lenTest - 1 - (Int32)(reps[repIndex] + 1))), + _matchFinder.GetIndexByte((Int32)lenTest - 1)); + state2.UpdateChar(); + posStateNext = (position + lenTest + 1) & _posStateMask; + UInt32 nextMatchPrice = curAndLenCharPrice + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice1(); + UInt32 nextRepMatchPrice = nextMatchPrice + _isRep[state2.Index].GetPrice1(); + + // for(; lenTest2 >= 2; lenTest2--) + { + UInt32 offset = lenTest + 1 + lenTest2; + while(lenEnd < cur + offset) + _optimum[++lenEnd].Price = kIfinityPrice; + UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext); + Optimal optimum = _optimum[cur + offset]; + if (curAndLenPrice < optimum.Price) + { + optimum.Price = curAndLenPrice; + optimum.PosPrev = cur + lenTest + 1; + optimum.BackPrev = 0; + optimum.Prev1IsChar = true; + optimum.Prev2 = true; + optimum.PosPrev2 = cur; + optimum.BackPrev2 = repIndex; + } + } + } + } + } + + if (newLen > numAvailableBytes) + { + newLen = numAvailableBytes; + for (numDistancePairs = 0; newLen > _matchDistances[numDistancePairs]; numDistancePairs += 2) ; + _matchDistances[numDistancePairs] = newLen; + numDistancePairs += 2; + } + if (newLen >= startLen) + { + normalMatchPrice = matchPrice + _isRep[state.Index].GetPrice0(); + while (lenEnd < cur + newLen) + _optimum[++lenEnd].Price = kIfinityPrice; + + UInt32 offs = 0; + while (startLen > _matchDistances[offs]) + offs += 2; + + for (UInt32 lenTest = startLen; ; lenTest++) + { + UInt32 curBack = _matchDistances[offs + 1]; + UInt32 curAndLenPrice = normalMatchPrice + GetPosLenPrice(curBack, lenTest, posState); + Optimal optimum = _optimum[cur + lenTest]; + if (curAndLenPrice < optimum.Price) + { + optimum.Price = curAndLenPrice; + optimum.PosPrev = cur; + optimum.BackPrev = curBack + Base.kNumRepDistances; + optimum.Prev1IsChar = false; + } + + if (lenTest == _matchDistances[offs]) + { + if (lenTest < numAvailableBytesFull) + { + UInt32 t = Math.Min(numAvailableBytesFull - 1 - lenTest, _numFastBytes); + UInt32 lenTest2 = _matchFinder.GetMatchLen((Int32)lenTest, curBack, t); + if (lenTest2 >= 2) + { + Base.State state2 = state; + state2.UpdateMatch(); + UInt32 posStateNext = (position + lenTest) & _posStateMask; + UInt32 curAndLenCharPrice = curAndLenPrice + + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice0() + + _literalEncoder.GetSubCoder(position + lenTest, + _matchFinder.GetIndexByte((Int32)lenTest - 1 - 1)). + GetPrice(true, + _matchFinder.GetIndexByte((Int32)lenTest - (Int32)(curBack + 1) - 1), + _matchFinder.GetIndexByte((Int32)lenTest - 1)); + state2.UpdateChar(); + posStateNext = (position + lenTest + 1) & _posStateMask; + UInt32 nextMatchPrice = curAndLenCharPrice + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice1(); + UInt32 nextRepMatchPrice = nextMatchPrice + _isRep[state2.Index].GetPrice1(); + + UInt32 offset = lenTest + 1 + lenTest2; + while (lenEnd < cur + offset) + _optimum[++lenEnd].Price = kIfinityPrice; + curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext); + optimum = _optimum[cur + offset]; + if (curAndLenPrice < optimum.Price) + { + optimum.Price = curAndLenPrice; + optimum.PosPrev = cur + lenTest + 1; + optimum.BackPrev = 0; + optimum.Prev1IsChar = true; + optimum.Prev2 = true; + optimum.PosPrev2 = cur; + optimum.BackPrev2 = curBack + Base.kNumRepDistances; + } + } + } + offs += 2; + if (offs == numDistancePairs) + break; + } + } + } + } + } + + bool ChangePair(UInt32 smallDist, UInt32 bigDist) + { + const int kDif = 7; + return (smallDist < ((UInt32)(1) << (32 - kDif)) && bigDist >= (smallDist << kDif)); + } + + void WriteEndMarker(UInt32 posState) + { + if (!_writeEndMark) + return; + + _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].Encode(_rangeEncoder, 1); + _isRep[_state.Index].Encode(_rangeEncoder, 0); + _state.UpdateMatch(); + UInt32 len = Base.kMatchMinLen; + _lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); + UInt32 posSlot = (1 << Base.kNumPosSlotBits) - 1; + UInt32 lenToPosState = Base.GetLenToPosState(len); + _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot); + int footerBits = 30; + UInt32 posReduced = (((UInt32)1) << footerBits) - 1; + _rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits); + _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask); + } + + void Flush(UInt32 nowPos) + { + ReleaseMFStream(); + WriteEndMarker(nowPos & _posStateMask); + _rangeEncoder.FlushData(); + _rangeEncoder.FlushStream(); + } + + public void CodeOneBlock(out Int64 inSize, out Int64 outSize, out bool finished) + { + inSize = 0; + outSize = 0; + finished = true; + + if (_inStream != null) + { + _matchFinder.SetStream(_inStream); + _matchFinder.Init(); + _needReleaseMFStream = true; + _inStream = null; + if (_trainSize > 0) + _matchFinder.Skip(_trainSize); + } + + if (_finished) + return; + _finished = true; + + + Int64 progressPosValuePrev = nowPos64; + if (nowPos64 == 0) + { + if (_matchFinder.GetNumAvailableBytes() == 0) + { + Flush((UInt32)nowPos64); + return; + } + UInt32 len, numDistancePairs; // it's not used + ReadMatchDistances(out len, out numDistancePairs); + UInt32 posState = (UInt32)(nowPos64) & _posStateMask; + _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].Encode(_rangeEncoder, 0); + _state.UpdateChar(); + Byte curByte = _matchFinder.GetIndexByte((Int32)(0 - _additionalOffset)); + _literalEncoder.GetSubCoder((UInt32)(nowPos64), _previousByte).Encode(_rangeEncoder, curByte); + _previousByte = curByte; + _additionalOffset--; + nowPos64++; + } + if (_matchFinder.GetNumAvailableBytes() == 0) + { + Flush((UInt32)nowPos64); + return; + } + while (true) + { + UInt32 pos; + UInt32 len = GetOptimum((UInt32)nowPos64, out pos); + + UInt32 posState = ((UInt32)nowPos64) & _posStateMask; + UInt32 complexState = (_state.Index << Base.kNumPosStatesBitsMax) + posState; + if (len == 1 && pos == 0xFFFFFFFF) + { + _isMatch[complexState].Encode(_rangeEncoder, 0); + Byte curByte = _matchFinder.GetIndexByte((Int32)(0 - _additionalOffset)); + LiteralEncoder.Encoder2 subCoder = _literalEncoder.GetSubCoder((UInt32)nowPos64, _previousByte); + if (!_state.IsCharState()) + { + Byte matchByte = _matchFinder.GetIndexByte((Int32)(0 - _repDistances[0] - 1 - _additionalOffset)); + subCoder.EncodeMatched(_rangeEncoder, matchByte, curByte); + } + else + subCoder.Encode(_rangeEncoder, curByte); + _previousByte = curByte; + _state.UpdateChar(); + } + else + { + _isMatch[complexState].Encode(_rangeEncoder, 1); + if (pos < Base.kNumRepDistances) + { + _isRep[_state.Index].Encode(_rangeEncoder, 1); + if (pos == 0) + { + _isRepG0[_state.Index].Encode(_rangeEncoder, 0); + if (len == 1) + _isRep0Long[complexState].Encode(_rangeEncoder, 0); + else + _isRep0Long[complexState].Encode(_rangeEncoder, 1); + } + else + { + _isRepG0[_state.Index].Encode(_rangeEncoder, 1); + if (pos == 1) + _isRepG1[_state.Index].Encode(_rangeEncoder, 0); + else + { + _isRepG1[_state.Index].Encode(_rangeEncoder, 1); + _isRepG2[_state.Index].Encode(_rangeEncoder, pos - 2); + } + } + if (len == 1) + _state.UpdateShortRep(); + else + { + _repMatchLenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); + _state.UpdateRep(); + } + UInt32 distance = _repDistances[pos]; + if (pos != 0) + { + for (UInt32 i = pos; i >= 1; i--) + _repDistances[i] = _repDistances[i - 1]; + _repDistances[0] = distance; + } + } + else + { + _isRep[_state.Index].Encode(_rangeEncoder, 0); + _state.UpdateMatch(); + _lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); + pos -= Base.kNumRepDistances; + UInt32 posSlot = GetPosSlot(pos); + UInt32 lenToPosState = Base.GetLenToPosState(len); + _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot); + + if (posSlot >= Base.kStartPosModelIndex) + { + int footerBits = (int)((posSlot >> 1) - 1); + UInt32 baseVal = ((2 | (posSlot & 1)) << footerBits); + UInt32 posReduced = pos - baseVal; + + if (posSlot < Base.kEndPosModelIndex) + RangeCoder.BitTreeEncoder.ReverseEncode(_posEncoders, + baseVal - posSlot - 1, _rangeEncoder, footerBits, posReduced); + else + { + _rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits); + _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask); + _alignPriceCount++; + } + } + UInt32 distance = pos; + for (UInt32 i = Base.kNumRepDistances - 1; i >= 1; i--) + _repDistances[i] = _repDistances[i - 1]; + _repDistances[0] = distance; + _matchPriceCount++; + } + _previousByte = _matchFinder.GetIndexByte((Int32)(len - 1 - _additionalOffset)); + } + _additionalOffset -= len; + nowPos64 += len; + if (_additionalOffset == 0) + { + // if (!_fastMode) + if (_matchPriceCount >= (1 << 7)) + FillDistancesPrices(); + if (_alignPriceCount >= Base.kAlignTableSize) + FillAlignPrices(); + inSize = nowPos64; + outSize = _rangeEncoder.GetProcessedSizeAdd(); + if (_matchFinder.GetNumAvailableBytes() == 0) + { + Flush((UInt32)nowPos64); + return; + } + + if (nowPos64 - progressPosValuePrev >= (1 << 12)) + { + _finished = false; + finished = false; + return; + } + } + } + } + + void ReleaseMFStream() + { + if (_matchFinder != null && _needReleaseMFStream) + { + _matchFinder.ReleaseStream(); + _needReleaseMFStream = false; + } + } + + void SetOutStream(System.IO.Stream outStream) { _rangeEncoder.SetStream(outStream); } + void ReleaseOutStream() { _rangeEncoder.ReleaseStream(); } + + void ReleaseStreams() + { + ReleaseMFStream(); + ReleaseOutStream(); + } + + void SetStreams(System.IO.Stream inStream, System.IO.Stream outStream, + Int64 inSize, Int64 outSize) + { + _inStream = inStream; + _finished = false; + Create(); + SetOutStream(outStream); + Init(); + + // if (!_fastMode) + { + FillDistancesPrices(); + FillAlignPrices(); + } + + _lenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen); + _lenEncoder.UpdateTables((UInt32)1 << _posStateBits); + _repMatchLenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen); + _repMatchLenEncoder.UpdateTables((UInt32)1 << _posStateBits); + + nowPos64 = 0; + } + + + public void Code(System.IO.Stream inStream, System.IO.Stream outStream, + Int64 inSize, Int64 outSize, ICodeProgress progress) + { + _needReleaseMFStream = false; + try + { + SetStreams(inStream, outStream, inSize, outSize); + while (true) + { + Int64 processedInSize; + Int64 processedOutSize; + bool finished; + CodeOneBlock(out processedInSize, out processedOutSize, out finished); + if (finished) + return; + if (progress != null) + { + progress.SetProgress(processedInSize, processedOutSize); + } + } + } + finally + { + ReleaseStreams(); + } + } + + const int kPropSize = 5; + Byte[] properties = new Byte[kPropSize]; + + public void WriteCoderProperties(System.IO.Stream outStream) + { + properties[0] = (Byte)((_posStateBits * 5 + _numLiteralPosStateBits) * 9 + _numLiteralContextBits); + for (int i = 0; i < 4; i++) + properties[1 + i] = (Byte)((_dictionarySize >> (8 * i)) & 0xFF); + outStream.Write(properties, 0, kPropSize); + } + + UInt32[] tempPrices = new UInt32[Base.kNumFullDistances]; + UInt32 _matchPriceCount; + + void FillDistancesPrices() + { + for (UInt32 i = Base.kStartPosModelIndex; i < Base.kNumFullDistances; i++) + { + UInt32 posSlot = GetPosSlot(i); + int footerBits = (int)((posSlot >> 1) - 1); + UInt32 baseVal = ((2 | (posSlot & 1)) << footerBits); + tempPrices[i] = BitTreeEncoder.ReverseGetPrice(_posEncoders, + baseVal - posSlot - 1, footerBits, i - baseVal); + } + + for (UInt32 lenToPosState = 0; lenToPosState < Base.kNumLenToPosStates; lenToPosState++) + { + UInt32 posSlot; + RangeCoder.BitTreeEncoder encoder = _posSlotEncoder[lenToPosState]; + + UInt32 st = (lenToPosState << Base.kNumPosSlotBits); + for (posSlot = 0; posSlot < _distTableSize; posSlot++) + _posSlotPrices[st + posSlot] = encoder.GetPrice(posSlot); + for (posSlot = Base.kEndPosModelIndex; posSlot < _distTableSize; posSlot++) + _posSlotPrices[st + posSlot] += ((((posSlot >> 1) - 1) - Base.kNumAlignBits) << RangeCoder.BitEncoder.kNumBitPriceShiftBits); + + UInt32 st2 = lenToPosState * Base.kNumFullDistances; + UInt32 i; + for (i = 0; i < Base.kStartPosModelIndex; i++) + _distancesPrices[st2 + i] = _posSlotPrices[st + i]; + for (; i < Base.kNumFullDistances; i++) + _distancesPrices[st2 + i] = _posSlotPrices[st + GetPosSlot(i)] + tempPrices[i]; + } + _matchPriceCount = 0; + } + + void FillAlignPrices() + { + for (UInt32 i = 0; i < Base.kAlignTableSize; i++) + _alignPrices[i] = _posAlignEncoder.ReverseGetPrice(i); + _alignPriceCount = 0; + } + + + static string[] kMatchFinderIDs = + { + "BT2", + "BT4", + }; + + static int FindMatchFinder(string s) + { + for (int m = 0; m < kMatchFinderIDs.Length; m++) + if (s == kMatchFinderIDs[m]) + return m; + return -1; + } + + public void SetCoderProperties(CoderPropID[] propIDs, object[] properties) + { + for (UInt32 i = 0; i < properties.Length; i++) + { + object prop = properties[i]; + switch (propIDs[i]) + { + case CoderPropID.NumFastBytes: + { + if (!(prop is Int32)) + throw new InvalidParamException(); + Int32 numFastBytes = (Int32)prop; + if (numFastBytes < 5 || numFastBytes > Base.kMatchMaxLen) + throw new InvalidParamException(); + _numFastBytes = (UInt32)numFastBytes; + break; + } + case CoderPropID.Algorithm: + { + /* + if (!(prop is Int32)) + throw new InvalidParamException(); + Int32 maximize = (Int32)prop; + _fastMode = (maximize == 0); + _maxMode = (maximize >= 2); + */ + break; + } + case CoderPropID.MatchFinder: + { + if (!(prop is String)) + throw new InvalidParamException(); + EMatchFinderType matchFinderIndexPrev = _matchFinderType; + int m = FindMatchFinder(((string)prop).ToUpper()); + if (m < 0) + throw new InvalidParamException(); + _matchFinderType = (EMatchFinderType)m; + if (_matchFinder != null && matchFinderIndexPrev != _matchFinderType) + { + _dictionarySizePrev = 0xFFFFFFFF; + _matchFinder = null; + } + break; + } + case CoderPropID.DictionarySize: + { + const int kDicLogSizeMaxCompress = 30; + if (!(prop is Int32)) + throw new InvalidParamException(); ; + Int32 dictionarySize = (Int32)prop; + if (dictionarySize < (UInt32)(1 << Base.kDicLogSizeMin) || + dictionarySize > (UInt32)(1 << kDicLogSizeMaxCompress)) + throw new InvalidParamException(); + _dictionarySize = (UInt32)dictionarySize; + int dicLogSize; + for (dicLogSize = 0; dicLogSize < (UInt32)kDicLogSizeMaxCompress; dicLogSize++) + if (dictionarySize <= ((UInt32)(1) << dicLogSize)) + break; + _distTableSize = (UInt32)dicLogSize * 2; + break; + } + case CoderPropID.PosStateBits: + { + if (!(prop is Int32)) + throw new InvalidParamException(); + Int32 v = (Int32)prop; + if (v < 0 || v > (UInt32)Base.kNumPosStatesBitsEncodingMax) + throw new InvalidParamException(); + _posStateBits = (int)v; + _posStateMask = (((UInt32)1) << (int)_posStateBits) - 1; + break; + } + case CoderPropID.LitPosBits: + { + if (!(prop is Int32)) + throw new InvalidParamException(); + Int32 v = (Int32)prop; + if (v < 0 || v > (UInt32)Base.kNumLitPosStatesBitsEncodingMax) + throw new InvalidParamException(); + _numLiteralPosStateBits = (int)v; + break; + } + case CoderPropID.LitContextBits: + { + if (!(prop is Int32)) + throw new InvalidParamException(); + Int32 v = (Int32)prop; + if (v < 0 || v > (UInt32)Base.kNumLitContextBitsMax) + throw new InvalidParamException(); ; + _numLiteralContextBits = (int)v; + break; + } + case CoderPropID.EndMarker: + { + if (!(prop is Boolean)) + throw new InvalidParamException(); + SetWriteEndMarkerMode((Boolean)prop); + break; + } + default: + throw new InvalidParamException(); + } + } + } + + uint _trainSize = 0; + public void SetTrainSize(uint trainSize) + { + _trainSize = trainSize; + } + + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/LZMA/LzmaEncoder.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/LZMA/LzmaEncoder.cs.meta new file mode 100644 index 0000000..fedcb56 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/LZMA/LzmaEncoder.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 37dcefc9d952dc34f9fba085a160a968 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/RangeCoder.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/RangeCoder.meta new file mode 100644 index 0000000..cf24bb3 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/RangeCoder.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 73c80167cede90a4a8fc4938bab053c8 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/RangeCoder/RangeCoder.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/RangeCoder/RangeCoder.cs new file mode 100644 index 0000000..949c6bb --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/RangeCoder/RangeCoder.cs @@ -0,0 +1,234 @@ +using System; + +namespace SevenZip.Compression.RangeCoder +{ + class Encoder + { + public const uint kTopValue = (1 << 24); + + System.IO.Stream Stream; + + public UInt64 Low; + public uint Range; + uint _cacheSize; + byte _cache; + + long StartPosition; + + public void SetStream(System.IO.Stream stream) + { + Stream = stream; + } + + public void ReleaseStream() + { + Stream = null; + } + + public void Init() + { + StartPosition = Stream.Position; + + Low = 0; + Range = 0xFFFFFFFF; + _cacheSize = 1; + _cache = 0; + } + + public void FlushData() + { + for (int i = 0; i < 5; i++) + ShiftLow(); + } + + public void FlushStream() + { + Stream.Flush(); + } + + public void CloseStream() + { + Stream.Close(); + } + + public void Encode(uint start, uint size, uint total) + { + Low += start * (Range /= total); + Range *= size; + while (Range < kTopValue) + { + Range <<= 8; + ShiftLow(); + } + } + + public void ShiftLow() + { + if ((uint)Low < (uint)0xFF000000 || (uint)(Low >> 32) == 1) + { + byte temp = _cache; + do + { + Stream.WriteByte((byte)(temp + (Low >> 32))); + temp = 0xFF; + } + while (--_cacheSize != 0); + _cache = (byte)(((uint)Low) >> 24); + } + _cacheSize++; + Low = ((uint)Low) << 8; + } + + public void EncodeDirectBits(uint v, int numTotalBits) + { + for (int i = numTotalBits - 1; i >= 0; i--) + { + Range >>= 1; + if (((v >> i) & 1) == 1) + Low += Range; + if (Range < kTopValue) + { + Range <<= 8; + ShiftLow(); + } + } + } + + public void EncodeBit(uint size0, int numTotalBits, uint symbol) + { + uint newBound = (Range >> numTotalBits) * size0; + if (symbol == 0) + Range = newBound; + else + { + Low += newBound; + Range -= newBound; + } + while (Range < kTopValue) + { + Range <<= 8; + ShiftLow(); + } + } + + public long GetProcessedSizeAdd() + { + return _cacheSize + + Stream.Position - StartPosition + 4; + // (long)Stream.GetProcessedSize(); + } + } + + class Decoder + { + public const uint kTopValue = (1 << 24); + public uint Range; + public uint Code; + // public Buffer.InBuffer Stream = new Buffer.InBuffer(1 << 16); + public System.IO.Stream Stream; + + public void Init(System.IO.Stream stream) + { + // Stream.Init(stream); + Stream = stream; + + Code = 0; + Range = 0xFFFFFFFF; + for (int i = 0; i < 5; i++) + Code = (Code << 8) | (byte)Stream.ReadByte(); + } + + public void ReleaseStream() + { + // Stream.ReleaseStream(); + Stream = null; + } + + public void CloseStream() + { + Stream.Close(); + } + + public void Normalize() + { + while (Range < kTopValue) + { + Code = (Code << 8) | (byte)Stream.ReadByte(); + Range <<= 8; + } + } + + public void Normalize2() + { + if (Range < kTopValue) + { + Code = (Code << 8) | (byte)Stream.ReadByte(); + Range <<= 8; + } + } + + public uint GetThreshold(uint total) + { + return Code / (Range /= total); + } + + public void Decode(uint start, uint size, uint total) + { + Code -= start * Range; + Range *= size; + Normalize(); + } + + public uint DecodeDirectBits(int numTotalBits) + { + uint range = Range; + uint code = Code; + uint result = 0; + for (int i = numTotalBits; i > 0; i--) + { + range >>= 1; + /* + result <<= 1; + if (code >= range) + { + code -= range; + result |= 1; + } + */ + uint t = (code - range) >> 31; + code -= range & (t - 1); + result = (result << 1) | (1 - t); + + if (range < kTopValue) + { + code = (code << 8) | (byte)Stream.ReadByte(); + range <<= 8; + } + } + Range = range; + Code = code; + return result; + } + + public uint DecodeBit(uint size0, int numTotalBits) + { + uint newBound = (Range >> numTotalBits) * size0; + uint symbol; + if (Code < newBound) + { + symbol = 0; + Range = newBound; + } + else + { + symbol = 1; + Code -= newBound; + Range -= newBound; + } + Normalize(); + return symbol; + } + + // ulong GetProcessedSize() {return Stream.GetProcessedSize(); } + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/RangeCoder/RangeCoder.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/RangeCoder/RangeCoder.cs.meta new file mode 100644 index 0000000..fdbc75b --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/RangeCoder/RangeCoder.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a855cbfe314340a43b3d71672dcbb058 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/RangeCoder/RangeCoderBit.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/RangeCoder/RangeCoderBit.cs new file mode 100644 index 0000000..4f0346d --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/RangeCoder/RangeCoderBit.cs @@ -0,0 +1,117 @@ +using System; + +namespace SevenZip.Compression.RangeCoder +{ + struct BitEncoder + { + public const int kNumBitModelTotalBits = 11; + public const uint kBitModelTotal = (1 << kNumBitModelTotalBits); + const int kNumMoveBits = 5; + const int kNumMoveReducingBits = 2; + public const int kNumBitPriceShiftBits = 6; + + uint Prob; + + public void Init() { Prob = kBitModelTotal >> 1; } + + public void UpdateModel(uint symbol) + { + if (symbol == 0) + Prob += (kBitModelTotal - Prob) >> kNumMoveBits; + else + Prob -= (Prob) >> kNumMoveBits; + } + + public void Encode(Encoder encoder, uint symbol) + { + // encoder.EncodeBit(Prob, kNumBitModelTotalBits, symbol); + // UpdateModel(symbol); + uint newBound = (encoder.Range >> kNumBitModelTotalBits) * Prob; + if (symbol == 0) + { + encoder.Range = newBound; + Prob += (kBitModelTotal - Prob) >> kNumMoveBits; + } + else + { + encoder.Low += newBound; + encoder.Range -= newBound; + Prob -= (Prob) >> kNumMoveBits; + } + if (encoder.Range < Encoder.kTopValue) + { + encoder.Range <<= 8; + encoder.ShiftLow(); + } + } + + private static UInt32[] ProbPrices = new UInt32[kBitModelTotal >> kNumMoveReducingBits]; + + static BitEncoder() + { + const int kNumBits = (kNumBitModelTotalBits - kNumMoveReducingBits); + for (int i = kNumBits - 1; i >= 0; i--) + { + UInt32 start = (UInt32)1 << (kNumBits - i - 1); + UInt32 end = (UInt32)1 << (kNumBits - i); + for (UInt32 j = start; j < end; j++) + ProbPrices[j] = ((UInt32)i << kNumBitPriceShiftBits) + + (((end - j) << kNumBitPriceShiftBits) >> (kNumBits - i - 1)); + } + } + + public uint GetPrice(uint symbol) + { + return ProbPrices[(((Prob - symbol) ^ ((-(int)symbol))) & (kBitModelTotal - 1)) >> kNumMoveReducingBits]; + } + public uint GetPrice0() { return ProbPrices[Prob >> kNumMoveReducingBits]; } + public uint GetPrice1() { return ProbPrices[(kBitModelTotal - Prob) >> kNumMoveReducingBits]; } + } + + struct BitDecoder + { + public const int kNumBitModelTotalBits = 11; + public const uint kBitModelTotal = (1 << kNumBitModelTotalBits); + const int kNumMoveBits = 5; + + uint Prob; + + public void UpdateModel(int numMoveBits, uint symbol) + { + if (symbol == 0) + Prob += (kBitModelTotal - Prob) >> numMoveBits; + else + Prob -= (Prob) >> numMoveBits; + } + + public void Init() { Prob = kBitModelTotal >> 1; } + + public uint Decode(RangeCoder.Decoder rangeDecoder) + { + uint newBound = (uint)(rangeDecoder.Range >> kNumBitModelTotalBits) * (uint)Prob; + if (rangeDecoder.Code < newBound) + { + rangeDecoder.Range = newBound; + Prob += (kBitModelTotal - Prob) >> kNumMoveBits; + if (rangeDecoder.Range < Decoder.kTopValue) + { + rangeDecoder.Code = (rangeDecoder.Code << 8) | (byte)rangeDecoder.Stream.ReadByte(); + rangeDecoder.Range <<= 8; + } + return 0; + } + else + { + rangeDecoder.Range -= newBound; + rangeDecoder.Code -= newBound; + Prob -= (Prob) >> kNumMoveBits; + if (rangeDecoder.Range < Decoder.kTopValue) + { + rangeDecoder.Code = (rangeDecoder.Code << 8) | (byte)rangeDecoder.Stream.ReadByte(); + rangeDecoder.Range <<= 8; + } + return 1; + } + } + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/RangeCoder/RangeCoderBit.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/RangeCoder/RangeCoderBit.cs.meta new file mode 100644 index 0000000..2a0f148 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/RangeCoder/RangeCoderBit.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f3fd3305ff6e02448a7b0470cfe65b77 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/RangeCoder/RangeCoderBitTree.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/RangeCoder/RangeCoderBitTree.cs new file mode 100644 index 0000000..4b4506f --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/RangeCoder/RangeCoderBitTree.cs @@ -0,0 +1,157 @@ +using System; + +namespace SevenZip.Compression.RangeCoder +{ + struct BitTreeEncoder + { + BitEncoder[] Models; + int NumBitLevels; + + public BitTreeEncoder(int numBitLevels) + { + NumBitLevels = numBitLevels; + Models = new BitEncoder[1 << numBitLevels]; + } + + public void Init() + { + for (uint i = 1; i < (1 << NumBitLevels); i++) + Models[i].Init(); + } + + public void Encode(Encoder rangeEncoder, UInt32 symbol) + { + UInt32 m = 1; + for (int bitIndex = NumBitLevels; bitIndex > 0; ) + { + bitIndex--; + UInt32 bit = (symbol >> bitIndex) & 1; + Models[m].Encode(rangeEncoder, bit); + m = (m << 1) | bit; + } + } + + public void ReverseEncode(Encoder rangeEncoder, UInt32 symbol) + { + UInt32 m = 1; + for (UInt32 i = 0; i < NumBitLevels; i++) + { + UInt32 bit = symbol & 1; + Models[m].Encode(rangeEncoder, bit); + m = (m << 1) | bit; + symbol >>= 1; + } + } + + public UInt32 GetPrice(UInt32 symbol) + { + UInt32 price = 0; + UInt32 m = 1; + for (int bitIndex = NumBitLevels; bitIndex > 0; ) + { + bitIndex--; + UInt32 bit = (symbol >> bitIndex) & 1; + price += Models[m].GetPrice(bit); + m = (m << 1) + bit; + } + return price; + } + + public UInt32 ReverseGetPrice(UInt32 symbol) + { + UInt32 price = 0; + UInt32 m = 1; + for (int i = NumBitLevels; i > 0; i--) + { + UInt32 bit = symbol & 1; + symbol >>= 1; + price += Models[m].GetPrice(bit); + m = (m << 1) | bit; + } + return price; + } + + public static UInt32 ReverseGetPrice(BitEncoder[] Models, UInt32 startIndex, + int NumBitLevels, UInt32 symbol) + { + UInt32 price = 0; + UInt32 m = 1; + for (int i = NumBitLevels; i > 0; i--) + { + UInt32 bit = symbol & 1; + symbol >>= 1; + price += Models[startIndex + m].GetPrice(bit); + m = (m << 1) | bit; + } + return price; + } + + public static void ReverseEncode(BitEncoder[] Models, UInt32 startIndex, + Encoder rangeEncoder, int NumBitLevels, UInt32 symbol) + { + UInt32 m = 1; + for (int i = 0; i < NumBitLevels; i++) + { + UInt32 bit = symbol & 1; + Models[startIndex + m].Encode(rangeEncoder, bit); + m = (m << 1) | bit; + symbol >>= 1; + } + } + } + + struct BitTreeDecoder + { + BitDecoder[] Models; + int NumBitLevels; + + public BitTreeDecoder(int numBitLevels) + { + NumBitLevels = numBitLevels; + Models = new BitDecoder[1 << numBitLevels]; + } + + public void Init() + { + for (uint i = 1; i < (1 << NumBitLevels); i++) + Models[i].Init(); + } + + public uint Decode(RangeCoder.Decoder rangeDecoder) + { + uint m = 1; + for (int bitIndex = NumBitLevels; bitIndex > 0; bitIndex--) + m = (m << 1) + Models[m].Decode(rangeDecoder); + return m - ((uint)1 << NumBitLevels); + } + + public uint ReverseDecode(RangeCoder.Decoder rangeDecoder) + { + uint m = 1; + uint symbol = 0; + for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) + { + uint bit = Models[m].Decode(rangeDecoder); + m <<= 1; + m += bit; + symbol |= (bit << bitIndex); + } + return symbol; + } + + public static uint ReverseDecode(BitDecoder[] Models, UInt32 startIndex, + RangeCoder.Decoder rangeDecoder, int NumBitLevels) + { + uint m = 1; + uint symbol = 0; + for (int bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) + { + uint bit = Models[startIndex + m].Decode(rangeDecoder); + m <<= 1; + m += bit; + symbol |= (bit << bitIndex); + } + return symbol; + } + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/RangeCoder/RangeCoderBitTree.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/RangeCoder/RangeCoderBitTree.cs.meta new file mode 100644 index 0000000..df4ba12 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/Compress/RangeCoder/RangeCoderBitTree.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ef79f786b772db344a4792a5cba382ff +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/ICoder.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/ICoder.cs new file mode 100644 index 0000000..c8b95c8 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/ICoder.cs @@ -0,0 +1,157 @@ +// ICoder.h + +using System; + +namespace SevenZip +{ + /// <summary> + /// The exception that is thrown when an error in input stream occurs during decoding. + /// </summary> + class DataErrorException : ApplicationException + { + public DataErrorException(): base("Data Error") { } + } + + /// <summary> + /// The exception that is thrown when the value of an argument is outside the allowable range. + /// </summary> + class InvalidParamException : ApplicationException + { + public InvalidParamException(): base("Invalid Parameter") { } + } + + public interface ICodeProgress + { + /// <summary> + /// Callback progress. + /// </summary> + /// <param name="inSize"> + /// input size. -1 if unknown. + /// </param> + /// <param name="outSize"> + /// output size. -1 if unknown. + /// </param> + void SetProgress(Int64 inSize, Int64 outSize); + }; + + public interface ICoder + { + /// <summary> + /// Codes streams. + /// </summary> + /// <param name="inStream"> + /// input Stream. + /// </param> + /// <param name="outStream"> + /// output Stream. + /// </param> + /// <param name="inSize"> + /// input Size. -1 if unknown. + /// </param> + /// <param name="outSize"> + /// output Size. -1 if unknown. + /// </param> + /// <param name="progress"> + /// callback progress reference. + /// </param> + /// <exception cref="SevenZip.DataErrorException"> + /// if input stream is not valid + /// </exception> + void Code(System.IO.Stream inStream, System.IO.Stream outStream, + Int64 inSize, Int64 outSize, ICodeProgress progress); + }; + + /* + public interface ICoder2 + { + void Code(ISequentialInStream []inStreams, + const UInt64 []inSizes, + ISequentialOutStream []outStreams, + UInt64 []outSizes, + ICodeProgress progress); + }; + */ + + /// <summary> + /// Provides the fields that represent properties idenitifiers for compressing. + /// </summary> + public enum CoderPropID + { + /// <summary> + /// Specifies default property. + /// </summary> + DefaultProp = 0, + /// <summary> + /// Specifies size of dictionary. + /// </summary> + DictionarySize, + /// <summary> + /// Specifies size of memory for PPM*. + /// </summary> + UsedMemorySize, + /// <summary> + /// Specifies order for PPM methods. + /// </summary> + Order, + /// <summary> + /// Specifies Block Size. + /// </summary> + BlockSize, + /// <summary> + /// Specifies number of postion state bits for LZMA (0 <= x <= 4). + /// </summary> + PosStateBits, + /// <summary> + /// Specifies number of literal context bits for LZMA (0 <= x <= 8). + /// </summary> + LitContextBits, + /// <summary> + /// Specifies number of literal position bits for LZMA (0 <= x <= 4). + /// </summary> + LitPosBits, + /// <summary> + /// Specifies number of fast bytes for LZ*. + /// </summary> + NumFastBytes, + /// <summary> + /// Specifies match finder. LZMA: "BT2", "BT4" or "BT4B". + /// </summary> + MatchFinder, + /// <summary> + /// Specifies the number of match finder cyckes. + /// </summary> + MatchFinderCycles, + /// <summary> + /// Specifies number of passes. + /// </summary> + NumPasses, + /// <summary> + /// Specifies number of algorithm. + /// </summary> + Algorithm, + /// <summary> + /// Specifies the number of threads. + /// </summary> + NumThreads, + /// <summary> + /// Specifies mode with end marker. + /// </summary> + EndMarker + }; + + + public interface ISetCoderProperties + { + void SetCoderProperties(CoderPropID[] propIDs, object[] properties); + }; + + public interface IWriteCoderProperties + { + void WriteCoderProperties(System.IO.Stream outStream); + } + + public interface ISetDecoderProperties + { + void SetDecoderProperties(byte[] properties); + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/ICoder.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/ICoder.cs.meta new file mode 100644 index 0000000..f4ca52a --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/7zip/ICoder.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9f4fba00efa28594ea18888f574d028a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS.meta new file mode 100644 index 0000000..bee3c03 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 59ab7ccacd9a9944bb9456da235d6760 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/ArchiveFlags.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/ArchiveFlags.cs new file mode 100644 index 0000000..6f46f5d --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/ArchiveFlags.cs @@ -0,0 +1,14 @@ +锘縰sing System; + +namespace UnityFS +{ + [Flags] + public enum ArchiveFlags + { + CompressionTypeMask = 0x3f, + BlocksAndDirectoryInfoCombined = 0x40, + BlocksInfoAtTheEnd = 0x80, + OldWebPluginCompatibility = 0x100, + BlockInfoNeedPaddingAtStart = 0x200 + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/ArchiveFlags.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/ArchiveFlags.cs.meta new file mode 100644 index 0000000..95b0a25 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/ArchiveFlags.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 099de05eebdffaf4baeed3290dc98aaf +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/BinaryReaderExtensions.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/BinaryReaderExtensions.cs new file mode 100644 index 0000000..848d820 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/BinaryReaderExtensions.cs @@ -0,0 +1,51 @@ +锘縰sing System; +using System.Collections.Generic; +using System.IO; +using System.Text; + +namespace UnityFS +{ + public static class BinaryReaderExtensions + { + + public static void AlignStream(this BinaryReader reader, int alignment) + { + var pos = reader.BaseStream.Position; + var mod = pos % alignment; + if (mod != 0) + { + reader.BaseStream.Position += alignment - mod; + } + } + + public static string ReadAlignedString(this BinaryReader reader) + { + var length = reader.ReadInt32(); + if (length > 0 && length <= reader.BaseStream.Length - reader.BaseStream.Position) + { + var stringData = reader.ReadBytes(length); + var result = Encoding.UTF8.GetString(stringData); + reader.AlignStream(4); + return result; + } + return ""; + } + + public static string ReadStringToNull(this BinaryReader reader, int maxLength = 32767) + { + var bytes = new List<byte>(); + int count = 0; + while (reader.BaseStream.Position != reader.BaseStream.Length && count < maxLength) + { + var b = reader.ReadByte(); + if (b == 0) + { + break; + } + bytes.Add(b); + count++; + } + return Encoding.UTF8.GetString(bytes.ToArray()); + } + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/BinaryReaderExtensions.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/BinaryReaderExtensions.cs.meta new file mode 100644 index 0000000..224d27e --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/BinaryReaderExtensions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a84e427dd05adde44b4345b3fd49007a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/BinaryWriterExtensions.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/BinaryWriterExtensions.cs new file mode 100644 index 0000000..8015515 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/BinaryWriterExtensions.cs @@ -0,0 +1,33 @@ +锘縰sing System; +using System.IO; +using System.Text; + +namespace UnityFS +{ + public static class BinaryWriterExtensions + { + public static void AlignStream(this BinaryWriter writer, int alignment) + { + var pos = writer.BaseStream.Position; + var mod = pos % alignment; + if (mod != 0) + { + writer.Write(new byte[alignment - mod]); + } + } + + public static void WriteAlignedString(this BinaryWriter writer, string str) + { + var bytes = Encoding.UTF8.GetBytes(str); + writer.Write(bytes.Length); + writer.Write(bytes); + writer.AlignStream(4); + } + + public static void WriteNullEndString(this BinaryWriter writer, string str) + { + writer.Write(Encoding.UTF8.GetBytes(str)); + writer.Write((byte)0); + } + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/BinaryWriterExtensions.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/BinaryWriterExtensions.cs.meta new file mode 100644 index 0000000..053416c --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/BinaryWriterExtensions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 02eda21769c083346a5bd9b7dca49427 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/BundleFileInfo.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/BundleFileInfo.cs new file mode 100644 index 0000000..d2a9eab --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/BundleFileInfo.cs @@ -0,0 +1,24 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace UnityFS +{ + public class BundleSubFile + { + public string file; + public byte[] data; + } + + public class BundleFileInfo + { + public string signature; + public uint version; + public string unityVersion; + public string unityRevision; + public ArchiveFlags flags; + public List<BundleSubFile> files; + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/BundleFileInfo.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/BundleFileInfo.cs.meta new file mode 100644 index 0000000..b33b9b2 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/BundleFileInfo.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1a72550a949e322419b9c5d6e4fe495d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/BundleFileReader.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/BundleFileReader.cs new file mode 100644 index 0000000..1804cf4 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/BundleFileReader.cs @@ -0,0 +1,212 @@ +锘縰sing LZ4; +using System; +using System.IO; +using System.Linq; +using UnityEngine; + +namespace UnityFS +{ + + public class BundleFileReader + { + + private Header m_Header; + private StorageBlock[] m_BlocksInfo; + private Node[] m_DirectoryInfo; + + private StreamFile[] fileList; + + public BundleFileReader() + { + + } + + public void Load(EndianBinaryReader reader) + { + Debug.Log($"reader. pos:{reader.Position} length:{reader.BaseStream.Length}"); + m_Header = new Header(); + m_Header.signature = reader.ReadStringToNull(); + m_Header.version = reader.ReadUInt32(); + m_Header.unityVersion = reader.ReadStringToNull(); + m_Header.unityRevision = reader.ReadStringToNull(); + System.Diagnostics.Debug.Assert(m_Header.signature == "UnityFS"); + + + m_Header.size = reader.ReadInt64(); + Debug.Log($"header size:{m_Header.size}"); + m_Header.compressedBlocksInfoSize = reader.ReadUInt32(); + m_Header.uncompressedBlocksInfoSize = reader.ReadUInt32(); + m_Header.flags = (ArchiveFlags)reader.ReadUInt32(); + if (m_Header.signature != "UnityFS") + { + reader.ReadByte(); + } + + ReadMetadata(reader); + using (var blocksStream = CreateBlocksStream()) + { + ReadBlocks(reader, blocksStream); + ReadFiles(blocksStream); + } + } + + public BundleFileInfo CreateBundleFileInfo() + { + return new BundleFileInfo + { + signature = m_Header.signature, + version = m_Header.version, + unityVersion = m_Header.unityVersion, + unityRevision = m_Header.unityRevision, + files = fileList.Select(f => new BundleSubFile { file = f.path, data = f.stream.ReadAllBytes() }).ToList(), + }; + } + + private byte[] ReadBlocksInfoAndDirectoryMetadataUnCompressedBytes(EndianBinaryReader reader) + { + byte[] metadataUncompressBytes; + if (m_Header.version >= 7) + { + reader.AlignStream(16); + } + if ((m_Header.flags & ArchiveFlags.BlocksInfoAtTheEnd) != 0) + { + var position = reader.Position; + reader.Position = reader.BaseStream.Length - m_Header.compressedBlocksInfoSize; + metadataUncompressBytes = reader.ReadBytes((int)m_Header.compressedBlocksInfoSize); + reader.Position = position; + } + else //0x40 BlocksAndDirectoryInfoCombined + { + metadataUncompressBytes = reader.ReadBytes((int)m_Header.compressedBlocksInfoSize); + } + return metadataUncompressBytes; + } + + private byte[] DecompressBytes(CompressionType compressionType, byte[] compressedBytes, uint uncompressedSize) + { + switch (compressionType) + { + case CompressionType.None: + { + return compressedBytes; + } + case CompressionType.Lzma: + { + var uncompressedStream = new MemoryStream((int)(uncompressedSize)); + using (var compressedStream = new MemoryStream(compressedBytes)) + { + ComparessHelper.Decompress7Zip(compressedStream, uncompressedStream, m_Header.compressedBlocksInfoSize, m_Header.uncompressedBlocksInfoSize); + } + return uncompressedStream.ReadAllBytes(); + } + case CompressionType.Lz4: + case CompressionType.Lz4HC: + { + var uncompressedBytes = new byte[uncompressedSize]; + var numWrite = LZ4Codec.Decode(compressedBytes, 0, compressedBytes.Length, uncompressedBytes, 0, uncompressedBytes.Length, true); + if (numWrite != uncompressedSize) + { + throw new IOException($"Lz4 decompression error, write {numWrite} bytes but expected {uncompressedSize} bytes"); + } + return uncompressedBytes; + } + default: + throw new IOException($"Unsupported compression type {compressionType}"); + } + } + + private void ReadMetadata(EndianBinaryReader reader) + { + byte[] compressMetadataBytes = ReadBlocksInfoAndDirectoryMetadataUnCompressedBytes(reader); + MemoryStream metadataStream = new MemoryStream(DecompressBytes((CompressionType)(m_Header.flags & ArchiveFlags.CompressionTypeMask), compressMetadataBytes, m_Header.uncompressedBlocksInfoSize)); + using (var blocksInfoReader = new EndianBinaryReader(metadataStream)) + { + var uncompressedDataHash = blocksInfoReader.ReadBytes(16); + var blocksInfoCount = blocksInfoReader.ReadInt32(); + m_BlocksInfo = new StorageBlock[blocksInfoCount]; + for (int i = 0; i < blocksInfoCount; i++) + { + m_BlocksInfo[i] = new StorageBlock + { + uncompressedSize = blocksInfoReader.ReadUInt32(), + compressedSize = blocksInfoReader.ReadUInt32(), + flags = (StorageBlockFlags)blocksInfoReader.ReadUInt16() + }; + } + + var nodesCount = blocksInfoReader.ReadInt32(); + m_DirectoryInfo = new Node[nodesCount]; + for (int i = 0; i < nodesCount; i++) + { + m_DirectoryInfo[i] = new Node + { + offset = blocksInfoReader.ReadInt64(), + size = blocksInfoReader.ReadInt64(), + flags = blocksInfoReader.ReadUInt32(), + path = blocksInfoReader.ReadStringToNull(), + }; + } + } + if (m_Header.flags.HasFlag(ArchiveFlags.BlockInfoNeedPaddingAtStart)) + { + reader.AlignStream(16); + } + } + + + private Stream CreateBlocksStream() + { + Stream blocksStream; + var uncompressedSizeSum = m_BlocksInfo.Sum(x => x.uncompressedSize); + if (uncompressedSizeSum >= int.MaxValue) + { + throw new Exception($"too fig file"); + } + else + { + blocksStream = new MemoryStream((int)uncompressedSizeSum); + } + return blocksStream; + } + + public void ReadFiles(Stream blocksStream) + { + fileList = new StreamFile[m_DirectoryInfo.Length]; + for (int i = 0; i < m_DirectoryInfo.Length; i++) + { + var node = m_DirectoryInfo[i]; + var file = new StreamFile(); + fileList[i] = file; + file.path = node.path; + file.fileName = Path.GetFileName(node.path); + if (node.size >= int.MaxValue) + { + throw new Exception($"exceed max file size"); + /*var memoryMappedFile = MemoryMappedFile.CreateNew(null, entryinfo_size); + file.stream = memoryMappedFile.CreateViewStream();*/ + //var extractPath = path + "_unpacked" + Path.DirectorySeparatorChar; + //Directory.CreateDirectory(extractPath); + //file.stream = new FileStream(extractPath + file.fileName, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite); + } + file.stream = new MemoryStream((int)node.size); + blocksStream.Position = node.offset; + blocksStream.CopyTo(file.stream, node.size); + file.stream.Position = 0; + } + } + + private void ReadBlocks(EndianBinaryReader reader, Stream blocksStream) + { + foreach (var blockInfo in m_BlocksInfo) + { + var compressedSize = (int)blockInfo.compressedSize; + byte[] compressedBlockBytes = reader.ReadBytes(compressedSize); + var compressionType = (CompressionType)(blockInfo.flags & StorageBlockFlags.CompressionTypeMask); + byte[] uncompressedBlockBytes = DecompressBytes(compressionType, compressedBlockBytes, blockInfo.uncompressedSize); + blocksStream.Write(uncompressedBlockBytes, 0, uncompressedBlockBytes.Length); + } + blocksStream.Position = 0; + } + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/BundleFileReader.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/BundleFileReader.cs.meta new file mode 100644 index 0000000..8b3cfae --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/BundleFileReader.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f9b938458cc610e4d8a910c4499693cf +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/BundleFileWriter.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/BundleFileWriter.cs new file mode 100644 index 0000000..7e039cb --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/BundleFileWriter.cs @@ -0,0 +1,112 @@ +锘縰sing LZ4; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UnityEngine; + +namespace UnityFS +{ + public class BundleFileWriter + { + private readonly BundleFileInfo _bundle; + + private readonly List<Node> _files = new List<Node>(); + private readonly List<StorageBlock> _blocks = new List<StorageBlock>(); + + private readonly EndianBinaryWriter _blockDirectoryMetadataStream = new EndianBinaryWriter(new MemoryStream()); + private byte[] _blockBytes; + + public BundleFileWriter(BundleFileInfo bundle) + { + _bundle = bundle; + } + + public void Write(EndianBinaryWriter output) + { + InitBlockAndDirectories(); + + output.WriteNullEndString(_bundle.signature); + output.Write(_bundle.version); + output.WriteNullEndString(_bundle.unityVersion); + output.WriteNullEndString(_bundle.unityRevision); + + BuildBlockDirectoryMetadata(); + + + long sizePos = output.Position; + output.Write(0L); + output.Write((uint)_blockDirectoryMetadataStream.Length); + output.Write((uint)_blockDirectoryMetadataStream.Length); + ArchiveFlags flags = ArchiveFlags.BlocksAndDirectoryInfoCombined | (uint)CompressionType.None; + output.Write((uint)flags); + + if (_bundle.version >= 7) + { + output.AlignStream(16); + } + byte[] metadataBytes = _blockDirectoryMetadataStream.BaseStream.ReadAllBytes(); + output.Write(metadataBytes, 0, metadataBytes.Length); + + byte[] dataBytes = _blockBytes; + output.Write(dataBytes, 0, dataBytes.Length); + + output.Position = sizePos; + output.Write(output.Length); + } + + private void InitBlockAndDirectories() + { + var dataStream = new MemoryStream(); + foreach(var file in _bundle.files) + { + byte[] data = file.data; + _files.Add(new Node { path = file.file, flags = 0, offset = dataStream.Length, size = data.LongLength }); + dataStream.Write(data, 0, data.Length); + } + byte[] dataBytes = dataStream.ToArray(); + + var compressedBlockStream = new MemoryStream(dataBytes.Length / 2); + int blockByteSize = 128 * 1024; + long dataSize = dataBytes.Length; + byte[] tempCompressBlock = new byte[blockByteSize * 2]; + for(long i = 0, blockNum = (dataSize + blockByteSize - 1) / blockByteSize; i < blockNum; i++) + { + long curBlockSize = Math.Min(dataSize, blockByteSize); + dataSize -= curBlockSize; + + int compressedSize = LZ4Codec.Encode(dataBytes, (int)(i * blockByteSize), (int)curBlockSize, tempCompressBlock, 0, tempCompressBlock.Length); + compressedBlockStream.Write(tempCompressBlock, 0, compressedSize); + _blocks.Add(new StorageBlock { flags = (StorageBlockFlags)(int)CompressionType.Lz4, compressedSize = (uint)compressedSize, uncompressedSize = (uint)curBlockSize }); + //Debug.Log($"== block[{i}] uncompressedSize:{curBlockSize} compressedSize:{compressedSize} totalblocksize:{compressedBlockStream.Length}"); + } + _blockBytes = compressedBlockStream.ToArray(); + } + + private void BuildBlockDirectoryMetadata() + { + var hash = new byte[16]; + _blockDirectoryMetadataStream.Write(hash, 0, 16); + + _blockDirectoryMetadataStream.Write((uint)_blocks.Count); + foreach(var b in _blocks) + { + _blockDirectoryMetadataStream.Write(b.uncompressedSize); + _blockDirectoryMetadataStream.Write(b.compressedSize); + _blockDirectoryMetadataStream.Write((ushort)b.flags); + } + + _blockDirectoryMetadataStream.Write((uint)_files.Count); + foreach(var f in _files) + { + _blockDirectoryMetadataStream.Write(f.offset); + _blockDirectoryMetadataStream.Write(f.size); + _blockDirectoryMetadataStream.Write(f.flags); + _blockDirectoryMetadataStream.WriteNullEndString(f.path); + } + //Debug.Log($"block and directory metadata size:{_blockDirectoryMetadataStream.Length}"); + } + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/BundleFileWriter.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/BundleFileWriter.cs.meta new file mode 100644 index 0000000..98d7466 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/BundleFileWriter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d6705163b267de54a868f5e84f6c7024 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/CompressionType.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/CompressionType.cs new file mode 100644 index 0000000..032103b --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/CompressionType.cs @@ -0,0 +1,11 @@ +锘縩amespace UnityFS +{ + public enum CompressionType + { + None, + Lzma, + Lz4, + Lz4HC, + Lzham + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/CompressionType.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/CompressionType.cs.meta new file mode 100644 index 0000000..ce8a30f --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/CompressionType.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ddcd6644c83d2a94f9668d6e913bd80e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/EndianBinaryReader.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/EndianBinaryReader.cs new file mode 100644 index 0000000..d6716a8 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/EndianBinaryReader.cs @@ -0,0 +1,107 @@ +锘縰sing System; +using System.IO; + +namespace UnityFS +{ + public class EndianBinaryReader : BinaryReader + { + private readonly byte[] buffer; + + public EndianType Endian; + + public EndianBinaryReader(Stream stream, EndianType endian = EndianType.BigEndian) : base(stream) + { + Endian = endian; + buffer = new byte[8]; + } + + public long Position + { + get => BaseStream.Position; + set => BaseStream.Position = value; + } + + private unsafe void ReadBufferBigEndian(byte* dst, byte[] src, int size) + { + System.Diagnostics.Debug.Assert(BitConverter.IsLittleEndian); + for (int i = 0; i < size; i++) + { + dst[i] = src[size - i - 1]; + } + } + + public override short ReadInt16() + { + return (short)ReadUInt16(); + } + + public unsafe override ushort ReadUInt16() + { + if (Endian == EndianType.BigEndian) + { + Read(buffer, 0, 2); + ushort x = 0; + ReadBufferBigEndian((byte*)&x, buffer, 2); + return x; + } + return base.ReadUInt16(); + } + + public override int ReadInt32() + { + return (int)ReadUInt32(); + } + + public unsafe override uint ReadUInt32() + { + if (Endian == EndianType.BigEndian) + { + Read(buffer, 0, 4); + uint x = 0; + ReadBufferBigEndian((byte*)&x, buffer, 4); + return x; + } + return base.ReadUInt32(); + } + + public override long ReadInt64() + { + return (long)ReadUInt64(); + } + + public unsafe override ulong ReadUInt64() + { + if (Endian == EndianType.BigEndian) + { + Read(buffer, 0, 8); + + ulong x = 0; + ReadBufferBigEndian((byte*)&x, buffer, 8); + return x; + } + return base.ReadUInt64(); + } + + public override float ReadSingle() + { + if (Endian == EndianType.BigEndian) + { + Read(buffer, 0, 4); + Array.Reverse(buffer, 0, 4); + return BitConverter.ToSingle(buffer, 0); + } + return base.ReadSingle(); + } + + public override double ReadDouble() + { + if (Endian == EndianType.BigEndian) + { + Read(buffer, 0, 8); + Array.Reverse(buffer); + return BitConverter.ToDouble(buffer, 0); + } + return base.ReadDouble(); + } + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/EndianBinaryReader.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/EndianBinaryReader.cs.meta new file mode 100644 index 0000000..53183c0 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/EndianBinaryReader.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9b02c037f0fa1014da65773804248d8d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/EndianBinaryWriter.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/EndianBinaryWriter.cs new file mode 100644 index 0000000..03938a9 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/EndianBinaryWriter.cs @@ -0,0 +1,107 @@ +锘縰sing System; +using System.IO; + +namespace UnityFS +{ + public class EndianBinaryWriter : BinaryWriter + { + private readonly byte[] buffer; + + public EndianType Endian; + + public EndianBinaryWriter(Stream stream, EndianType endian = EndianType.BigEndian) : base(stream) + { + Endian = endian; + buffer = new byte[8]; + } + + public long Position + { + get => BaseStream.Position; + set => BaseStream.Position = value; + } + + public long Length => BaseStream.Length; + + public override void Write(short x) + { + Write((ushort)x); + } + + private unsafe void WriteBufferBigEndian(byte[] dst, byte* src, int size) + { + System.Diagnostics.Debug.Assert(BitConverter.IsLittleEndian); + for(int i = 0; i < size; i++) + { + dst[i] = src[size - i - 1]; + } + } + + public unsafe override void Write(ushort x) + { + if (Endian == EndianType.BigEndian) + { + WriteBufferBigEndian(buffer, (byte*)&x, 2); + Write(buffer, 0, 2); + return; + } + base.Write(x); + } + + public override void Write(int x) + { + Write((uint)x); + } + + public unsafe override void Write(uint x) + { + if (Endian == EndianType.BigEndian) + { + WriteBufferBigEndian(buffer, (byte*)&x, 4); + Write(buffer, 0, 4); + return; + } + base.Write(x); + } + + public override void Write(long x) + { + Write((ulong)x); + } + + public unsafe override void Write(ulong x) + { + if (Endian == EndianType.BigEndian) + { + WriteBufferBigEndian(buffer, (byte*)&x, 8); + Write(buffer, 0, 8); + return; + } + base.Write(x); + } + + public override void Write(float x) + { + if (Endian == EndianType.BigEndian) + { + var buf = BitConverter.GetBytes(x); + Array.Reverse(buf, 0, 4); + Write(buf, 0, 4); + return; + } + base.Write(x); + } + + public override void Write(double x) + { + if (Endian == EndianType.BigEndian) + { + var buf = BitConverter.GetBytes(x); + Array.Reverse(buf, 0, 8); + Write(buf, 0, 8); + return; + } + base.Write(x); + } + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/EndianBinaryWriter.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/EndianBinaryWriter.cs.meta new file mode 100644 index 0000000..cff8503 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/EndianBinaryWriter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4107364c7434b2042ad647b28e322513 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/EndianType.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/EndianType.cs new file mode 100644 index 0000000..53e740f --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/EndianType.cs @@ -0,0 +1,14 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace UnityFS +{ + public enum EndianType + { + LittleEndian, + BigEndian + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/EndianType.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/EndianType.cs.meta new file mode 100644 index 0000000..c878edc --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/EndianType.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2f6cbab4506c18248b410a164be891d2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/GlobalgamedatasPatcher.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/GlobalgamedatasPatcher.cs new file mode 100644 index 0000000..193b1f2 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/GlobalgamedatasPatcher.cs @@ -0,0 +1,53 @@ +锘縰sing System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UnityEngine; +using UnityFS; + +namespace HybridCLR.Editor.UnityBinFileReader +{ + public class Dataunity3dPatcher + { + + public void ApplyPatch(string dataunity3dFile, List<string> hotUpdateAssemblies) + { + var reader = new BundleFileReader(); + using (var fs = new EndianBinaryReader(new MemoryStream(File.ReadAllBytes(dataunity3dFile)))) + { + reader.Load(fs); + } + + var info = reader.CreateBundleFileInfo(); + //Debug.Log($"name:{info.signature} version:{info.version} files:{info.files.Count}"); + //foreach (var file in info.files) + //{ + // Debug.Log($"file:{file.file} size:{file.data.Length}"); + //} + + var globalgamemanagersFile = info.files.Find(f => f.file == "globalgamemanagers"); + //Debug.LogFormat("gobalgamemanagers origin size:{0}", globalgamemanagersFile.data.Length); + + var ggdBinFile = new UnityBinFile(); + ggdBinFile.LoadFromStream(new MemoryStream(globalgamemanagersFile.data)); + ggdBinFile.AddScriptingAssemblies(hotUpdateAssemblies); + byte[] patchedGlobalgamedatasBytes = ggdBinFile.CreatePatchedBytes(); + //Debug.LogFormat("gobalgamemanagers post patche size:{0}", patchedGlobalgamedatasBytes.Length); + globalgamemanagersFile.data = patchedGlobalgamedatasBytes; + + var writer = new BundleFileWriter(info); + var output = new MemoryStream(); + writer.Write(new EndianBinaryWriter(output)); + Debug.Log($"patch file:{dataunity3dFile} size:{output.Length}"); + + //string bakFile = dataunity3dFile + ".bak"; + //if (!File.Exists(bakFile)) + //{ + // File.Copy(dataunity3dFile, bakFile); + //} + File.WriteAllBytes(dataunity3dFile, output.ToArray()); + } + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/GlobalgamedatasPatcher.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/GlobalgamedatasPatcher.cs.meta new file mode 100644 index 0000000..b33d83c --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/GlobalgamedatasPatcher.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 653a22d285c79f44a8113c5571b2d26b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/Header.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/Header.cs new file mode 100644 index 0000000..2715cce --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/Header.cs @@ -0,0 +1,14 @@ +锘縩amespace UnityFS +{ + public class Header + { + public string signature; + public uint version; + public string unityVersion; + public string unityRevision; + public long size; + public uint compressedBlocksInfoSize; + public uint uncompressedBlocksInfoSize; + public ArchiveFlags flags; + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/Header.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/Header.cs.meta new file mode 100644 index 0000000..e5a516a --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/Header.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f121e0520fa65c240884d43fd00b3c2a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/Node.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/Node.cs new file mode 100644 index 0000000..d9cfd97 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/Node.cs @@ -0,0 +1,10 @@ +锘縩amespace UnityFS +{ + public class Node + { + public long offset; + public long size; + public uint flags; + public string path; + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/Node.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/Node.cs.meta new file mode 100644 index 0000000..0736374 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/Node.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e3eea8a6a32b6ac4ba609b39715e25e2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/ScriptingAssembliesJsonPatcher.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/ScriptingAssembliesJsonPatcher.cs new file mode 100644 index 0000000..71b9ab3 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/ScriptingAssembliesJsonPatcher.cs @@ -0,0 +1,50 @@ +锘縰sing System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UnityEngine; + +namespace UnityFS +{ + public class ScriptingAssembliesJsonPatcher + { + [Serializable] + private class ScriptingAssemblies + { + public List<string> names; + public List<int> types; + } + + private string _file; + ScriptingAssemblies _scriptingAssemblies; + + public void Load(string file) + { + _file = file; + string content = File.ReadAllText(file); + _scriptingAssemblies = JsonUtility.FromJson<ScriptingAssemblies>(content); + } + + public void AddScriptingAssemblies(List<string> assemblies) + { + foreach (string name in assemblies) + { + if (!_scriptingAssemblies.names.Contains(name)) + { + _scriptingAssemblies.names.Add(name); + _scriptingAssemblies.types.Add(16); // user dll type + Debug.Log($"[PatchScriptAssembliesJson] add hotfix assembly:{name} to {_file}"); + } + } + } + + public void Save(string jsonFile) + { + string content = JsonUtility.ToJson(_scriptingAssemblies); + + File.WriteAllText(jsonFile, content); + } + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/ScriptingAssembliesJsonPatcher.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/ScriptingAssembliesJsonPatcher.cs.meta new file mode 100644 index 0000000..b1d4449 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/ScriptingAssembliesJsonPatcher.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8f2dd29d56a640d4ebd1c2fd374b7638 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/SevenZipHelper.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/SevenZipHelper.cs new file mode 100644 index 0000000..2d17669 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/SevenZipHelper.cs @@ -0,0 +1,49 @@ +using System; +using System.IO; +using SevenZip.Compression.LZMA; + + +namespace UnityFS +{ + public static class ComparessHelper + { + public static MemoryStream Decompress7Zip(MemoryStream inStream) + { + var decoder = new Decoder(); + + inStream.Seek(0, SeekOrigin.Begin); + var newOutStream = new MemoryStream(); + + var properties = new byte[5]; + if (inStream.Read(properties, 0, 5) != 5) + throw new Exception("input .lzma is too short"); + long outSize = 0; + for (var i = 0; i < 8; i++) + { + var v = inStream.ReadByte(); + if (v < 0) + throw new Exception("Can't Read 1"); + outSize |= ((long)(byte)v) << (8 * i); + } + decoder.SetDecoderProperties(properties); + + var compressedSize = inStream.Length - inStream.Position; + decoder.Code(inStream, newOutStream, compressedSize, outSize, null); + + newOutStream.Position = 0; + return newOutStream; + } + + public static void Decompress7Zip(Stream compressedStream, Stream decompressedStream, long compressedSize, long decompressedSize) + { + var basePosition = compressedStream.Position; + var decoder = new Decoder(); + var properties = new byte[5]; + if (compressedStream.Read(properties, 0, 5) != 5) + throw new Exception("input .lzma is too short"); + decoder.SetDecoderProperties(properties); + decoder.Code(compressedStream, decompressedStream, compressedSize - 5, decompressedSize, null); + compressedStream.Position = basePosition + compressedSize; + } + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/SevenZipHelper.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/SevenZipHelper.cs.meta new file mode 100644 index 0000000..77f375b --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/SevenZipHelper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6606a654e10b3ba48b76b566b903b353 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/StorageBlock.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/StorageBlock.cs new file mode 100644 index 0000000..148c4d1 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/StorageBlock.cs @@ -0,0 +1,9 @@ +锘縩amespace UnityFS +{ + public class StorageBlock + { + public uint compressedSize; + public uint uncompressedSize; + public StorageBlockFlags flags; + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/StorageBlock.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/StorageBlock.cs.meta new file mode 100644 index 0000000..e1e8ad9 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/StorageBlock.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 40dc58bec5631f14c9c17c8a486496d4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/StorageBlockFlags.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/StorageBlockFlags.cs new file mode 100644 index 0000000..619fcac --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/StorageBlockFlags.cs @@ -0,0 +1,11 @@ +锘縰sing System; + +namespace UnityFS +{ + [Flags] + public enum StorageBlockFlags + { + CompressionTypeMask = 0x3f, + Streamed = 0x40 + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/StorageBlockFlags.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/StorageBlockFlags.cs.meta new file mode 100644 index 0000000..d3f199d --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/StorageBlockFlags.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 79b9ed6799d3caf459cf2dfae5765a23 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/StreamExtensions.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/StreamExtensions.cs new file mode 100644 index 0000000..ecffd07 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/StreamExtensions.cs @@ -0,0 +1,32 @@ +锘縰sing System.IO; + +namespace UnityFS +{ + public static class StreamExtensions + { + private const int BufferSize = 81920; + + public static void CopyTo(this Stream source, Stream destination, long size) + { + var buffer = new byte[BufferSize]; + for (var left = size; left > 0; left -= BufferSize) + { + int toRead = BufferSize < left ? BufferSize : (int)left; + int read = source.Read(buffer, 0, toRead); + destination.Write(buffer, 0, read); + if (read != toRead) + { + return; + } + } + } + + public static byte[] ReadAllBytes(this Stream source) + { + source.Position = 0; + var bytes = new byte[source.Length]; + source.Read(bytes, 0, bytes.Length); + return bytes; + } + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/StreamExtensions.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/StreamExtensions.cs.meta new file mode 100644 index 0000000..a06440e --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/StreamExtensions.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2262fbf5672028a48b0c63821d7ff0c0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/StreamFile.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/StreamFile.cs new file mode 100644 index 0000000..0fffc06 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/StreamFile.cs @@ -0,0 +1,11 @@ +锘縰sing System.IO; + +namespace UnityFS +{ + public class StreamFile + { + public string path; + public string fileName; + public Stream stream; + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/StreamFile.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/StreamFile.cs.meta new file mode 100644 index 0000000..7c14e8d --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/StreamFile.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: fad7df04825c947489aad0d5d0c191a7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/UnityBinFile.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/UnityBinFile.cs new file mode 100644 index 0000000..ad4ad5f --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/UnityBinFile.cs @@ -0,0 +1,124 @@ +锘縰sing System.Collections; +using System.Collections.Generic; +using System.IO; +using UnityEngine; +using System.Text; +using System.Reflection; +using System; +using System.Linq; + +namespace UnityFS +{ + /// <summary> + /// Unity 鐢熸垚鐨勪簩杩涘埗鏂囦欢(鏈唬鐮佷笉鏀寔5.x涔嬪墠鐨勭増鏈�) + /// </summary> + public unsafe class UnityBinFile + { + /* + * MonoManager: idx: 6; + * type: metaData.types[objects[6].typeID] + */ + public const int kMonoManagerIdx = 6; + + public FileHeader header; + public MetaData metaData; + public ScriptsData scriptsData; + + private Stream _originStream; + + public void LoadFromStream(Stream source) + { + _originStream = source; + using (var br = new BinaryReader(source, Encoding.UTF8, true)) + { + header.LoadFromStream(br); + // 鎸夌悊璇� metaData 搴旇鏂板紑涓�涓猙uffer鏉ラ伩鍏嶅姞杞芥椂鐨勫榻愰�昏緫闂锛屼絾鐢变簬 sizeof(Header) = 20锛屽凡缁忓榻愬埌4浜嗭紝鎵�浠ュ彲浠ヨ繛缁 + metaData.LoadFromStream(br, header.dataOffset); + scriptsData = metaData.GetScriptData(br); + } + } + + public void Load(string path) + { + LoadFromStream(new MemoryStream(File.ReadAllBytes(path))); + } + + public void AddScriptingAssemblies(List<string> assemblies) + { + foreach (string name in assemblies) + { + if (!scriptsData.dllNames.Contains(name)) + { + scriptsData.dllNames.Add(name); + scriptsData.dllTypes.Add(16); // user dll type + Debug.Log($"[PatchScriptAssembliesJson] add dll:{name} to globalgamemanagers"); + } + } + } + + public byte[] CreatePatchedBytes() + { + var fsR = _originStream; + fsR.Position = 0; + var brR = new BinaryReader(fsR, Encoding.UTF8, true); + + var ms = new MemoryStream((int)(header.fileSize * 1.5f)); + var bw = new BinaryWriter(ms, Encoding.UTF8, true); + + /* + * 寮�濮嬪啓鍏ata + * dll鍚嶇О鍒楄〃瀛樺偍浜� data 鍖烘锛屼慨鏀瑰叾鏁版嵁骞朵笉浼氬奖鍝� MetaData 澶у皬锛屽洜姝� dataOffset 涓嶄細鏀瑰彉 + */ + ms.Position = header.dataOffset; + + Dictionary<long, ObjectInfo> newObjInfos = new Dictionary<long, ObjectInfo>(); + foreach (var kv in metaData.objects) + { + long objID = kv.Key; + ObjectInfo objInfo = kv.Value; + + byte[] buff = new byte[objInfo.size]; + fsR.Position = objInfo.realPos; + brR.Read(buff, 0, buff.Length); + + + {// unity 鐨勬暟鎹亸绉昏矊浼间細瀵归綈鍒� 8 + int newPos = (((int)ms.Position + 7) >> 3) << 3; + int gapSize = newPos - (int)ms.Position; + + for (int i = 0; i < gapSize; i++) + bw.Write((byte)0); + + objInfo.dataPos = (uint)ms.Position - header.dataOffset; // 閲嶅畾浣嶆暟鎹亸绉� + } + + if (objID != kMonoManagerIdx) + bw.Write(buff, 0, buff.Length); + else + objInfo.size = (uint)scriptsData.SaveToStream(bw); + + newObjInfos.Add(objID, objInfo); + } + + metaData.objects = newObjInfos; + header.fileSize = (uint)ms.Position; + + ms.Position = 0; + header.SaveToStream(bw); + metaData.SaveToStream(bw); + + brR.Close(); + + // 鍐欏叆鏂版枃浠� + ms.Position = 0; + return ms.ToArray(); + } + + public void Save(string newPath) + { + byte[] patchedBytes = CreatePatchedBytes(); + File.WriteAllBytes(newPath, patchedBytes); + } + } + +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/UnityBinFile.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/UnityBinFile.cs.meta new file mode 100644 index 0000000..457dbb7 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/UnityBinFile.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7f9902041e9a1ff4c9f2d65d6384530d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/UnityBinFileDefines.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/UnityBinFileDefines.cs new file mode 100644 index 0000000..637dc4e --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/UnityBinFileDefines.cs @@ -0,0 +1,397 @@ +锘縰sing System.Collections; +using System.Collections.Generic; +using System.IO; +using UnityEngine; +using static UnityFS.UnityBinUtils; + +namespace UnityFS +{ + public struct FileHeader + { + public const int kSize = 20; + + public uint dataSize => fileSize - metadataSize; + + public uint metadataSize; + public uint fileSize; + public uint version; + public uint dataOffset; + public byte endianess; + + public void LoadFromStream(BinaryReader br) + { + long startPos = br.BaseStream.Position; + metadataSize = br.ReadUInt32(); + fileSize = br.ReadUInt32(); + version = br.ReadUInt32(); + dataOffset = br.ReadUInt32(); + endianess = br.ReadByte(); + br.BaseStream.Position = startPos + kSize; + + SwapEndianess(); + } + + public long SaveToStream(BinaryWriter bw) + { + SwapEndianess(); + + long startPos = bw.BaseStream.Position; + bw.Write(metadataSize); + bw.Write(fileSize); + bw.Write(version); + bw.Write(dataOffset); + bw.Write(endianess); + bw.BaseStream.Position = startPos + kSize; + return kSize; + } + + void SwapEndianess() + { + SwapUInt(ref metadataSize); + SwapUInt(ref fileSize); + SwapUInt(ref version); + SwapUInt(ref dataOffset); + } + } + + public struct MetaData + { + public long dataStartPos; + + public string version; + public uint platform; + public bool enableTypeTree; + public int typeCount; + public ObjectType[] types; + public int objectCount; + public Dictionary<long, ObjectInfo> objects; + public int scriptTypeCount; + public ScriptType[] scriptTypes; + public int externalsCount; + public ExternalInfo[] externals; + +#if UNITY_2019_2_OR_NEWER + public int refTypeCount; + public ObjectType[] refTypes; +#endif + public string dummyStr; + + public void LoadFromStream(BinaryReader br, uint dataOffset) + { + long startPos = br.BaseStream.Position; + dataStartPos = startPos; + + version = br.ReadRawString(); + platform = br.ReadUInt32(); + enableTypeTree = br.ReadBoolean(); + typeCount = br.ReadInt32(); + types = new ObjectType[typeCount]; + + for (int i = 0; i < typeCount; i++) + { + types[i].LoadFromStream(br); + } + + objectCount = br.ReadInt32(); + objects = new Dictionary<long, ObjectInfo>(); + for(int i = 0; i < objectCount; i++) + { + long id = br.AlignedReadInt64(); + ObjectInfo objInfo = new ObjectInfo(); + objInfo.LoadFromStream(br); + objInfo.realPos = objInfo.dataPos + dataOffset; + + objects.Add(id, objInfo); + } + + scriptTypeCount = br.ReadInt32(); + scriptTypes = new ScriptType[scriptTypeCount]; + for(int i = 0; i < scriptTypeCount; i++) + { + scriptTypes[i].LoadFromStream(br); + } + + externalsCount = br.ReadInt32(); + externals = new ExternalInfo[externalsCount]; + for(int i = 0; i < externalsCount; i++) + { + externals[i].LoadFromStream(br); + } + +#if UNITY_2019_2_OR_NEWER + refTypeCount = br.ReadInt32(); + refTypes = new ObjectType[refTypeCount]; + for(int i = 0; i < refTypeCount; i++) + { + refTypes[i].LoadFromStream(br); + } +#endif + dummyStr = br.ReadRawString(); + } + + public long SaveToStream(BinaryWriter bw) + { + long startPos = bw.BaseStream.Position; + bw.WriteRawString(version); + bw.Write(platform); + bw.Write(enableTypeTree); + + bw.Write(typeCount); + foreach(var type in types) + type.SaveToStream(bw); + + bw.Write(objectCount); + foreach (var kv in objects) + { + bw.AlignedWriteInt64(kv.Key); + kv.Value.SaveToStream(bw); + } + + bw.Write(scriptTypeCount); + foreach(var st in scriptTypes) + st.SaveToStream(bw); + + bw.Write(externalsCount); + foreach(var external in externals) + external.SaveToStream(bw); + +#if UNITY_2019_2_OR_NEWER + bw.Write(refTypeCount); + foreach(var refT in refTypes) + refT.SaveToStream(bw); +#endif + + bw.WriteRawString(dummyStr); + + return bw.BaseStream.Position - startPos; + } + + public ScriptsData GetScriptData(BinaryReader br) + { + ObjectInfo objInfo = objects[UnityBinFile.kMonoManagerIdx]; + br.BaseStream.Seek(objInfo.realPos, SeekOrigin.Begin); + + ScriptsData data = new ScriptsData(); + data.LoadFromStream(br); + return data; + } + } + + public struct ObjectType + { + public int typeID; + public bool isStriped; + public short scriptTypeIndex; + + public bool needReadScriptHash; // dont save + + public Hash scriptSigHash; + public Hash typeHash; + + public void LoadFromStream(BinaryReader br) + { + typeID = br.ReadInt32(); + isStriped = br.ReadBoolean(); + scriptTypeIndex = br.ReadInt16(); + + needReadScriptHash = typeID == -1 || typeID == 0x72; + if(needReadScriptHash) + scriptSigHash.LoadFromStream(br); + + typeHash.LoadFromStream(br); + + // GlobalManagers does not has TypeTrees + } + + public long SaveToStream(BinaryWriter bw) + { + long startPos = bw.BaseStream.Position; + bw.Write(typeID); + bw.Write(isStriped); + bw.Write(scriptTypeIndex); + + if(needReadScriptHash) + scriptSigHash.SaveToStream(bw); + + typeHash.SaveToStream(bw); + return bw.BaseStream.Position - startPos; + } + + public int Size() + { + int ret = 0; + ret += sizeof(int); + ret += sizeof(bool); + ret += sizeof(short); + + if (needReadScriptHash) + ret += Hash.kSize; + + ret += Hash.kSize; + return ret; + } + } + + public struct ObjectInfo + { + public const int kSize = 12; + + public uint dataPos; + public uint size; + public uint typeID; + + public uint realPos; // dataPos + Header.dataOffset; // dont save + + public void LoadFromStream(BinaryReader br) + { + dataPos = br.ReadUInt32(); + size = br.ReadUInt32(); + typeID = br.ReadUInt32(); + } + + public long SaveToStream(BinaryWriter bw) + { + bw.Write(dataPos); + bw.Write(size); + bw.Write(typeID); + return kSize; + } + } + + public struct ScriptType + { + public int localFileIndex; + public long localIdentifierOfBin; + + public void LoadFromStream(BinaryReader br) + { + localFileIndex = br.ReadInt32(); + localIdentifierOfBin = br.AlignedReadInt64(); + } + + public long SaveToStream(BinaryWriter bw) + { + long startPos = bw.BaseStream.Position; + bw.Write(localFileIndex); + bw.AlignedWriteInt64(localIdentifierOfBin); + return bw.BaseStream.Position - startPos; + } + } + + public struct ExternalInfo + { + public string dummy; + public Hash guid; + public int type; + public string name; + + public void LoadFromStream(BinaryReader br) + { + dummy = br.ReadRawString(); + guid.LoadFromStream(br); + type = br.ReadInt32(); + name = br.ReadRawString(); + } + + public long SaveToStream(BinaryWriter bw) + { + long startPos = bw.BaseStream.Position; + bw.WriteRawString(dummy); + guid.SaveToStream(bw); + bw.Write(type); + bw.WriteRawString(name); + return bw.BaseStream.Position - startPos; + } + } + + public struct ScriptsData + { + public ScriptID[] scriptIDs; + public List<string> dllNames; + public List<int> dllTypes; // 16 is user type + + public void LoadFromStream(BinaryReader br) + { + { + int count = br.ReadInt32(); + scriptIDs = new ScriptID[count]; + for(int i = 0; i < count; i++) + scriptIDs[i].LoadFromStream(br); + } + { + int count = br.ReadInt32(); + dllNames = new List<string>(count); + for (var i = 0; i < count; i++) + dllNames.Add(br.ReadSizeString()); + } + { + int count = br.ReadInt32(); + dllTypes = new List<int>(count); + for(var i = 0; i < count; i++) + dllTypes.Add(br.ReadInt32()); + } + } + + public long SaveToStream(BinaryWriter bw) + { + long startPos = bw.BaseStream.Position; + bw.Write(scriptIDs.Length); + for(int i = 0; i < scriptIDs.Length; i++) + scriptIDs[i].SaveToStream(bw); + + bw.Write(dllNames.Count); + for(int i = 0, imax = dllNames.Count; i < imax; i++) + bw.WriteSizeString(dllNames[i]); + + bw.Write(dllTypes.Count); + for(int i = 0, imax = dllTypes.Count; i < imax; i++) + bw.Write(dllTypes[i]); + + return bw.BaseStream.Position - startPos; + } + } + + public struct ScriptID + { + public int fileID; + public long pathID; // localIdentifier + + public void LoadFromStream(BinaryReader br) + { + fileID = br.ReadInt32(); + pathID = br.ReadInt64(); + } + + public long SaveToStream(BinaryWriter bw) + { + bw.Write(fileID); + bw.Write(pathID); + return 4 + 8; + } + } + + public struct Hash + { + public const int kSize = 16; + + public int[] data; + + public void LoadFromStream(BinaryReader br) + { + data = new int[4]; + for(int i = 0; i < data.Length; i++) + { + data[i] = br.ReadInt32(); + } + } + + public long SaveToStream(BinaryWriter bw) + { + for(int i = 0; i < data.Length; i++) + { + bw.Write(data[i]); + } + return kSize; + } + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/UnityBinFileDefines.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/UnityBinFileDefines.cs.meta new file mode 100644 index 0000000..89a829a --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/UnityBinFileDefines.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 10655ce82e730324db6ae297f77df04b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/UnityBinUtils.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/UnityBinUtils.cs new file mode 100644 index 0000000..edeefb3 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/UnityBinUtils.cs @@ -0,0 +1,78 @@ +锘縰sing System.Collections; +using System.Collections.Generic; +using System.IO; +using UnityEngine; +using System.Text; + +namespace UnityFS +{ + public static class UnityBinUtils + { + public static void SwapUInt(ref uint val) + { + val = (val >> 24) | ((val >> 8) & 0x0000ff00) | ((val << 8) & 0x00ff0000) | (val << 24); + } + + public static string ReadRawString(this BinaryReader br) + { + long startPos = br.BaseStream.Position; + while (true) + { + byte val = br.ReadByte(); + if(val == 0) + break; + } + int size = (int)(br.BaseStream.Position - startPos); + br.BaseStream.Position = startPos; + + byte[] buffer = br.ReadBytes(size); + string ret = Encoding.UTF8.GetString(buffer, 0, size - 1); + + return ret; + } + + public static void WriteRawString(this BinaryWriter bw, string str) + { + byte[] buffer = Encoding.UTF8.GetBytes(str); + bw.Write(buffer, 0, buffer.Length); + bw.Write((byte)0); + } + + public static string ReadSizeString(this BinaryReader br) + { + int size = br.ReadInt32(); + byte[] buff = br.ReadBytes(size); + br.BaseStream.AlignOffset4(); + + string ret = Encoding.UTF8.GetString(buff); + return ret; + } + + public static void WriteSizeString(this BinaryWriter bw, string str) + { + byte[] buff = Encoding.UTF8.GetBytes(str); + bw.Write(buff.Length); + bw.Write(buff, 0, buff.Length); + bw.BaseStream.AlignOffset4(); + } + + public static void AlignOffset4(this Stream stream) + { + int offset = (((int)stream.Position + 3) >> 2) << 2; + stream.Position = offset; + } + + public static long AlignedReadInt64(this BinaryReader br) + { + br.BaseStream.AlignOffset4(); + return br.ReadInt64(); + } + + public static void AlignedWriteInt64(this BinaryWriter bw, long val) + { + bw.BaseStream.AlignOffset4(); + bw.Write(val); + } + } +} + diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/UnityBinUtils.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/UnityBinUtils.cs.meta new file mode 100644 index 0000000..4be54e7 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityFS/UnityBinUtils.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 12a24c30a3914be418be10cfebfa9649 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook.meta new file mode 100644 index 0000000..4fab614 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 13fe0cab0b357464d889de45c8d98850 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/CodePatcher.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/CodePatcher.cs new file mode 100644 index 0000000..6ec2fa7 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/CodePatcher.cs @@ -0,0 +1,320 @@ +锘縰sing DotNetDetour; +using System; +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using System.Linq; + +namespace MonoHook +{ + public unsafe abstract class CodePatcher + { + public bool isValid { get; protected set; } + + protected void* _pTarget, _pReplace, _pProxy; + protected int _jmpCodeSize; + protected byte[] _targetHeaderBackup; + + public CodePatcher(IntPtr target, IntPtr replace, IntPtr proxy, int jmpCodeSize) + { + _pTarget = target.ToPointer(); + _pReplace = replace.ToPointer(); + _pProxy = proxy.ToPointer(); + _jmpCodeSize = jmpCodeSize; + } + + public void ApplyPatch() + { + BackupHeader(); + EnableAddrModifiable(); + PatchTargetMethod(); + PatchProxyMethod(); + FlushICache(); + } + + public void RemovePatch() + { + if (_targetHeaderBackup == null) + return; + + EnableAddrModifiable(); + RestoreHeader(); + FlushICache(); + } + + protected void BackupHeader() + { + if (_targetHeaderBackup != null) + return; + + uint requireSize = LDasm.SizeofMinNumByte(_pTarget, _jmpCodeSize); + _targetHeaderBackup = new byte[requireSize]; + + fixed (void* ptr = _targetHeaderBackup) + HookUtils.MemCpy(ptr, _pTarget, _targetHeaderBackup.Length); + } + + protected void RestoreHeader() + { + if (_targetHeaderBackup == null) + return; + + HookUtils.MemCpy_Jit(_pTarget, _targetHeaderBackup); + } + + protected void PatchTargetMethod() + { + byte[] buff = GenJmpCode(_pTarget, _pReplace); + HookUtils.MemCpy_Jit(_pTarget, buff); + } + protected void PatchProxyMethod() + { + if (_pProxy == null) + return; + + // copy target's code to proxy + HookUtils.MemCpy_Jit(_pProxy, _targetHeaderBackup); + + // jmp to target's new position + long jmpFrom = (long)_pProxy + _targetHeaderBackup.Length; + long jmpTo = (long)_pTarget + _targetHeaderBackup.Length; + + byte[] buff = GenJmpCode((void*)jmpFrom, (void*)jmpTo); + HookUtils.MemCpy_Jit((void*)jmpFrom, buff); + } + + protected void FlushICache() + { + HookUtils.FlushICache(_pTarget, _targetHeaderBackup.Length); + HookUtils.FlushICache(_pProxy, _targetHeaderBackup.Length * 2); + } + protected abstract byte[] GenJmpCode(void* jmpFrom, void* jmpTo); + +#if ENABLE_HOOK_DEBUG + protected string PrintAddrs() + { + if (IntPtr.Size == 4) + return $"target:0x{(uint)_pTarget:x}, replace:0x{(uint)_pReplace:x}, proxy:0x{(uint)_pProxy:x}"; + else + return $"target:0x{(ulong)_pTarget:x}, replace:0x{(ulong)_pReplace:x}, proxy:0x{(ulong)_pProxy:x}"; + } +#endif + + private void EnableAddrModifiable() + { + HookUtils.SetAddrFlagsToRWX(new IntPtr(_pTarget), _targetHeaderBackup.Length); + HookUtils.SetAddrFlagsToRWX(new IntPtr(_pProxy), _targetHeaderBackup.Length + _jmpCodeSize); + } + } + + public unsafe class CodePatcher_x86 : CodePatcher + { + protected static readonly byte[] s_jmpCode = new byte[] // 5 bytes + { + 0xE9, 0x00, 0x00, 0x00, 0x00, // jmp $val ; $val = $dst - $src - 5 + }; + + public CodePatcher_x86(IntPtr target, IntPtr replace, IntPtr proxy) : base(target, replace, proxy, s_jmpCode.Length) { } + + protected override unsafe byte[] GenJmpCode(void* jmpFrom, void* jmpTo) + { + byte[] ret = new byte[s_jmpCode.Length]; + int val = (int)jmpTo - (int)jmpFrom - 5; + + fixed(void * p = &ret[0]) + { + byte* ptr = (byte*)p; + *ptr = 0xE9; + int* pOffset = (int*)(ptr + 1); + *pOffset = val; + } + return ret; + } + } + + /// <summary> + /// x64涓�2G 鍐呯殑璺宠浆 + /// </summary> + public unsafe class CodePatcher_x64_near : CodePatcher_x86 // x64_near pathcer code is same to x86 + { + public CodePatcher_x64_near(IntPtr target, IntPtr replace, IntPtr proxy) : base(target, replace, proxy) { } + } + + /// <summary> + /// x64涓嬭窛绂昏秴杩�2G鐨勮烦杞� + /// </summary> + public unsafe class CodePatcher_x64_far : CodePatcher + { + protected static readonly byte[] s_jmpCode = new byte[] // 12 bytes + { + // 鐢变簬 rax 浼氳鍑芥暟浣滀负杩斿洖鍊间慨鏀癸紝骞朵笖涓嶄細琚仛涓哄弬鏁颁娇鐢紝鍥犳淇敼鏄畨鍏ㄧ殑 + 0x48, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // mov rax, <jmpTo> + 0x50, // push rax + 0xC3 // ret + }; + + //protected static readonly byte[] s_jmpCode2 = new byte[] // 14 bytes + //{ + // 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // <jmpTo> + // 0xFF, 0x25, 0xF2, 0xFF, 0xFF, 0xFF // jmp [rip - 0xe] + //}; + + public CodePatcher_x64_far(IntPtr target, IntPtr replace, IntPtr proxy) : base(target, replace, proxy, s_jmpCode.Length) { } + protected override unsafe byte[] GenJmpCode(void* jmpFrom, void* jmpTo) + { + byte[] ret = new byte[s_jmpCode.Length]; + + fixed (void* p = &ret[0]) + { + byte* ptr = (byte*)p; + *ptr++ = 0x48; + *ptr++ = 0xB8; + *(long*)ptr = (long)jmpTo; + ptr += 8; + *ptr++ = 0x50; + *ptr++ = 0xC3; + } + return ret; + } + } + + public unsafe class CodePatcher_arm32_near : CodePatcher + { + private static readonly byte[] s_jmpCode = new byte[] // 4 bytes + { + 0x00, 0x00, 0x00, 0xEA, // B $val ; $val = (($dst - $src) / 4 - 2) & 0x1FFFFFF + }; + + public CodePatcher_arm32_near(IntPtr target, IntPtr replace, IntPtr proxy) : base(target, replace, proxy, s_jmpCode.Length) + { + if (Math.Abs((long)target - (long)replace) >= ((1 << 25) - 1)) + throw new ArgumentException("address offset of target and replace must less than ((1 << 25) - 1)"); + +#if ENABLE_HOOK_DEBUG + Debug.Log($"CodePatcher_arm32_near: {PrintAddrs()}"); +#endif + } + + protected override unsafe byte[] GenJmpCode(void* jmpFrom, void* jmpTo) + { + byte[] ret = new byte[s_jmpCode.Length]; + int val = ((int)jmpTo - (int)jmpFrom) / 4 - 2; + + fixed (void* p = &ret[0]) + { + byte* ptr = (byte*)p; + *ptr++ = (byte)val; + *ptr++ = (byte)(val >> 8); + *ptr++ = (byte)(val >> 16); + *ptr++ = 0xEA; + } + return ret; + } + } + + public unsafe class CodePatcher_arm32_far : CodePatcher + { + private static readonly byte[] s_jmpCode = new byte[] // 8 bytes + { + 0x04, 0xF0, 0x1F, 0xE5, // LDR PC, [PC, #-4] + 0x00, 0x00, 0x00, 0x00, // $val + }; + + public CodePatcher_arm32_far(IntPtr target, IntPtr replace, IntPtr proxy) : base(target, replace, proxy, s_jmpCode.Length) + { + if (Math.Abs((long)target - (long)replace) < ((1 << 25) - 1)) + throw new ArgumentException("address offset of target and replace must larger than ((1 << 25) - 1), please use InstructionModifier_arm32_near instead"); + +#if ENABLE_HOOK_DEBUG + Debug.Log($"CodePatcher_arm32_far: {PrintAddrs()}"); +#endif + } + + protected override unsafe byte[] GenJmpCode(void* jmpFrom, void* jmpTo) + { + byte[] ret = new byte[s_jmpCode.Length]; + + fixed (void* p = &ret[0]) + { + uint* ptr = (uint*)p; + *ptr++ = 0xE51FF004; + *ptr = (uint)jmpTo; + } + return ret; + } + } + + /// <summary> + /// arm64 涓� 卤128MB 鑼冨洿鍐呯殑璺宠浆 + /// </summary> + public unsafe class CodePatcher_arm64_near : CodePatcher + { + private static readonly byte[] s_jmpCode = new byte[] // 4 bytes + { + /* + * from 0x14 to 0x17 is B opcode + * offset bits is 26 + * https://developer.arm.com/documentation/ddi0596/2021-09/Base-Instructions/B--Branch- + */ + 0x00, 0x00, 0x00, 0x14, // B $val ; $val = (($dst - $src)/4) & 7FFFFFF + }; + + public CodePatcher_arm64_near(IntPtr target, IntPtr replace, IntPtr proxy) : base(target, replace, proxy, s_jmpCode.Length) + { + if (Math.Abs((long)target - (long)replace) >= ((1 << 26) - 1) * 4) + throw new ArgumentException("address offset of target and replace must less than (1 << 26) - 1) * 4"); + +#if ENABLE_HOOK_DEBUG + Debug.Log($"CodePatcher_arm64: {PrintAddrs()}"); +#endif + } + + protected override unsafe byte[] GenJmpCode(void* jmpFrom, void* jmpTo) + { + byte[] ret = new byte[s_jmpCode.Length]; + int val = (int)((long)jmpTo - (long)jmpFrom) / 4; + + fixed (void* p = &ret[0]) + { + byte* ptr = (byte*)p; + *ptr++ = (byte)val; + *ptr++ = (byte)(val >> 8); + *ptr++ = (byte)(val >> 16); + + byte last = (byte)(val >> 24); + last &= 0b11; + last |= 0x14; + + *ptr = last; + } + return ret; + } + } + + /// <summary> + /// arm64 杩滆窛绂昏烦杞� + /// </summary> + public unsafe class CodePatcher_arm64_far : CodePatcher + { + private static readonly byte[] s_jmpCode = new byte[] // 20 bytes(瀛楄妭鏁拌繃澶氾紝澶嵄闄╀簡锛屼笉寤鸿浣跨敤) + { + /* + * ADR: https://developer.arm.com/documentation/ddi0596/2021-09/Base-Instructions/ADR--Form-PC-relative-address- + * BR: https://developer.arm.com/documentation/ddi0596/2021-09/Base-Instructions/BR--Branch-to-Register- + */ + 0x6A, 0x00, 0x00, 0x10, // ADR X10, #C + 0x4A, 0x01, 0x40, 0xF9, // LDR X10, [X10,#0] + 0x40, 0x01, 0x1F, 0xD6, // BR X10 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // $dst + }; + + public CodePatcher_arm64_far(IntPtr target, IntPtr replace, IntPtr proxy, int jmpCodeSize) : base(target, replace, proxy, jmpCodeSize) + { + } + + protected override unsafe byte[] GenJmpCode(void* jmpFrom, void* jmpTo) + { + throw new NotImplementedException(); + } + } +} \ No newline at end of file diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/CodePatcher.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/CodePatcher.cs.meta new file mode 100644 index 0000000..f745350 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/CodePatcher.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 97cc0d26f72fc4148b8370b2252d1585 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/HookPool.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/HookPool.cs new file mode 100644 index 0000000..34a0599 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/HookPool.cs @@ -0,0 +1,74 @@ +锘縰sing System.Collections; +using System.Collections.Generic; +using System.Reflection; +using UnityEngine; +using System.Linq; +using System.IO; +#if UNITY_EDITOR +using UnityEditor; +#endif + +namespace MonoHook +{ + /// <summary> + /// Hook 姹狅紝闃叉閲嶅 Hook + /// </summary> + public static class HookPool + { + private static Dictionary<MethodBase, MethodHook> _hooks = new Dictionary<MethodBase, MethodHook>(); + + public static void AddHook(MethodBase method, MethodHook hook) + { + MethodHook preHook; + if (_hooks.TryGetValue(method, out preHook)) + { + preHook.Uninstall(); + _hooks[method] = hook; + } + else + _hooks.Add(method, hook); + } + + public static MethodHook GetHook(MethodBase method) + { + if (method == null) return null; + + MethodHook hook; + if (_hooks.TryGetValue(method, out hook)) + return hook; + return null; + } + + public static void RemoveHooker(MethodBase method) + { + if (method == null) return; + + _hooks.Remove(method); + } + + public static void UninstallAll() + { + var list = _hooks.Values.ToList(); + foreach (var hook in list) + hook.Uninstall(); + + _hooks.Clear(); + } + + public static void UninstallByTag(string tag) + { + var list = _hooks.Values.ToList(); + foreach (var hook in list) + { + if(hook.tag == tag) + hook.Uninstall(); + } + } + + public static List<MethodHook> GetAllHooks() + { + return _hooks.Values.ToList(); + } + } + +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/HookPool.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/HookPool.cs.meta new file mode 100644 index 0000000..7503859 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/HookPool.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6b7421e47f0ae1e4ebb72bf18d1d7d48 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/HookUtils.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/HookUtils.cs new file mode 100644 index 0000000..07a5e5e --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/HookUtils.cs @@ -0,0 +1,272 @@ +锘�#if !(UNITY_STANDALONE_OSX || UNITY_EDITOR_OSX) +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Text; +using UnityEngine; + +namespace MonoHook +{ + public static unsafe class HookUtils + { + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + delegate void DelegateFlushICache(void* code, int size); // delegate * unmanaged[Cdecl] <void, byte, uint> native_flush_cache_fun_ptr; // unsupported at C# 8.0 + + static DelegateFlushICache flush_icache; + private static readonly long _Pagesize; + + static HookUtils() + { + PropertyInfo p_SystemPageSize = typeof(Environment).GetProperty("SystemPageSize"); + if (p_SystemPageSize == null) + throw new NotSupportedException("Unsupported runtime"); + _Pagesize = (int)p_SystemPageSize.GetValue(null, new object[0]); + SetupFlushICacheFunc(); + } + + public static void MemCpy(void* pDst, void* pSrc, int len) + { + byte* pDst_ = (byte*)pDst; + byte* pSrc_ = (byte*)pSrc; + + for (int i = 0; i < len; i++) + *pDst_++ = *pSrc_++; + } + + public static void MemCpy_Jit(void* pDst, byte[] src) + { + fixed (void* p = &src[0]) + { + MemCpy(pDst, p, src.Length); + } + } + + /// <summary> + /// set flags of address to `read write execute` + /// </summary> + public static void SetAddrFlagsToRWX(IntPtr ptr, int size) + { + if (ptr == IntPtr.Zero) + return; + +#if UNITY_STANDALONE_WIN || UNITY_EDITOR_WIN + uint oldProtect; + bool ret = VirtualProtect(ptr, (uint)size, Protection.PAGE_EXECUTE_READWRITE, out oldProtect); + UnityEngine.Debug.Assert(ret); +#else + SetMemPerms(ptr,(ulong)size,MmapProts.PROT_READ | MmapProts.PROT_WRITE | MmapProts.PROT_EXEC); +#endif + } + + public static void FlushICache(void* code, int size) + { + if (code == null) + return; + + flush_icache?.Invoke(code, size); + +#if ENABLE_HOOK_DEBUG + Debug.Log($"flush icache at 0x{(IntPtr.Size == 4 ? (uint)code : (ulong)code):x}, size:{size}"); +#endif + } + + public static KeyValuePair<long, long> GetPageAlignedAddr(long code, int size) + { + long pagesize = _Pagesize; + long startPage = (code) & ~(pagesize - 1); + long endPage = (code + size + pagesize - 1) & ~(pagesize - 1); + return new KeyValuePair<long, long>(startPage, endPage); + } + + + const int PRINT_SPLIT = 4; + const int PRINT_COL_SIZE = PRINT_SPLIT * 4; + public static string HexToString(void* ptr, int size, int offset = 0) + { + Func<IntPtr, string> formatAddr = (IntPtr addr__) => IntPtr.Size == 4 ? $"0x{(uint)addr__:x}" : $"0x{(ulong)addr__:x}"; + + byte* addr = (byte*)ptr; + + StringBuilder sb = new StringBuilder(1024); + sb.AppendLine($"addr:{formatAddr(new IntPtr(addr))}"); + + addr += offset; + size += Math.Abs(offset); + + int count = 0; + while (true) + { + sb.Append($"\r\n{formatAddr(new IntPtr(addr + count))}: "); + for (int i = 1; i < PRINT_COL_SIZE + 1; i++) + { + if (count >= size) + goto END; + + sb.Append($"{*(addr + count):x2}"); + if (i % PRINT_SPLIT == 0) + sb.Append(" "); + + count++; + } + } + END:; + return sb.ToString(); + } + + static void SetupFlushICacheFunc() + { + string processorType = SystemInfo.processorType.ToLowerInvariant(); + if (processorType.Contains("intel") || processorType.Contains("amd")) + return; + + if (IntPtr.Size == 4) + { + // never release, so save GCHandle is unnecessary + s_ptr_flush_icache_arm32 = GCHandle.Alloc(s_flush_icache_arm32, GCHandleType.Pinned).AddrOfPinnedObject().ToPointer(); + SetAddrFlagsToRWX(new IntPtr(s_ptr_flush_icache_arm32), s_flush_icache_arm32.Length); + flush_icache = Marshal.GetDelegateForFunctionPointer<DelegateFlushICache>(new IntPtr(s_ptr_flush_icache_arm32)); + } + else + { + s_ptr_flush_icache_arm64 = GCHandle.Alloc(s_flush_icache_arm64, GCHandleType.Pinned).AddrOfPinnedObject().ToPointer(); + SetAddrFlagsToRWX(new IntPtr(s_ptr_flush_icache_arm64), s_flush_icache_arm64.Length); + flush_icache = Marshal.GetDelegateForFunctionPointer<DelegateFlushICache>(new IntPtr(s_ptr_flush_icache_arm64)); + } + +#if ENABLE_HOOK_DEBUG + Debug.Log($"flush_icache delegate is {((flush_icache != null) ? "not " : "")}null"); +#endif + } + + + static void* s_ptr_flush_icache_arm32, s_ptr_flush_icache_arm64; + private static byte[] s_flush_icache_arm32 = new byte[] + { + // void cdecl mono_arch_flush_icache (guint8 *code, gint size) + 0x00, 0x48, 0x2D, 0xE9, // PUSH {R11,LR} + 0x0D, 0xB0, 0xA0, 0xE1, // MOV R11, SP + 0x08, 0xD0, 0x4D, 0xE2, // SUB SP, SP, #8 + 0x04, 0x00, 0x8D, 0xE5, // STR R0, [SP,#8+var_4] + 0x00, 0x10, 0x8D, 0xE5, // STR R1, [SP,#8+var_8] + 0x04, 0x00, 0x9D, 0xE5, // LDR R0, [SP,#8+var_4] + 0x04, 0x10, 0x9D, 0xE5, // LDR R1, [SP,#8+var_4] + 0x00, 0x20, 0x9D, 0xE5, // LDR R2, [SP,#8+var_8] + 0x02, 0x10, 0x81, 0xE0, // ADD R1, R1, R2 + 0x01, 0x00, 0x00, 0xEB, // BL __clear_cache + 0x0B, 0xD0, 0xA0, 0xE1, // MOV SP, R11 + 0x00, 0x88, 0xBD, 0xE8, // POP {R11,PC} + + // __clear_cache ; CODE XREF: j___clear_cache+8鈫慾 + 0x80, 0x00, 0x2D, 0xE9, // PUSH { R7 } + 0x02, 0x70, 0x00, 0xE3, 0x0F, 0x70, 0x40, 0xE3, // MOV R7, #0xF0002 + 0x00, 0x20, 0xA0, 0xE3, // MOV R2, #0 + 0x00, 0x00, 0x00, 0xEF, // SVC 0 + 0x80, 0x00, 0xBD, 0xE8, // POP {R7} + 0x1E, 0xFF, 0x2F, 0xE1, // BX LR + }; + + private static byte[] s_flush_icache_arm64 = new byte[] // X0: code, W1: size + { + // void cdecl mono_arch_flush_icache (guint8 *code, gint size) + 0xFF, 0xC3, 0x00, 0xD1, // SUB SP, SP, #0x30 + 0xE8, 0x03, 0x7E, 0xB2, // MOV X8, #4 + 0xE0, 0x17, 0x00, 0xF9, // STR X0, [SP,#0x30+var_8] + 0xE1, 0x27, 0x00, 0xB9, // STR W1, [SP,#0x30+var_C] + 0xE0, 0x17, 0x40, 0xF9, // LDR X0, [SP,#0x30+var_8] + 0xE9, 0x27, 0x80, 0xB9, // LDRSW X9, [SP,#0x30+var_C] + 0x09, 0x00, 0x09, 0x8B, // ADD X9, X0, X9 + 0xE9, 0x0F, 0x00, 0xF9, // STR X9, [SP,#0x30+var_18] + 0xE8, 0x07, 0x00, 0xF9, // STR X8, [SP,#0x30+var_28] + 0xE8, 0x03, 0x00, 0xF9, // STR X8, [SP,#0x30+var_30] + 0xE8, 0x17, 0x40, 0xF9, // LDR X8, [SP,#0x30+var_8] + 0x08, 0xF5, 0x7E, 0x92, // AND X8, X8, #0xFFFFFFFFFFFFFFFC + 0xE8, 0x0B, 0x00, 0xF9, // STR X8, [SP,#0x30+var_20] + + // loc_590 ; CODE XREF: mono_arch_flush_icache(uchar*, int)+58鈫搄 + 0xE8, 0x0B, 0x40, 0xF9, // LDR X8, [SP,#0x30+var_20] + 0xE9, 0x0F, 0x40, 0xF9, // LDR X9, [SP,#0x30+var_18] + 0x1F, 0x01, 0x09, 0xEB, // CMP X8, X9 + 0xE2, 0x00, 0x00, 0x54, // B.CS loc_5B8 + 0xE8, 0x0B, 0x40, 0xF9, // LDR X8, [SP,#0x30+var_20] + 0x28, 0x7E, 0x0B, 0xD5, // SYS #3, c7, c14, #1, X8 + 0xE8, 0x0B, 0x40, 0xF9, // LDR X8, [SP,#0x30+var_20] + 0x08, 0x11, 0x00, 0x91, // ADD X8, X8, #4 + 0xE8, 0x0B, 0x00, 0xF9, // STR X8, [SP,#0x30+var_20] + 0xF7, 0xFF, 0xFF, 0x17, // B loc_590 + // ; --------------------------------------------------------------------------- + + // loc_5B8 ; CODE XREF: mono_arch_flush_icache(uchar *, int)+40鈫慾 + 0x9F, 0x3B, 0x03, 0xD5, // DSB ISH + 0xE8, 0x17, 0x40, 0xF9, // LDR X8, [SP,#0x30+var_8] + 0x08, 0xF5, 0x7E, 0x92, // AND X8, X8, #0xFFFFFFFFFFFFFFFC + 0xE8, 0x0B, 0x00, 0xF9, // STR X8, [SP,#0x30+var_20] + + // loc_5C8 ; CODE XREF: mono_arch_flush_icache(uchar *, int)+90鈫搄 + 0xE8, 0x0B, 0x40, 0xF9, // LDR X8, [SP,#0x30+var_20] + 0xE9, 0x0F, 0x40, 0xF9, // LDR X9, [SP,#0x30+var_18] + 0x1F, 0x01, 0x09, 0xEB, // CMP X8, X9 + 0xE2, 0x00, 0x00, 0x54, // B.CS loc_5F0 + 0xE8, 0x0B, 0x40, 0xF9, // LDR X8, [SP,#0x30+var_20] + 0x28, 0x75, 0x0B, 0xD5, // SYS #3, c7, c5, #1, X8 + 0xE8, 0x0B, 0x40, 0xF9, // LDR X8, [SP,#0x30+var_20] + 0x08, 0x11, 0x00, 0x91, // ADD X8, X8, #4 + 0xE8, 0x0B, 0x00, 0xF9, // STR X8, [SP,#0x30+var_20] + 0xF7, 0xFF, 0xFF, 0x17, // B loc_5C8 + // ; --------------------------------------------------------------------------- + + // loc_5F0 ; CODE XREF: mono_arch_flush_icache(uchar *, int)+78鈫慾 + 0x9F, 0x3B, 0x03, 0xD5, // DSB ISH + 0xDF, 0x3F, 0x03, 0xD5, // ISB + 0xFF, 0xC3, 0x00, 0x91, // ADD SP, SP, #0x30 ; '0' + 0xC0, 0x03, 0x5F, 0xD6, // RET + }; + + +#if UNITY_STANDALONE_WIN || UNITY_EDITOR_WIN + [Flags] + public enum Protection + { + PAGE_NOACCESS = 0x01, + PAGE_READONLY = 0x02, + PAGE_READWRITE = 0x04, + PAGE_WRITECOPY = 0x08, + PAGE_EXECUTE = 0x10, + PAGE_EXECUTE_READ = 0x20, + PAGE_EXECUTE_READWRITE = 0x40, + PAGE_EXECUTE_WRITECOPY = 0x80, + PAGE_GUARD = 0x100, + PAGE_NOCACHE = 0x200, + PAGE_WRITECOMBINE = 0x400 + } + + [DllImport("kernel32")] + public static extern bool VirtualProtect(IntPtr lpAddress, uint dwSize, Protection flNewProtect, out uint lpflOldProtect); + +#else + [Flags] + public enum MmapProts : int { + PROT_READ = 0x1, + PROT_WRITE = 0x2, + PROT_EXEC = 0x4, + PROT_NONE = 0x0, + PROT_GROWSDOWN = 0x01000000, + PROT_GROWSUP = 0x02000000, + } + + [DllImport("libc", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + private static extern int mprotect(IntPtr start, IntPtr len, MmapProts prot); + + public static unsafe void SetMemPerms(IntPtr start, ulong len, MmapProts prot) { + var requiredAddr = GetPageAlignedAddr(start.ToInt64(), (int)len); + long startPage = requiredAddr.Key; + long endPage = requiredAddr.Value; + + if (mprotect((IntPtr) startPage, (IntPtr) (endPage - startPage), prot) != 0) + throw new Exception($"mprotect with prot:{prot} fail!"); + } +#endif + } +} + +#endif \ No newline at end of file diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/HookUtils.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/HookUtils.cs.meta new file mode 100644 index 0000000..8ec4cb3 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/HookUtils.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e84139b42a6164e4c93ce4df1be6dcfb +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/HookUtils_OSX.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/HookUtils_OSX.cs new file mode 100644 index 0000000..4efdb0b --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/HookUtils_OSX.cs @@ -0,0 +1,116 @@ +锘�#if (UNITY_STANDALONE_OSX || UNITY_EDITOR_OSX) +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Text; +using UnityEngine; + +namespace MonoHook +{ + public static unsafe class HookUtils + { + static bool jit_write_protect_supported; + private static readonly long _Pagesize; + + + static HookUtils() + { + try + { + jit_write_protect_supported = pthread_jit_write_protect_supported_np() != 0; + } + catch { } + + PropertyInfo p_SystemPageSize = typeof(Environment).GetProperty("SystemPageSize"); + if (p_SystemPageSize == null) + throw new NotSupportedException("Unsupported runtime"); + _Pagesize = (int)p_SystemPageSize.GetValue(null, new object[0]); + } + + public static void MemCpy(void* pDst, void* pSrc, int len) + { + byte* pDst_ = (byte*)pDst; + byte* pSrc_ = (byte*)pSrc; + + for (int i = 0; i < len; i++) + *pDst_++ = *pSrc_++; + } + + public static void MemCpy_Jit(void* pDst, byte[] src) + { + if (!jit_write_protect_supported) + { + fixed(void * pSrc = &src[0]) + { + MemCpy(pDst, pSrc, src.Length); + } + + return; + } + + fixed(void * p = &src[0]) + { + memcpy_jit(new IntPtr(pDst), new IntPtr(p), src.Length); + } + } + + /// <summary> + /// set flags of address to `read write execute` + /// </summary> + public static void SetAddrFlagsToRWX(IntPtr ptr, int size) { } + + public static void FlushICache(void* code, int size) { } + + public static KeyValuePair<long, long> GetPageAlignedAddr(long code, int size) + { + long pagesize = _Pagesize; + long startPage = (code) & ~(pagesize - 1); + long endPage = (code + size + pagesize - 1) & ~(pagesize - 1); + return new KeyValuePair<long, long>(startPage, endPage); + } + + + const int PRINT_SPLIT = 4; + const int PRINT_COL_SIZE = PRINT_SPLIT * 4; + public static string HexToString(void* ptr, int size, int offset = 0) + { + Func<IntPtr, string> formatAddr = (IntPtr addr__) => IntPtr.Size == 4 ? $"0x{(uint)addr__:x}" : $"0x{(ulong)addr__:x}"; + + byte* addr = (byte*)ptr; + + StringBuilder sb = new StringBuilder(1024); + sb.AppendLine($"addr:{formatAddr(new IntPtr(addr))}"); + + addr += offset; + size += Math.Abs(offset); + + int count = 0; + while (true) + { + sb.Append($"\r\n{formatAddr(new IntPtr(addr + count))}: "); + for (int i = 1; i < PRINT_COL_SIZE + 1; i++) + { + if (count >= size) + goto END; + + sb.Append($"{*(addr + count):x2}"); + if (i % PRINT_SPLIT == 0) + sb.Append(" "); + + count++; + } + } + END:; + return sb.ToString(); + } + + [DllImport("pthread", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + private static extern int pthread_jit_write_protect_supported_np(); + + [DllImport("libMonoHookUtils_OSX", SetLastError = true, CallingConvention = CallingConvention.Cdecl)] + private static extern IntPtr memcpy_jit(IntPtr dst, IntPtr src, int len); + } +} + +#endif \ No newline at end of file diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/HookUtils_OSX.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/HookUtils_OSX.cs.meta new file mode 100644 index 0000000..6ecee49 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/HookUtils_OSX.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: efda6e010e5c6594081c4a62861d469f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/HybridCLRHooks.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/HybridCLRHooks.meta new file mode 100644 index 0000000..8169f8d --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/HybridCLRHooks.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d796fc01daee1964586621890988a5ae +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/HybridCLRHooks/CopyStrippedAOTAssembliesHook.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/HybridCLRHooks/CopyStrippedAOTAssembliesHook.cs new file mode 100644 index 0000000..d494552 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/HybridCLRHooks/CopyStrippedAOTAssembliesHook.cs @@ -0,0 +1,67 @@ +锘� +using System; +using System.Collections; +using System.Collections.Generic; +using System.Reflection; +using UnityEngine; +using UnityEditor; +using System.Runtime.CompilerServices; +using MonoHook; +using HybridCLR.Editor.BuildProcessors; +using System.IO; + +namespace HybridCLR.MonoHook +{ +#if UNITY_2021_1_OR_NEWER && !UNITY_2023_1_OR_NEWER + [InitializeOnLoad] + public class CopyStrippedAOTAssembliesHook + { + private static MethodHook _hook; + + static CopyStrippedAOTAssembliesHook() + { + if (_hook == null) + { + Type type = typeof(UnityEditor.EditorApplication).Assembly.GetType("UnityEditorInternal.AssemblyStripper"); + MethodInfo miTarget = type.GetMethod("StripAssembliesTo", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public); + + MethodInfo miReplacement = new StripAssembliesDel(OverrideStripAssembliesTo).Method; + MethodInfo miProxy = new StripAssembliesDel(StripAssembliesToProxy).Method; + + _hook = new MethodHook(miTarget, miReplacement, miProxy); + _hook.Install(); + } + } + + private delegate bool StripAssembliesDel(string outputFolder, out string output, out string error, IEnumerable<string> linkXmlFiles, object runInformation); + + private static bool OverrideStripAssembliesTo(string outputFolder, out string output, out string error, IEnumerable<string> linkXmlFiles, object runInformation) + { + bool result = StripAssembliesToProxy(outputFolder, out output, out error, linkXmlFiles, runInformation); + if (!result) + { + return false; + } + UnityEngine.Debug.Log($"== StripAssembliesTo outputDir:{outputFolder}"); + string outputStrippedDir = HybridCLR.Editor.SettingsUtil.GetAssembliesPostIl2CppStripDir(EditorUserBuildSettings.activeBuildTarget); + Directory.CreateDirectory(outputStrippedDir); + foreach (var aotDll in Directory.GetFiles(outputFolder, "*.dll")) + { + string dstFile = $"{outputStrippedDir}/{Path.GetFileName(aotDll)}"; + Debug.Log($"[RunAssemblyStripper] copy aot dll {aotDll} -> {dstFile}"); + File.Copy(aotDll, dstFile, true); + } + return result; + } + + [MethodImpl(MethodImplOptions.NoOptimization)] + private static bool StripAssembliesToProxy(string outputFolder, out string output, out string error, IEnumerable<string> linkXmlFiles, object runInformation) + { + Debug.LogError("== StripAssembliesToProxy =="); + output = ""; + error = ""; + return true; + } + } +#endif +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/HybridCLRHooks/CopyStrippedAOTAssembliesHook.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/HybridCLRHooks/CopyStrippedAOTAssembliesHook.cs.meta new file mode 100644 index 0000000..18542c3 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/HybridCLRHooks/CopyStrippedAOTAssembliesHook.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: cf42c4f20b8a1b94baa04a1a5c6b8beb +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/HybridCLRHooks/GetIl2CppFolderHook.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/HybridCLRHooks/GetIl2CppFolderHook.cs new file mode 100644 index 0000000..fbaf8bf --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/HybridCLRHooks/GetIl2CppFolderHook.cs @@ -0,0 +1,56 @@ +锘� +using System; +using System.Collections; +using System.Collections.Generic; +using System.Reflection; +using UnityEngine; +using UnityEditor; +using System.Runtime.CompilerServices; +using MonoHook; +using HybridCLR.Editor.BuildProcessors; +using System.IO; + +namespace HybridCLR.MonoHook +{ +#if UNITY_2022 || UNITY_2023_1_OR_NEWER + [InitializeOnLoad] + public class GetIl2CppFolderHook + { + private static MethodHook _hook; + + static GetIl2CppFolderHook() + { + if (_hook == null) + { + Type type = typeof(UnityEditor.EditorApplication).Assembly.GetType("UnityEditorInternal.IL2CPPUtils"); + MethodInfo miTarget = type.GetMethod("GetIl2CppFolder", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public, null, + new Type[] { typeof(bool).MakeByRefType() }, null); + + MethodInfo miReplacement = new StripAssembliesDel(OverrideMethod).Method; + MethodInfo miProxy = new StripAssembliesDel(PlaceHolderMethod).Method; + + _hook = new MethodHook(miTarget, miReplacement, miProxy); + _hook.Install(); + } + } + + private delegate string StripAssembliesDel(out bool isDevelopmentLocation); + + private static string OverrideMethod(out bool isDevelopmentLocation) + { + //Debug.Log("[GetIl2CppFolderHook] OverrideMethod"); + string result = PlaceHolderMethod(out isDevelopmentLocation); + isDevelopmentLocation = false; + return result; + } + + [MethodImpl(MethodImplOptions.NoOptimization)] + private static string PlaceHolderMethod(out bool isDevelopmentLocation) + { + Debug.LogError("[GetIl2CppFolderHook] PlaceHolderMethod"); + isDevelopmentLocation = false; + return null; + } + } +#endif +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/HybridCLRHooks/GetIl2CppFolderHook.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/HybridCLRHooks/GetIl2CppFolderHook.cs.meta new file mode 100644 index 0000000..bcde7d8 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/HybridCLRHooks/GetIl2CppFolderHook.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 96c2bc28db69e1644892219abef3d4b5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/HybridCLRHooks/PatchScriptingAssembliesJsonHook.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/HybridCLRHooks/PatchScriptingAssembliesJsonHook.cs new file mode 100644 index 0000000..c912756 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/HybridCLRHooks/PatchScriptingAssembliesJsonHook.cs @@ -0,0 +1,74 @@ +锘� +using System; +using System.Collections; +using System.Collections.Generic; +using System.Reflection; +using UnityEngine; +using UnityEditor; +using System.Runtime.CompilerServices; +using MonoHook; +using HybridCLR.Editor.BuildProcessors; +using System.IO; + +namespace HybridCLR.MonoHook +{ +#if UNITY_2021_1_OR_NEWER && (UNITY_WEBGL || UNITY_WEIXINMINIGAME) + [InitializeOnLoad] + public class PatchScriptingAssembliesJsonHook + { + private static MethodHook _hook; + + static PatchScriptingAssembliesJsonHook() + { + if (_hook == null) + { + Type type = typeof(UnityEditor.EditorApplication); + MethodInfo miTarget = type.GetMethod("BuildMainWindowTitle", BindingFlags.Static | BindingFlags.NonPublic); + + MethodInfo miReplacement = new Func<string>(BuildMainWindowTitle).Method; + MethodInfo miProxy = new Func<string>(BuildMainWindowTitleProxy).Method; + + _hook = new MethodHook(miTarget, miReplacement, miProxy); + _hook.Install(); + } + } + + private static string BuildMainWindowTitle() + { + var cacheDir = $"{Application.dataPath}/../Library/PlayerDataCache"; + if (Directory.Exists(cacheDir)) + { + foreach (var tempJsonPath in Directory.GetDirectories(cacheDir, "*", SearchOption.TopDirectoryOnly)) + { + string dirName = Path.GetFileName(tempJsonPath); + #if UNITY_WEIXINMINIGAME + if (!dirName.Contains("WeixinMiniGame")) + { + continue; + } +#else + if (!dirName.Contains("WebGL")) + { + continue; + } +#endif + + var patcher = new PatchScriptingAssemblyList(); + patcher.PathScriptingAssembilesFile(tempJsonPath); + } + } + + string newTitle = BuildMainWindowTitleProxy(); + return newTitle; + } + + [MethodImpl(MethodImplOptions.NoOptimization)] + private static string BuildMainWindowTitleProxy() + { + // 涓烘弧瓒矼onoHook瑕佹眰鐨勬渶灏忎唬鐮侀暱搴﹁�岀壒鍦板姞鍏ョ殑鏃犵敤濉厖浠g爜锛� + UnityEngine.Debug.Log(12345.ToString()); + return string.Empty; + } + } +#endif +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/HybridCLRHooks/PatchScriptingAssembliesJsonHook.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/HybridCLRHooks/PatchScriptingAssembliesJsonHook.cs.meta new file mode 100644 index 0000000..ccf939f --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/HybridCLRHooks/PatchScriptingAssembliesJsonHook.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: cc89a9041ab48ac41975fbd1e00b9b98 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/LDasm.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/LDasm.cs new file mode 100644 index 0000000..d87ab91 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/LDasm.cs @@ -0,0 +1,903 @@ +锘縰sing System; +using System.Runtime.InteropServices; + +namespace DotNetDetour +{ + /// <summary> + /// 鐢ㄤ簬璁$畻姹囩紪鎸囦护闀垮害锛屼娇鐢ㄧ殑鏄疊lackBone鐨凩Dasm.c涓殑绠楁硶锛屾垜鎶婁粬缈昏瘧鎴怌#浜� + /// </summary> + public unsafe class LDasm + { + const int F_INVALID = 0x01; + const int F_PREFIX = 0x02; + const int F_REX = 0x04; + const int F_MODRM = 0x08; + const int F_SIB = 0x10; + const int F_DISP = 0x20; + const int F_IMM = 0x40; + const int F_RELATIVE = 0x80; + + const int OP_NONE = 0x00; + const int OP_INVALID = 0x80; + + const int OP_DATA_I8 = 0x01; + const int OP_DATA_I16 = 0x02; + const int OP_DATA_I16_I32 = 0x04; + const int OP_DATA_I16_I32_I64 = 0x08; + const int OP_EXTENDED = 0x10; + const int OP_RELATIVE = 0x20; + const int OP_MODRM = 0x40; + const int OP_PREFIX = 0x80; + + struct ldasm_data + { + public byte flags; + public byte rex; + public byte modrm; + public byte sib; + public byte opcd_offset; + public byte opcd_size; + public byte disp_offset; + public byte disp_size; + public byte imm_offset; + public byte imm_size; + } + + static byte[] flags_table = + { + /* 00 */ OP_MODRM, + /* 01 */ OP_MODRM, + /* 02 */ OP_MODRM, + /* 03 */ OP_MODRM, + /* 04 */ OP_DATA_I8, + /* 05 */ OP_DATA_I16_I32, + /* 06 */ OP_NONE, + /* 07 */ OP_NONE, + /* 08 */ OP_MODRM, + /* 09 */ OP_MODRM, + /* 0A */ OP_MODRM, + /* 0B */ OP_MODRM, + /* 0C */ OP_DATA_I8, + /* 0D */ OP_DATA_I16_I32, + /* 0E */ OP_NONE, + /* 0F */ OP_NONE, + + /* 10 */ OP_MODRM, + /* 11 */ OP_MODRM, + /* 12 */ OP_MODRM, + /* 13 */ OP_MODRM, + /* 14 */ OP_DATA_I8, + /* 15 */ OP_DATA_I16_I32, + /* 16 */ OP_NONE, + /* 17 */ OP_NONE, + /* 18 */ OP_MODRM, + /* 19 */ OP_MODRM, + /* 1A */ OP_MODRM, + /* 1B */ OP_MODRM, + /* 1C */ OP_DATA_I8, + /* 1D */ OP_DATA_I16_I32, + /* 1E */ OP_NONE, + /* 1F */ OP_NONE, + + /* 20 */ OP_MODRM, + /* 21 */ OP_MODRM, + /* 22 */ OP_MODRM, + /* 23 */ OP_MODRM, + /* 24 */ OP_DATA_I8, + /* 25 */ OP_DATA_I16_I32, + /* 26 */ OP_PREFIX, + /* 27 */ OP_NONE, + /* 28 */ OP_MODRM, + /* 29 */ OP_MODRM, + /* 2A */ OP_MODRM, + /* 2B */ OP_MODRM, + /* 2C */ OP_DATA_I8, + /* 2D */ OP_DATA_I16_I32, + /* 2E */ OP_PREFIX, + /* 2F */ OP_NONE, + + /* 30 */ OP_MODRM, + /* 31 */ OP_MODRM, + /* 32 */ OP_MODRM, + /* 33 */ OP_MODRM, + /* 34 */ OP_DATA_I8, + /* 35 */ OP_DATA_I16_I32, + /* 36 */ OP_PREFIX, + /* 37 */ OP_NONE, + /* 38 */ OP_MODRM, + /* 39 */ OP_MODRM, + /* 3A */ OP_MODRM, + /* 3B */ OP_MODRM, + /* 3C */ OP_DATA_I8, + /* 3D */ OP_DATA_I16_I32, + /* 3E */ OP_PREFIX, + /* 3F */ OP_NONE, + + /* 40 */ OP_NONE, + /* 41 */ OP_NONE, + /* 42 */ OP_NONE, + /* 43 */ OP_NONE, + /* 44 */ OP_NONE, + /* 45 */ OP_NONE, + /* 46 */ OP_NONE, + /* 47 */ OP_NONE, + /* 48 */ OP_NONE, + /* 49 */ OP_NONE, + /* 4A */ OP_NONE, + /* 4B */ OP_NONE, + /* 4C */ OP_NONE, + /* 4D */ OP_NONE, + /* 4E */ OP_NONE, + /* 4F */ OP_NONE, + + /* 50 */ OP_NONE, + /* 51 */ OP_NONE, + /* 52 */ OP_NONE, + /* 53 */ OP_NONE, + /* 54 */ OP_NONE, + /* 55 */ OP_NONE, + /* 56 */ OP_NONE, + /* 57 */ OP_NONE, + /* 58 */ OP_NONE, + /* 59 */ OP_NONE, + /* 5A */ OP_NONE, + /* 5B */ OP_NONE, + /* 5C */ OP_NONE, + /* 5D */ OP_NONE, + /* 5E */ OP_NONE, + /* 5F */ OP_NONE, + /* 60 */ OP_NONE, + + /* 61 */ OP_NONE, + /* 62 */ OP_MODRM, + /* 63 */ OP_MODRM, + /* 64 */ OP_PREFIX, + /* 65 */ OP_PREFIX, + /* 66 */ OP_PREFIX, + /* 67 */ OP_PREFIX, + /* 68 */ OP_DATA_I16_I32, + /* 69 */ OP_MODRM | OP_DATA_I16_I32, + /* 6A */ OP_DATA_I8, + /* 6B */ OP_MODRM | OP_DATA_I8, + /* 6C */ OP_NONE, + /* 6D */ OP_NONE, + /* 6E */ OP_NONE, + /* 6F */ OP_NONE, + + /* 70 */ OP_RELATIVE | OP_DATA_I8, + /* 71 */ OP_RELATIVE | OP_DATA_I8, + /* 72 */ OP_RELATIVE | OP_DATA_I8, + /* 73 */ OP_RELATIVE | OP_DATA_I8, + /* 74 */ OP_RELATIVE | OP_DATA_I8, + /* 75 */ OP_RELATIVE | OP_DATA_I8, + /* 76 */ OP_RELATIVE | OP_DATA_I8, + /* 77 */ OP_RELATIVE | OP_DATA_I8, + /* 78 */ OP_RELATIVE | OP_DATA_I8, + /* 79 */ OP_RELATIVE | OP_DATA_I8, + /* 7A */ OP_RELATIVE | OP_DATA_I8, + /* 7B */ OP_RELATIVE | OP_DATA_I8, + /* 7C */ OP_RELATIVE | OP_DATA_I8, + /* 7D */ OP_RELATIVE | OP_DATA_I8, + /* 7E */ OP_RELATIVE | OP_DATA_I8, + /* 7F */ OP_RELATIVE | OP_DATA_I8, + + /* 80 */ OP_MODRM | OP_DATA_I8, + /* 81 */ OP_MODRM | OP_DATA_I16_I32, + /* 82 */ OP_MODRM | OP_DATA_I8, + /* 83 */ OP_MODRM | OP_DATA_I8, + /* 84 */ OP_MODRM, + /* 85 */ OP_MODRM, + /* 86 */ OP_MODRM, + /* 87 */ OP_MODRM, + /* 88 */ OP_MODRM, + /* 89 */ OP_MODRM, + /* 8A */ OP_MODRM, + /* 8B */ OP_MODRM, + /* 8C */ OP_MODRM, + /* 8D */ OP_MODRM, + /* 8E */ OP_MODRM, + /* 8F */ OP_MODRM, + + /* 90 */ OP_NONE, + /* 91 */ OP_NONE, + /* 92 */ OP_NONE, + /* 93 */ OP_NONE, + /* 94 */ OP_NONE, + /* 95 */ OP_NONE, + /* 96 */ OP_NONE, + /* 97 */ OP_NONE, + /* 98 */ OP_NONE, + /* 99 */ OP_NONE, + /* 9A */ OP_DATA_I16 | OP_DATA_I16_I32, + /* 9B */ OP_NONE, + /* 9C */ OP_NONE, + /* 9D */ OP_NONE, + /* 9E */ OP_NONE, + /* 9F */ OP_NONE, + + /* A0 */ OP_DATA_I8, + /* A1 */ OP_DATA_I16_I32_I64, + /* A2 */ OP_DATA_I8, + /* A3 */ OP_DATA_I16_I32_I64, + /* A4 */ OP_NONE, + /* A5 */ OP_NONE, + /* A6 */ OP_NONE, + /* A7 */ OP_NONE, + /* A8 */ OP_DATA_I8, + /* A9 */ OP_DATA_I16_I32, + /* AA */ OP_NONE, + /* AB */ OP_NONE, + /* AC */ OP_NONE, + /* AD */ OP_NONE, + /* AE */ OP_NONE, + /* AF */ OP_NONE, + + /* B0 */ OP_DATA_I8, + /* B1 */ OP_DATA_I8, + /* B2 */ OP_DATA_I8, + /* B3 */ OP_DATA_I8, + /* B4 */ OP_DATA_I8, + /* B5 */ OP_DATA_I8, + /* B6 */ OP_DATA_I8, + /* B7 */ OP_DATA_I8, + /* B8 */ OP_DATA_I16_I32_I64, + /* B9 */ OP_DATA_I16_I32_I64, + /* BA */ OP_DATA_I16_I32_I64, + /* BB */ OP_DATA_I16_I32_I64, + /* BC */ OP_DATA_I16_I32_I64, + /* BD */ OP_DATA_I16_I32_I64, + /* BE */ OP_DATA_I16_I32_I64, + /* BF */ OP_DATA_I16_I32_I64, + + /* C0 */ OP_MODRM | OP_DATA_I8, + /* C1 */ OP_MODRM | OP_DATA_I8, + /* C2 */ OP_DATA_I16, + /* C3 */ OP_NONE, + /* C4 */ OP_MODRM, + /* C5 */ OP_MODRM, + /* C6 */ OP_MODRM | OP_DATA_I8, + /* C7 */ OP_MODRM | OP_DATA_I16_I32, + /* C8 */ OP_DATA_I8 | OP_DATA_I16, + /* C9 */ OP_NONE, + /* CA */ OP_DATA_I16, + /* CB */ OP_NONE, + /* CC */ OP_NONE, + /* CD */ OP_DATA_I8, + /* CE */ OP_NONE, + /* CF */ OP_NONE, + + /* D0 */ OP_MODRM, + /* D1 */ OP_MODRM, + /* D2 */ OP_MODRM, + /* D3 */ OP_MODRM, + /* D4 */ OP_DATA_I8, + /* D5 */ OP_DATA_I8, + /* D6 */ OP_NONE, + /* D7 */ OP_NONE, + /* D8 */ OP_MODRM, + /* D9 */ OP_MODRM, + /* DA */ OP_MODRM, + /* DB */ OP_MODRM, + /* DC */ OP_MODRM, + /* DD */ OP_MODRM, + /* DE */ OP_MODRM, + /* DF */ OP_MODRM, + + /* E0 */ OP_RELATIVE | OP_DATA_I8, + /* E1 */ OP_RELATIVE | OP_DATA_I8, + /* E2 */ OP_RELATIVE | OP_DATA_I8, + /* E3 */ OP_RELATIVE | OP_DATA_I8, + /* E4 */ OP_DATA_I8, + /* E5 */ OP_DATA_I8, + /* E6 */ OP_DATA_I8, + /* E7 */ OP_DATA_I8, + /* E8 */ OP_RELATIVE | OP_DATA_I16_I32, + /* E9 */ OP_RELATIVE | OP_DATA_I16_I32, + /* EA */ OP_DATA_I16 | OP_DATA_I16_I32, + /* EB */ OP_RELATIVE | OP_DATA_I8, + /* EC */ OP_NONE, + /* ED */ OP_NONE, + /* EE */ OP_NONE, + /* EF */ OP_NONE, + + /* F0 */ OP_PREFIX, + /* F1 */ OP_NONE, + /* F2 */ OP_PREFIX, + /* F3 */ OP_PREFIX, + /* F4 */ OP_NONE, + /* F5 */ OP_NONE, + /* F6 */ OP_MODRM, + /* F7 */ OP_MODRM, + /* F8 */ OP_NONE, + /* F9 */ OP_NONE, + /* FA */ OP_NONE, + /* FB */ OP_NONE, + /* FC */ OP_NONE, + /* FD */ OP_NONE, + /* FE */ OP_MODRM, + /* FF */ OP_MODRM + }; + + static byte[] flags_table_ex = + { + /* 0F00 */ OP_MODRM, + /* 0F01 */ OP_MODRM, + /* 0F02 */ OP_MODRM, + /* 0F03 */ OP_MODRM, + /* 0F04 */ OP_INVALID, + /* 0F05 */ OP_NONE, + /* 0F06 */ OP_NONE, + /* 0F07 */ OP_NONE, + /* 0F08 */ OP_NONE, + /* 0F09 */ OP_NONE, + /* 0F0A */ OP_INVALID, + /* 0F0B */ OP_NONE, + /* 0F0C */ OP_INVALID, + /* 0F0D */ OP_MODRM, + /* 0F0E */ OP_INVALID, + /* 0F0F */ OP_MODRM | OP_DATA_I8, //3Dnow + + /* 0F10 */ OP_MODRM, + /* 0F11 */ OP_MODRM, + /* 0F12 */ OP_MODRM, + /* 0F13 */ OP_MODRM, + /* 0F14 */ OP_MODRM, + /* 0F15 */ OP_MODRM, + /* 0F16 */ OP_MODRM, + /* 0F17 */ OP_MODRM, + /* 0F18 */ OP_MODRM, + /* 0F19 */ OP_INVALID, + /* 0F1A */ OP_INVALID, + /* 0F1B */ OP_INVALID, + /* 0F1C */ OP_INVALID, + /* 0F1D */ OP_INVALID, + /* 0F1E */ OP_INVALID, + /* 0F1F */ OP_NONE, + + /* 0F20 */ OP_MODRM, + /* 0F21 */ OP_MODRM, + /* 0F22 */ OP_MODRM, + /* 0F23 */ OP_MODRM, + /* 0F24 */ OP_MODRM | OP_EXTENDED, //SSE5 + /* 0F25 */ OP_INVALID, + /* 0F26 */ OP_MODRM, + /* 0F27 */ OP_INVALID, + /* 0F28 */ OP_MODRM, + /* 0F29 */ OP_MODRM, + /* 0F2A */ OP_MODRM, + /* 0F2B */ OP_MODRM, + /* 0F2C */ OP_MODRM, + /* 0F2D */ OP_MODRM, + /* 0F2E */ OP_MODRM, + /* 0F2F */ OP_MODRM, + + /* 0F30 */ OP_NONE, + /* 0F31 */ OP_NONE, + /* 0F32 */ OP_NONE, + /* 0F33 */ OP_NONE, + /* 0F34 */ OP_NONE, + /* 0F35 */ OP_NONE, + /* 0F36 */ OP_INVALID, + /* 0F37 */ OP_NONE, + /* 0F38 */ OP_MODRM | OP_EXTENDED, + /* 0F39 */ OP_INVALID, + /* 0F3A */ OP_MODRM | OP_EXTENDED | OP_DATA_I8, + /* 0F3B */ OP_INVALID, + /* 0F3C */ OP_INVALID, + /* 0F3D */ OP_INVALID, + /* 0F3E */ OP_INVALID, + /* 0F3F */ OP_INVALID, + + /* 0F40 */ OP_MODRM, + /* 0F41 */ OP_MODRM, + /* 0F42 */ OP_MODRM, + /* 0F43 */ OP_MODRM, + /* 0F44 */ OP_MODRM, + /* 0F45 */ OP_MODRM, + /* 0F46 */ OP_MODRM, + /* 0F47 */ OP_MODRM, + /* 0F48 */ OP_MODRM, + /* 0F49 */ OP_MODRM, + /* 0F4A */ OP_MODRM, + /* 0F4B */ OP_MODRM, + /* 0F4C */ OP_MODRM, + /* 0F4D */ OP_MODRM, + /* 0F4E */ OP_MODRM, + /* 0F4F */ OP_MODRM, + + /* 0F50 */ OP_MODRM, + /* 0F51 */ OP_MODRM, + /* 0F52 */ OP_MODRM, + /* 0F53 */ OP_MODRM, + /* 0F54 */ OP_MODRM, + /* 0F55 */ OP_MODRM, + /* 0F56 */ OP_MODRM, + /* 0F57 */ OP_MODRM, + /* 0F58 */ OP_MODRM, + /* 0F59 */ OP_MODRM, + /* 0F5A */ OP_MODRM, + /* 0F5B */ OP_MODRM, + /* 0F5C */ OP_MODRM, + /* 0F5D */ OP_MODRM, + /* 0F5E */ OP_MODRM, + /* 0F5F */ OP_MODRM, + + /* 0F60 */ OP_MODRM, + /* 0F61 */ OP_MODRM, + /* 0F62 */ OP_MODRM, + /* 0F63 */ OP_MODRM, + /* 0F64 */ OP_MODRM, + /* 0F65 */ OP_MODRM, + /* 0F66 */ OP_MODRM, + /* 0F67 */ OP_MODRM, + /* 0F68 */ OP_MODRM, + /* 0F69 */ OP_MODRM, + /* 0F6A */ OP_MODRM, + /* 0F6B */ OP_MODRM, + /* 0F6C */ OP_MODRM, + /* 0F6D */ OP_MODRM, + /* 0F6E */ OP_MODRM, + /* 0F6F */ OP_MODRM, + + /* 0F70 */ OP_MODRM | OP_DATA_I8, + /* 0F71 */ OP_MODRM | OP_DATA_I8, + /* 0F72 */ OP_MODRM | OP_DATA_I8, + /* 0F73 */ OP_MODRM | OP_DATA_I8, + /* 0F74 */ OP_MODRM, + /* 0F75 */ OP_MODRM, + /* 0F76 */ OP_MODRM, + /* 0F77 */ OP_NONE, + /* 0F78 */ OP_MODRM, + /* 0F79 */ OP_MODRM, + /* 0F7A */ OP_INVALID, + /* 0F7B */ OP_INVALID, + /* 0F7C */ OP_MODRM, + /* 0F7D */ OP_MODRM, + /* 0F7E */ OP_MODRM, + /* 0F7F */ OP_MODRM, + + /* 0F80 */ OP_RELATIVE | OP_DATA_I16_I32, + /* 0F81 */ OP_RELATIVE | OP_DATA_I16_I32, + /* 0F82 */ OP_RELATIVE | OP_DATA_I16_I32, + /* 0F83 */ OP_RELATIVE | OP_DATA_I16_I32, + /* 0F84 */ OP_RELATIVE | OP_DATA_I16_I32, + /* 0F85 */ OP_RELATIVE | OP_DATA_I16_I32, + /* 0F86 */ OP_RELATIVE | OP_DATA_I16_I32, + /* 0F87 */ OP_RELATIVE | OP_DATA_I16_I32, + /* 0F88 */ OP_RELATIVE | OP_DATA_I16_I32, + /* 0F89 */ OP_RELATIVE | OP_DATA_I16_I32, + /* 0F8A */ OP_RELATIVE | OP_DATA_I16_I32, + /* 0F8B */ OP_RELATIVE | OP_DATA_I16_I32, + /* 0F8C */ OP_RELATIVE | OP_DATA_I16_I32, + /* 0F8D */ OP_RELATIVE | OP_DATA_I16_I32, + /* 0F8E */ OP_RELATIVE | OP_DATA_I16_I32, + /* 0F8F */ OP_RELATIVE | OP_DATA_I16_I32, + + /* 0F90 */ OP_MODRM, + /* 0F91 */ OP_MODRM, + /* 0F92 */ OP_MODRM, + /* 0F93 */ OP_MODRM, + /* 0F94 */ OP_MODRM, + /* 0F95 */ OP_MODRM, + /* 0F96 */ OP_MODRM, + /* 0F97 */ OP_MODRM, + /* 0F98 */ OP_MODRM, + /* 0F99 */ OP_MODRM, + /* 0F9A */ OP_MODRM, + /* 0F9B */ OP_MODRM, + /* 0F9C */ OP_MODRM, + /* 0F9D */ OP_MODRM, + /* 0F9E */ OP_MODRM, + /* 0F9F */ OP_MODRM, + + /* 0FA0 */ OP_NONE, + /* 0FA1 */ OP_NONE, + /* 0FA2 */ OP_NONE, + /* 0FA3 */ OP_MODRM, + /* 0FA4 */ OP_MODRM | OP_DATA_I8, + /* 0FA5 */ OP_MODRM, + /* 0FA6 */ OP_INVALID, + /* 0FA7 */ OP_INVALID, + /* 0FA8 */ OP_NONE, + /* 0FA9 */ OP_NONE, + /* 0FAA */ OP_NONE, + /* 0FAB */ OP_MODRM, + /* 0FAC */ OP_MODRM | OP_DATA_I8, + /* 0FAD */ OP_MODRM, + /* 0FAE */ OP_MODRM, + /* 0FAF */ OP_MODRM, + + /* 0FB0 */ OP_MODRM, + /* 0FB1 */ OP_MODRM, + /* 0FB2 */ OP_MODRM, + /* 0FB3 */ OP_MODRM, + /* 0FB4 */ OP_MODRM, + /* 0FB5 */ OP_MODRM, + /* 0FB6 */ OP_MODRM, + /* 0FB7 */ OP_MODRM, + /* 0FB8 */ OP_MODRM, + /* 0FB9 */ OP_MODRM, + /* 0FBA */ OP_MODRM | OP_DATA_I8, + /* 0FBB */ OP_MODRM, + /* 0FBC */ OP_MODRM, + /* 0FBD */ OP_MODRM, + /* 0FBE */ OP_MODRM, + /* 0FBF */ OP_MODRM, + + /* 0FC0 */ OP_MODRM, + /* 0FC1 */ OP_MODRM, + /* 0FC2 */ OP_MODRM | OP_DATA_I8, + /* 0FC3 */ OP_MODRM, + /* 0FC4 */ OP_MODRM | OP_DATA_I8, + /* 0FC5 */ OP_MODRM | OP_DATA_I8, + /* 0FC6 */ OP_MODRM | OP_DATA_I8, + /* 0FC7 */ OP_MODRM, + /* 0FC8 */ OP_NONE, + /* 0FC9 */ OP_NONE, + /* 0FCA */ OP_NONE, + /* 0FCB */ OP_NONE, + /* 0FCC */ OP_NONE, + /* 0FCD */ OP_NONE, + /* 0FCE */ OP_NONE, + /* 0FCF */ OP_NONE, + + /* 0FD0 */ OP_MODRM, + /* 0FD1 */ OP_MODRM, + /* 0FD2 */ OP_MODRM, + /* 0FD3 */ OP_MODRM, + /* 0FD4 */ OP_MODRM, + /* 0FD5 */ OP_MODRM, + /* 0FD6 */ OP_MODRM, + /* 0FD7 */ OP_MODRM, + /* 0FD8 */ OP_MODRM, + /* 0FD9 */ OP_MODRM, + /* 0FDA */ OP_MODRM, + /* 0FDB */ OP_MODRM, + /* 0FDC */ OP_MODRM, + /* 0FDD */ OP_MODRM, + /* 0FDE */ OP_MODRM, + /* 0FDF */ OP_MODRM, + + /* 0FE0 */ OP_MODRM, + /* 0FE1 */ OP_MODRM, + /* 0FE2 */ OP_MODRM, + /* 0FE3 */ OP_MODRM, + /* 0FE4 */ OP_MODRM, + /* 0FE5 */ OP_MODRM, + /* 0FE6 */ OP_MODRM, + /* 0FE7 */ OP_MODRM, + /* 0FE8 */ OP_MODRM, + /* 0FE9 */ OP_MODRM, + /* 0FEA */ OP_MODRM, + /* 0FEB */ OP_MODRM, + /* 0FEC */ OP_MODRM, + /* 0FED */ OP_MODRM, + /* 0FEE */ OP_MODRM, + /* 0FEF */ OP_MODRM, + + /* 0FF0 */ OP_MODRM, + /* 0FF1 */ OP_MODRM, + /* 0FF2 */ OP_MODRM, + /* 0FF3 */ OP_MODRM, + /* 0FF4 */ OP_MODRM, + /* 0FF5 */ OP_MODRM, + /* 0FF6 */ OP_MODRM, + /* 0FF7 */ OP_MODRM, + /* 0FF8 */ OP_MODRM, + /* 0FF9 */ OP_MODRM, + /* 0FFA */ OP_MODRM, + /* 0FFB */ OP_MODRM, + /* 0FFC */ OP_MODRM, + /* 0FFD */ OP_MODRM, + /* 0FFE */ OP_MODRM, + /* 0FFF */ OP_INVALID, + }; + + static byte cflags(byte op) + { + return flags_table[op]; + } + + static byte cflags_ex(byte op) + { + return flags_table_ex[op]; + } + + /// <summary> + /// 璁$畻澶т簬绛変簬 size 瀛楄妭鐨勬渶灏戞寚浠ょ殑闀垮害 + /// </summary> + /// <param name="code"></param> + /// <returns></returns> + public static uint SizeofMinNumByte(void* code, int size) + { + if (IsARM()) + return (uint)((size + 3) / 4) * 4; // 姝や负 jit 妯″紡涓嬬殑闀垮害锛屼笉鍐嶆敮鎸� thumb + + uint Length; + byte* pOpcode; + uint Result = 0; + ldasm_data data = new ldasm_data(); + bool is64 = IntPtr.Size == 8; + do + { + Length = ldasm(code, data, is64); + + pOpcode = (byte*)code + data.opcd_offset; + Result += Length; + if (Result >= size) + break; + if ((Length == 1) && (*pOpcode == 0xCC)) + break; + + code = (void*)((ulong)code + Length); + + } while (Length>0); + + return Result; + } + + static bool? s_isArm; + public static bool IsARM() + { + if(s_isArm.HasValue) + return s_isArm.Value; + + var arch = RuntimeInformation.ProcessArchitecture; + s_isArm = arch == Architecture.Arm || arch == Architecture.Arm64; + + return s_isArm.Value; + } + + public static bool IsArm32() + { + return IsARM() && IntPtr.Size == 4; + } + + public static bool IsArm64() + { + return IsARM() && IntPtr.Size == 8; + } + + static bool? s_isiOS; + public static bool IsiOS() + { + if(s_isiOS.HasValue) + return s_isiOS.Value; + + s_isiOS = UnityEngine.SystemInfo.operatingSystem.ToLower().Contains("ios"); + return s_isiOS.Value; + } + + static bool? s_isIL2CPP; + public static bool IsIL2CPP() + { + if (s_isIL2CPP.HasValue) + return s_isIL2CPP.Value; + + try + { + byte[] ilBody = typeof(LDasm).GetMethod("IsIL2CPP").GetMethodBody().GetILAsByteArray(); + if (ilBody == null || ilBody.Length == 0) + s_isIL2CPP = true; + else + s_isIL2CPP = false; + } + catch + { + s_isIL2CPP = true; + } + + return s_isIL2CPP.Value; + } + + public static bool IsThumb(IntPtr code) + { + return IsArm32() && ((long)code & 0x1) == 0x1; + } + + /// <summary> + /// 璁$畻 thumb 鎸囦护闀垮害 + /// </summary> + /// <param name="code"></param> + /// <param name="size"></param> + /// <returns></returns> + public static uint CalcARMThumbMinLen(void* code, int size) + { + uint len = 0; + + ushort* ins = (ushort*)code; + while (true) + { + if (len >= size) + return len; + + if (((*ins >> 13) & 3) == 3) + { + ins += 2; + len += 4; + } + else + { + ins++; + len += 2; + } + } + } + + static uint ldasm(void* code, ldasm_data ld, bool is64) + { + byte* p = (byte*)code; + byte s, op, f; + byte rexw, pr_66, pr_67; + + s = rexw = pr_66 = pr_67 = 0; + + /* dummy check */ + if ((int)code==0) + return 0; + + /* init output data */ + //memset(ld, 0, sizeof(ldasm_data)); + + /* phase 1: parse prefixies */ + while ((cflags(*p) & OP_PREFIX)!=0) + { + if (*p == 0x66) + pr_66 = 1; + if (*p == 0x67) + pr_67 = 1; + p++; s++; + ld.flags |= F_PREFIX; + if (s == 15) + { + ld.flags |= F_INVALID; + return s; + } + } + + /* parse REX prefix */ + if (is64 && *p >> 4 == 4) + { + ld.rex = *p; + rexw = (byte)((ld.rex >> 3) & 1); + ld.flags |= F_REX; + p++; s++; + } + + /* can be only one REX prefix */ + if (is64 && *p >> 4 == 4) + { + ld.flags |= F_INVALID; + s++; + return s; + } + + /* phase 2: parse opcode */ + ld.opcd_offset = (byte)(p - (byte*)code); + ld.opcd_size = 1; + op = *p++; s++; + + /* is 2 byte opcode? */ + if (op == 0x0F) + { + op = *p++; s++; + ld.opcd_size++; + f = cflags_ex(op); + if ((f & OP_INVALID)!=0) + { + ld.flags |= F_INVALID; + return s; + } + /* for SSE instructions */ + if ((f & OP_EXTENDED)!=0) + { + op = *p++; s++; + ld.opcd_size++; + } + } + else { + f = cflags(op); + /* pr_66 = pr_67 for opcodes A0-A3 */ + if (op >= 0xA0 && op <= 0xA3) + pr_66 = pr_67; + } + + /* phase 3: parse ModR/M, SIB and DISP */ + if ((f & OP_MODRM)!=0) + { + byte mod = (byte)(*p >> 6); + byte ro = (byte)((*p & 0x38) >> 3); + byte rm = (byte)(*p & 7); + + ld.modrm = *p++; s++; + ld.flags |= F_MODRM; + + /* in F6,F7 opcodes immediate data present if R/O == 0 */ + if (op == 0xF6 && (ro == 0 || ro == 1)) + f |= OP_DATA_I8; + if (op == 0xF7 && (ro == 0 || ro == 1)) + f |= OP_DATA_I16_I32_I64; + + /* is SIB byte exist? */ + if (mod != 3 && rm == 4 && !(!is64 && pr_67!=0)) + { + ld.sib = *p++; s++; + ld.flags |= F_SIB; + + /* if base == 5 and mod == 0 */ + if ((ld.sib & 7) == 5 && mod == 0) + { + ld.disp_size = 4; + } + } + + switch (mod) + { + case 0: + if (is64) + { + if (rm == 5) + { + ld.disp_size = 4; + if (is64) + ld.flags |= F_RELATIVE; + } + } + else if (pr_67!=0) + { + if (rm == 6) + ld.disp_size = 2; + } + else { + if (rm == 5) + ld.disp_size = 4; + } + break; + case 1: + ld.disp_size = 1; + break; + case 2: + if (is64) + ld.disp_size = 4; + else if (pr_67!=0) + ld.disp_size = 2; + else + ld.disp_size = 4; + break; + } + + if (ld.disp_size>0) + { + ld.disp_offset = (byte)(p - (byte*)code); + p += ld.disp_size; + s += ld.disp_size; + ld.flags |= F_DISP; + } + } + + /* phase 4: parse immediate data */ + if (rexw!=0 && (f & OP_DATA_I16_I32_I64)!=0) + ld.imm_size = 8; + else if ((f & OP_DATA_I16_I32)!=0 || (f & OP_DATA_I16_I32_I64)!=0) + ld.imm_size = (byte)(4 - (pr_66 << 1)); + + /* if exist, add OP_DATA_I16 and OP_DATA_I8 size */ + ld.imm_size += (byte)(f & 3); + + if ((ld.imm_size)!=0) + { + s += ld.imm_size; + ld.imm_offset = (byte)(p - (byte*)code); + ld.flags |= F_IMM; + if ((f & OP_RELATIVE)!=0) + ld.flags |= F_RELATIVE; + } + + /* instruction is too long */ + if (s > 15) + ld.flags |= F_INVALID; + + return s; + } + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/LDasm.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/LDasm.cs.meta new file mode 100644 index 0000000..969a5a1 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/LDasm.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3c561c9729c367e4fbef63f4ec56f268 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/MethodHook.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/MethodHook.cs new file mode 100644 index 0000000..2c7c862 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/MethodHook.cs @@ -0,0 +1,381 @@ +/* + Desc: 涓�涓彲浠ヨ繍琛屾椂 Hook Mono 鏂规硶鐨勫伐鍏凤紝璁╀綘鍙互鏃犻渶淇敼 UnityEditor.dll 绛夋枃浠跺氨鍙互閲嶅啓鍏跺嚱鏁板姛鑳� + Author: Misaka Mikoto + Github: https://github.com/Misaka-Mikoto-Tech/MonoHook + */ + +using DotNetDetour; +using System; +using System.Diagnostics; +using System.Reflection; +using System.Runtime.InteropServices; +using Unity.Collections.LowLevel.Unsafe; +#if UNITY_EDITOR +using UnityEditor; +#endif +using UnityEngine; +using System.Runtime.CompilerServices; + + +/* +>>>>>>> 鍘熷 UnityEditor.LogEntries.Clear 涓�鍨�(.net 4.x) +0000000000403A00 < | 55 | push rbp | +0000000000403A01 | 48 8B EC | mov rbp,rsp | +0000000000403A04 | 48 81 EC 80 00 00 00 | sub rsp,80 | +0000000000403A0B | 48 89 65 B0 | mov qword ptr ss:[rbp-50],rsp | +0000000000403A0F | 48 89 6D A8 | mov qword ptr ss:[rbp-58],rbp | +0000000000403A13 | 48 89 5D C8 | mov qword ptr ss:[rbp-38],rbx | << +0000000000403A17 | 48 89 75 D0 | mov qword ptr ss:[rbp-30],rsi | +0000000000403A1B | 48 89 7D D8 | mov qword ptr ss:[rbp-28],rdi | +0000000000403A1F | 4C 89 65 E0 | mov qword ptr ss:[rbp-20],r12 | +0000000000403A23 | 4C 89 6D E8 | mov qword ptr ss:[rbp-18],r13 | +0000000000403A27 | 4C 89 75 F0 | mov qword ptr ss:[rbp-10],r14 | +0000000000403A2B | 4C 89 7D F8 | mov qword ptr ss:[rbp-8],r15 | +0000000000403A2F | 49 BB 00 2D 1E 1A FE 7F 00 00 | mov r11,7FFE1A1E2D00 | +0000000000403A39 | 4C 89 5D B8 | mov qword ptr ss:[rbp-48],r11 | +0000000000403A3D | 49 BB 08 2D 1E 1A FE 7F 00 00 | mov r11,7FFE1A1E2D08 | + + +>>>>>>> 浜屽瀷(.net 2.x) +0000000000403E8F | 55 | push rbp | +0000000000403E90 | 48 8B EC | mov rbp,rsp | +0000000000403E93 | 48 83 EC 70 | sub rsp,70 | +0000000000403E97 | 48 89 65 C8 | mov qword ptr ss:[rbp-38],rsp | +0000000000403E9B | 48 89 5D B8 | mov qword ptr ss:[rbp-48],rbx | +0000000000403E9F | 48 89 6D C0 | mov qword ptr ss:[rbp-40],rbp | <<(16) +0000000000403EA3 | 48 89 75 F8 | mov qword ptr ss:[rbp-8],rsi | +0000000000403EA7 | 48 89 7D F0 | mov qword ptr ss:[rbp-10],rdi | +0000000000403EAB | 4C 89 65 D0 | mov qword ptr ss:[rbp-30],r12 | +0000000000403EAF | 4C 89 6D D8 | mov qword ptr ss:[rbp-28],r13 | +0000000000403EB3 | 4C 89 75 E0 | mov qword ptr ss:[rbp-20],r14 | +0000000000403EB7 | 4C 89 7D E8 | mov qword ptr ss:[rbp-18],r15 | +0000000000403EBB | 48 83 EC 20 | sub rsp,20 | +0000000000403EBF | 49 BB 18 3F 15 13 FE 7F 00 00 | mov r11,7FFE13153F18 | +0000000000403EC9 | 41 FF D3 | call r11 | +0000000000403ECC | 48 83 C4 20 | add rsp,20 | + +>>>>>>>>> arm64 +il2cpp:00000000003DE714 F5 0F 1D F8 STR X21, [SP,#-0x10+var_20]! | << absolute safe +il2cpp:00000000003DE718 F4 4F 01 A9 STP X20, X19, [SP,#0x20+var_10] | << may be safe +il2cpp:00000000003DE71C FD 7B 02 A9 STP X29, X30, [SP,#0x20+var_s0] | +il2cpp:00000000003DE720 FD 83 00 91 ADD X29, SP, #0x20 | +il2cpp:00000000003DE724 B5 30 00 B0 ADRP X21, #_ZZ62GameObject_SetActive_mCF1EEF2A314F3AE | << dangerous: relative instruction, can not be overwritten +il2cpp:00000000003DE728 A2 56 47 F9 LDR method, [X21,#_ZZ62GameObject_SetActive_mCF] ; | +il2cpp:00000000003DE72C F3 03 01 2A MOV W19, W1 | + */ + +namespace MonoHook +{ + /// <summary> + /// Hook 绫伙紝鐢ㄦ潵 Hook 鏌愪釜 C# 鏂规硶 + /// </summary> + public unsafe class MethodHook + { + public string tag; + public bool isHooked { get; private set; } + public bool isPlayModeHook { get; private set; } + + public MethodBase targetMethod { get; private set; } // 闇�瑕佽hook鐨勭洰鏍囨柟娉� + public MethodBase replacementMethod { get; private set; } // 琚玥ook鍚庣殑鏇夸唬鏂规硶 + public MethodBase proxyMethod { get; private set; } // 鐩爣鏂规硶鐨勪唬鐞嗘柟娉�(鍙互閫氳繃姝ゆ柟娉曡皟鐢ㄨhook鍚庣殑鍘熸柟娉�) + + private IntPtr _targetPtr; // 鐩爣鏂规硶琚� jit 鍚庣殑鍦板潃鎸囬拡 + private IntPtr _replacementPtr; + private IntPtr _proxyPtr; + + private CodePatcher _codePatcher; + +#if UNITY_EDITOR && !UNITY_2020_3_OR_NEWER + /// <summary> + /// call `MethodInfo.MethodHandle.GetFunctionPointer()` + /// will visit static class `UnityEditor.IMGUI.Controls.TreeViewGUI.Styles` and invoke its static constructor, + /// and init static filed `foldout`, but `GUISKin.current` is null now, + /// so we should wait until `GUISKin.current` has a valid value + /// </summary> + private static FieldInfo s_fi_GUISkin_current; +#endif + + static MethodHook() + { +#if UNITY_EDITOR && !UNITY_2020_3_OR_NEWER + s_fi_GUISkin_current = typeof(GUISkin).GetField("current", BindingFlags.Static | BindingFlags.NonPublic); +#endif + } + + /// <summary> + /// 鍒涘缓涓�涓� Hook + /// </summary> + /// <param name="targetMethod">闇�瑕佹浛鎹㈢殑鐩爣鏂规硶</param> + /// <param name="replacementMethod">鍑嗗濂界殑鏇挎崲鏂规硶</param> + /// <param name="proxyMethod">濡傛灉杩橀渶瑕佽皟鐢ㄥ師濮嬬洰鏍囨柟娉曪紝鍙互閫氳繃姝ゅ弬鏁扮殑鏂规硶璋冪敤锛屽鏋滀笉闇�瑕佸彲浠ュ~ null</param> + public MethodHook(MethodBase targetMethod, MethodBase replacementMethod, MethodBase proxyMethod, string data = "") + { + this.targetMethod = targetMethod; + this.replacementMethod = replacementMethod; + this.proxyMethod = proxyMethod; + this.tag = data; + + CheckMethod(); + } + + public void Install() + { + if (LDasm.IsiOS()) // iOS 涓嶆敮鎸佷慨鏀� code 鎵�鍦ㄥ尯鍩� page + return; + + if (isHooked) + return; + +#if UNITY_EDITOR && !UNITY_2020_3_OR_NEWER + if (s_fi_GUISkin_current.GetValue(null) != null) + DoInstall(); + else + EditorApplication.update += OnEditorUpdate; +#else + DoInstall(); +#endif + isPlayModeHook = Application.isPlaying; + } + + public void Uninstall() + { + if (!isHooked) + return; + + _codePatcher.RemovePatch(); + + isHooked = false; + HookPool.RemoveHooker(targetMethod); + } + + #region private + private void DoInstall() + { + if (targetMethod == null || replacementMethod == null) + throw new Exception("none of methods targetMethod or replacementMethod can be null"); + + HookPool.AddHook(targetMethod, this); + + if (_codePatcher == null) + { + if (GetFunctionAddr()) + { +#if ENABLE_HOOK_DEBUG + UnityEngine.Debug.Log($"Original [{targetMethod.DeclaringType.Name}.{targetMethod.Name}]: {HookUtils.HexToString(_targetPtr.ToPointer(), 64, -16)}"); + UnityEngine.Debug.Log($"Original [{replacementMethod.DeclaringType.Name}.{replacementMethod.Name}]: {HookUtils.HexToString(_replacementPtr.ToPointer(), 64, -16)}"); + if(proxyMethod != null) + UnityEngine.Debug.Log($"Original [{proxyMethod.DeclaringType.Name}.{proxyMethod.Name}]: {HookUtils.HexToString(_proxyPtr.ToPointer(), 64, -16)}"); +#endif + + CreateCodePatcher(); + _codePatcher.ApplyPatch(); + +#if ENABLE_HOOK_DEBUG + UnityEngine.Debug.Log($"New [{targetMethod.DeclaringType.Name}.{targetMethod.Name}]: {HookUtils.HexToString(_targetPtr.ToPointer(), 64, -16)}"); + UnityEngine.Debug.Log($"New [{replacementMethod.DeclaringType.Name}.{replacementMethod.Name}]: {HookUtils.HexToString(_replacementPtr.ToPointer(), 64, -16)}"); + if(proxyMethod != null) + UnityEngine.Debug.Log($"New [{proxyMethod.DeclaringType.Name}.{proxyMethod.Name}]: {HookUtils.HexToString(_proxyPtr.ToPointer(), 64, -16)}"); +#endif + } + } + + isHooked = true; + } + + private void CheckMethod() + { + if (targetMethod == null || replacementMethod == null) + throw new Exception("MethodHook:targetMethod and replacementMethod and proxyMethod can not be null"); + + string methodName = $"{targetMethod.DeclaringType.Name}.{targetMethod.Name}"; + if (targetMethod.IsAbstract) + throw new Exception($"WRANING: you can not hook abstract method [{methodName}]"); + +#if UNITY_EDITOR && !UNITY_2020_3_OR_NEWER + int minMethodBodySize = 10; + + { + if ((targetMethod.MethodImplementationFlags & MethodImplAttributes.InternalCall) != MethodImplAttributes.InternalCall) + { + int codeSize = targetMethod.GetMethodBody().GetILAsByteArray().Length; // GetMethodBody can not call on il2cpp + if (codeSize < minMethodBodySize) + UnityEngine.Debug.LogWarning($"WRANING: you can not hook method [{methodName}], cause its method body is too short({codeSize}), will random crash on IL2CPP release mode"); + } + } + + if(proxyMethod != null) + { + methodName = $"{proxyMethod.DeclaringType.Name}.{proxyMethod.Name}"; + int codeSize = proxyMethod.GetMethodBody().GetILAsByteArray().Length; + if (codeSize < minMethodBodySize) + UnityEngine.Debug.LogWarning($"WRANING: size of method body[{methodName}] is too short({codeSize}), will random crash on IL2CPP release mode, please fill some dummy code inside"); + + if ((proxyMethod.MethodImplementationFlags & MethodImplAttributes.NoOptimization) != MethodImplAttributes.NoOptimization) + throw new Exception($"WRANING: method [{methodName}] must has a Attribute `MethodImpl(MethodImplOptions.NoOptimization)` to prevent code call to this optimized by compiler(pass args by shared stack)"); + } +#endif + } + + private void CreateCodePatcher() + { + long addrOffset = Math.Abs(_targetPtr.ToInt64() - _proxyPtr.ToInt64()); + + if(_proxyPtr != IntPtr.Zero) + addrOffset = Math.Max(addrOffset, Math.Abs(_targetPtr.ToInt64() - _proxyPtr.ToInt64())); + + if (LDasm.IsARM()) + { + if (IntPtr.Size == 8) + _codePatcher = new CodePatcher_arm64_near(_targetPtr, _replacementPtr, _proxyPtr); + else if (addrOffset < ((1 << 25) - 1)) + _codePatcher = new CodePatcher_arm32_near(_targetPtr, _replacementPtr, _proxyPtr); + else if (addrOffset < ((1 << 27) - 1)) + _codePatcher = new CodePatcher_arm32_far(_targetPtr, _replacementPtr, _proxyPtr); + else + throw new Exception("address of target method and replacement method are too far, can not hook"); + } + else + { + if (IntPtr.Size == 8) + { + if(addrOffset < 0x7fffffff) // 2G + _codePatcher = new CodePatcher_x64_near(_targetPtr, _replacementPtr, _proxyPtr); + else + _codePatcher = new CodePatcher_x64_far(_targetPtr, _replacementPtr, _proxyPtr); + } + else + _codePatcher = new CodePatcher_x86(_targetPtr, _replacementPtr, _proxyPtr); + } + } + + /// <summary> + /// 鑾峰彇瀵瑰簲鍑芥暟jit鍚庣殑native code鐨勫湴鍧� + /// </summary> + private bool GetFunctionAddr() + { + _targetPtr = GetFunctionAddr(targetMethod); + _replacementPtr = GetFunctionAddr(replacementMethod); + _proxyPtr = GetFunctionAddr(proxyMethod); + + if (_targetPtr == IntPtr.Zero || _replacementPtr == IntPtr.Zero) + return false; + + if (proxyMethod != null && _proxyPtr == null) + return false; + + if(_replacementPtr == _targetPtr) + { + throw new Exception($"the addresses of target method {targetMethod.Name} and replacement method {replacementMethod.Name} can not be same"); + } + + if (LDasm.IsThumb(_targetPtr) || LDasm.IsThumb(_replacementPtr)) + { + throw new Exception("does not support thumb arch"); + } + + return true; + } + + + [StructLayout(LayoutKind.Sequential, Pack = 1)] // 濂藉儚鍦� IL2CPP 閲屾棤鏁� + private struct __ForCopy + { + public long __dummy; + public MethodBase method; + } + /// <summary> + /// 鑾峰彇鏂规硶鎸囦护鍦板潃 + /// </summary> + /// <param name="method"></param> + /// <returns></returns> + private IntPtr GetFunctionAddr(MethodBase method) + { + if (method == null) + return IntPtr.Zero; + + if (!LDasm.IsIL2CPP()) + return method.MethodHandle.GetFunctionPointer(); + else + { + /* + // System.Reflection.MonoMethod + typedef struct Il2CppReflectionMethod + { + Il2CppObject object; + const MethodInfo *method; + Il2CppString *name; + Il2CppReflectionType *reftype; + } Il2CppReflectionMethod; + + typedef Il2CppClass Il2CppVTable; + typedef struct Il2CppObject + { + union + { + Il2CppClass *klass; + Il2CppVTable *vtable; + }; + MonitorData *monitor; + } Il2CppObject; + + typedef struct MethodInfo + { + Il2CppMethodPointer methodPointer; // this is the pointer to native code of method + InvokerMethod invoker_method; + const char* name; + Il2CppClass *klass; + const Il2CppType *return_type; + const ParameterInfo* parameters; + // ... + } + */ + + __ForCopy __forCopy = new __ForCopy() { method = method }; + + long* ptr = &__forCopy.__dummy; + ptr++; // addr of _forCopy.method + + IntPtr methodAddr = IntPtr.Zero; + if (sizeof(IntPtr) == 8) + { + long methodDataAddr = *(long*)ptr; + byte* ptrData = (byte*)methodDataAddr + sizeof(IntPtr) * 2; // offset of Il2CppReflectionMethod::const MethodInfo *method; + + long methodPtr = 0; + methodPtr = *(long*)ptrData; + methodAddr = new IntPtr(*(long*)methodPtr); // MethodInfo::Il2CppMethodPointer methodPointer; + } + else + { + int methodDataAddr = *(int*)ptr; + byte* ptrData = (byte*)methodDataAddr + sizeof(IntPtr) * 2; // offset of Il2CppReflectionMethod::const MethodInfo *method; + + int methodPtr = 0; + methodPtr = *(int*)ptrData; + methodAddr = new IntPtr(*(int*)methodPtr); + } + return methodAddr; + } + } + +#if UNITY_EDITOR && !UNITY_2020_3_OR_NEWER + private void OnEditorUpdate() + { + if (s_fi_GUISkin_current.GetValue(null) != null) + { + try + { + DoInstall(); + } + finally + { + EditorApplication.update -= OnEditorUpdate; + } + } + } +#endif + + #endregion + } + +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/MethodHook.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/MethodHook.cs.meta new file mode 100644 index 0000000..007e62c --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/MethodHook.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: bd0b8071cf434d6498160259e3829980 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/Plugins.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/Plugins.meta new file mode 100644 index 0000000..1f7f284 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/Plugins.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 16b9dc031f67b4fe5ad79c230f75768c +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/Plugins/Utils.cpp b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/Plugins/Utils.cpp new file mode 100644 index 0000000..106d990 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/Plugins/Utils.cpp @@ -0,0 +1,23 @@ +// +// Utils.cpp +// MonoHookUtils_OSX +// +// Created by Misaka-Mikoto on 2022/8/31. +// +#include <stdio.h> +#include <stdint.h> +#include <pthread.h> +#include <string.h> +#include <libkern/OSCacheControl.h> + +extern "C"{ + +void* memcpy_jit(void* dst, void* src, int32_t size) +{ + pthread_jit_write_protect_np(0); + void* ret = memcpy(dst, src, size); + pthread_jit_write_protect_np(1); + sys_icache_invalidate (dst, size); + return ret; +} +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/Plugins/Utils.cpp.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/Plugins/Utils.cpp.meta new file mode 100644 index 0000000..447c3db --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/Plugins/Utils.cpp.meta @@ -0,0 +1,81 @@ +fileFormatVersion: 2 +guid: 56b28b5583a184c669dcb968d175544c +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + : Any + second: + enabled: 0 + settings: + Exclude Android: 1 + Exclude Editor: 0 + Exclude Linux64: 1 + Exclude OSXUniversal: 1 + Exclude WebGL: 1 + Exclude Win: 1 + Exclude Win64: 1 + Exclude iOS: 1 + - first: + Android: Android + second: + enabled: 0 + settings: + CPU: ARMv7 + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 1 + settings: + CPU: AnyCPU + DefaultValueInitialized: true + OS: OSX + - first: + Standalone: Linux64 + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: OSXUniversal + second: + enabled: 0 + settings: + CPU: ARM64 + - first: + Standalone: Win + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: Win64 + second: + enabled: 0 + settings: + CPU: None + - first: + iPhone: iOS + second: + enabled: 0 + settings: + AddToEmbeddedBinaries: false + CPU: AnyCPU + CompileFlags: + FrameworkDependencies: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/Plugins/build_libMonoHookUtils_OSX.dylib.sh b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/Plugins/build_libMonoHookUtils_OSX.dylib.sh new file mode 100644 index 0000000..8de985c --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/Plugins/build_libMonoHookUtils_OSX.dylib.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +clang -shared -undefined dynamic_lookup -o libMonoHookUtils_OSX.dylib Utils.cpp + diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/Plugins/build_libMonoHookUtils_OSX.dylib.sh.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/Plugins/build_libMonoHookUtils_OSX.dylib.sh.meta new file mode 100644 index 0000000..ed9f26d --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/Plugins/build_libMonoHookUtils_OSX.dylib.sh.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 69eeb734e262a0a4fbe0887249198f73 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/Plugins/silicon.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/Plugins/silicon.meta new file mode 100644 index 0000000..2e09562 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/Plugins/silicon.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7adba4475cf0bdc4fa7995c0d748f480 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/Plugins/silicon/libMonoHookUtils_OSX.dylib b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/Plugins/silicon/libMonoHookUtils_OSX.dylib new file mode 100644 index 0000000..edabc8a --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/Plugins/silicon/libMonoHookUtils_OSX.dylib Binary files differ diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/Plugins/silicon/libMonoHookUtils_OSX.dylib.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/Plugins/silicon/libMonoHookUtils_OSX.dylib.meta new file mode 100644 index 0000000..3045ab9 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/Plugins/silicon/libMonoHookUtils_OSX.dylib.meta @@ -0,0 +1,81 @@ +fileFormatVersion: 2 +guid: e092a73910a69894daea44290d7292f6 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 1 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + : Any + second: + enabled: 0 + settings: + Exclude Android: 1 + Exclude Editor: 0 + Exclude Linux64: 1 + Exclude OSXUniversal: 1 + Exclude WebGL: 1 + Exclude Win: 1 + Exclude Win64: 1 + Exclude iOS: 1 + - first: + Android: Android + second: + enabled: 0 + settings: + CPU: ARMv7 + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 1 + settings: + CPU: ARM64 + DefaultValueInitialized: true + OS: OSX + - first: + Standalone: Linux64 + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: OSXUniversal + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: Win + second: + enabled: 0 + settings: + CPU: x86 + - first: + Standalone: Win64 + second: + enabled: 0 + settings: + CPU: x86_64 + - first: + iPhone: iOS + second: + enabled: 0 + settings: + AddToEmbeddedBinaries: false + CPU: AnyCPU + CompileFlags: + FrameworkDependencies: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/Plugins/x86_64.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/Plugins/x86_64.meta new file mode 100644 index 0000000..d4267c3 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/Plugins/x86_64.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 31f6a810e38e66f4c832b135770a04bb +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/Plugins/x86_64/libMonoHookUtils_OSX.dylib b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/Plugins/x86_64/libMonoHookUtils_OSX.dylib new file mode 100644 index 0000000..07f9063 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/Plugins/x86_64/libMonoHookUtils_OSX.dylib Binary files differ diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/Plugins/x86_64/libMonoHookUtils_OSX.dylib.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/Plugins/x86_64/libMonoHookUtils_OSX.dylib.meta new file mode 100644 index 0000000..f301feb --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/3rds/UnityHook/Plugins/x86_64/libMonoHookUtils_OSX.dylib.meta @@ -0,0 +1,81 @@ +fileFormatVersion: 2 +guid: 4adb23596911347faa69537b900c9f5e +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + : Any + second: + enabled: 0 + settings: + Exclude Android: 1 + Exclude Editor: 0 + Exclude Linux64: 1 + Exclude OSXUniversal: 1 + Exclude WebGL: 1 + Exclude Win: 1 + Exclude Win64: 1 + Exclude iOS: 1 + - first: + Android: Android + second: + enabled: 0 + settings: + CPU: ARMv7 + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 1 + settings: + CPU: x86_64 + DefaultValueInitialized: true + OS: OSX + - first: + Standalone: Linux64 + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: OSXUniversal + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Win + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: Win64 + second: + enabled: 0 + settings: + CPU: None + - first: + iPhone: iOS + second: + enabled: 0 + settings: + AddToEmbeddedBinaries: false + CPU: AnyCPU + CompileFlags: + FrameworkDependencies: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ABI.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ABI.meta new file mode 100644 index 0000000..0557322 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ABI.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d26c8b77c84f09442a05f2c67e5e09b8 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ABI/ABIUtil.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ABI/ABIUtil.cs new file mode 100644 index 0000000..43846b0 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ABI/ABIUtil.cs @@ -0,0 +1,23 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace HybridCLR.Editor.ABI +{ + public static class ABIUtil + { + public static string GetHybridCLRPlatformMacro(PlatformABI abi) + { + switch(abi) + { + case PlatformABI.Arm64: return "HYBRIDCLR_ABI_ARM_64"; + case PlatformABI.Universal64: return "HYBRIDCLR_ABI_UNIVERSAL_64"; + case PlatformABI.Universal32: return "HYBRIDCLR_ABI_UNIVERSAL_32"; + case PlatformABI.WebGL32: return "HYBRIDCLR_ABI_WEBGL32"; + default: throw new NotSupportedException(); + } + } + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ABI/ABIUtil.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ABI/ABIUtil.cs.meta new file mode 100644 index 0000000..79a2ec0 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ABI/ABIUtil.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: edeb86f4b5b13ca4cb0fe9d87ce509bb +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ABI/MethodDesc.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ABI/MethodDesc.cs new file mode 100644 index 0000000..6675f34 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ABI/MethodDesc.cs @@ -0,0 +1,77 @@ +锘縰sing dnlib.DotNet; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; + +namespace HybridCLR.Editor.ABI +{ + public class MethodDesc : IEquatable<MethodDesc> + { + public string Sig { get; private set; } + + public MethodDef MethodDef { get; set; } + + public ReturnInfo ReturnInfo { get; set; } + + public List<ParamInfo> ParamInfos { get; set; } + + public void Init() + { + for(int i = 0; i < ParamInfos.Count; i++) + { + ParamInfos[i].Index = i; + } + Sig = CreateCallSigName(); + } + + public void TransfromSigTypes(Func<TypeInfo, bool, TypeInfo> transformer) + { + ReturnInfo.Type = transformer(ReturnInfo.Type, true); + foreach(var paramType in ParamInfos) + { + paramType.Type = transformer(paramType.Type, false); + } + } + + public string CreateCallSigName() + { + var n = new StringBuilder(); + n.Append(ReturnInfo.Type.CreateSigName()); + foreach(var param in ParamInfos) + { + n.Append(param.Type.CreateSigName()); + } + return n.ToString(); + } + + public string CreateInvokeSigName() + { + var n = new StringBuilder(); + n.Append(ReturnInfo.Type.CreateSigName()); + foreach (var param in ParamInfos) + { + n.Append(param.Type.CreateSigName()); + } + return n.ToString(); + } + + public override bool Equals(object obj) + { + return Equals((MethodDesc)obj); + } + + public bool Equals(MethodDesc other) + { + return Sig == other.Sig; + } + + public override int GetHashCode() + { + return Sig.GetHashCode(); + } + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ABI/MethodDesc.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ABI/MethodDesc.cs.meta new file mode 100644 index 0000000..0a0a97a --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ABI/MethodDesc.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 28e06667d06f37b4990b16f54f903a35 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ABI/ParamInfo.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ABI/ParamInfo.cs new file mode 100644 index 0000000..fc2cc7f --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ABI/ParamInfo.cs @@ -0,0 +1,30 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace HybridCLR.Editor.ABI +{ + + public class ParamInfo + { + public TypeInfo Type { get; set; } + + public int Index { get; set; } + + } + + public class ReturnInfo + { + public TypeInfo Type { get; set; } + + public bool IsVoid => Type.PorType == ParamOrReturnType.VOID; + + public override string ToString() + { + return Type.GetTypeName(); + } + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ABI/ParamInfo.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ABI/ParamInfo.cs.meta new file mode 100644 index 0000000..6b4174e --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ABI/ParamInfo.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f2ba16cf4bf82374c814789b6ced3abd +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ABI/ParamOrReturnType.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ABI/ParamOrReturnType.cs new file mode 100644 index 0000000..f8a478c --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ABI/ParamOrReturnType.cs @@ -0,0 +1,27 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace HybridCLR.Editor.ABI +{ + public enum ParamOrReturnType + { + VOID, + I1, + U1, + I2, + U2, + I4, + U4, + I8, + U8, + R4, + R8, + I, + U, + TYPEDBYREF, + STRUCT, + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ABI/ParamOrReturnType.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ABI/ParamOrReturnType.cs.meta new file mode 100644 index 0000000..12ffd4b --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ABI/ParamOrReturnType.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 80682e47c38a2f04f8af94d356688cf0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ABI/PlatformABI.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ABI/PlatformABI.cs new file mode 100644 index 0000000..62fdb16 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ABI/PlatformABI.cs @@ -0,0 +1,10 @@ +锘縩amespace HybridCLR.Editor.ABI +{ + public enum PlatformABI + { + Universal32, + Universal64, + Arm64, + WebGL32, + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ABI/PlatformABI.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ABI/PlatformABI.cs.meta new file mode 100644 index 0000000..bea367c --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ABI/PlatformABI.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b9f06ff0612105b4ea20e0309e759e24 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ABI/TypeCreator.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ABI/TypeCreator.cs new file mode 100644 index 0000000..12af7ae --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ABI/TypeCreator.cs @@ -0,0 +1,102 @@ +锘縰sing dnlib.DotNet; +using HybridCLR.Editor.Meta; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UnityEngine; + +namespace HybridCLR.Editor.ABI +{ + public class TypeCreator + { + private readonly Dictionary<TypeSig, TypeInfo> _typeInfoCache = new Dictionary<TypeSig, TypeInfo>(TypeEqualityComparer.Instance); + + private int _nextStructId = 0; + + public TypeInfo CreateTypeInfo(TypeSig type) + { + type = type.RemovePinnedAndModifiers(); + if (!_typeInfoCache.TryGetValue(type, out var typeInfo)) + { + typeInfo = CreateTypeInfo0(type); + _typeInfoCache.Add(type, typeInfo); + } + return typeInfo; + } + + TypeInfo CreateTypeInfo0(TypeSig type) + { + type = type.RemovePinnedAndModifiers(); + if (type.IsByRef) + { + return TypeInfo.s_u; + } + switch (type.ElementType) + { + case ElementType.Void: return TypeInfo.s_void; + case ElementType.Boolean: return TypeInfo.s_u1; + case ElementType.I1: return TypeInfo.s_i1; + case ElementType.U1: return TypeInfo.s_u1; + case ElementType.I2: return TypeInfo.s_i2; + case ElementType.Char: + case ElementType.U2: return TypeInfo.s_u2; + case ElementType.I4: return TypeInfo.s_i4; + case ElementType.U4: return TypeInfo.s_u4; + case ElementType.I8: return TypeInfo.s_i8; + case ElementType.U8: return TypeInfo.s_u8; + case ElementType.R4: return TypeInfo.s_r4; + case ElementType.R8: return TypeInfo.s_r8; + case ElementType.I: return TypeInfo.s_i; + case ElementType.U: + case ElementType.String: + case ElementType.Ptr: + case ElementType.ByRef: + case ElementType.Class: + case ElementType.Array: + case ElementType.SZArray: + case ElementType.FnPtr: + case ElementType.Object: + case ElementType.Module: + case ElementType.Var: + case ElementType.MVar: + return TypeInfo.s_u; + case ElementType.TypedByRef: return TypeInfo.s_typedByRef; + case ElementType.ValueType: + { + TypeDef typeDef = type.ToTypeDefOrRef().ResolveTypeDef(); + if (typeDef == null) + { + throw new Exception($"type:{type} definition could not be found. Please try `HybridCLR/Genergate/LinkXml`, then Build once to generate the AOT dll, and then regenerate the bridge function"); + } + if (typeDef.IsEnum) + { + return CreateTypeInfo(typeDef.GetEnumUnderlyingType()); + } + return CreateValueType(type); + } + case ElementType.GenericInst: + { + GenericInstSig gis = (GenericInstSig)type; + if (!gis.GenericType.IsValueType) + { + return TypeInfo.s_u; + } + TypeDef typeDef = gis.GenericType.ToTypeDefOrRef().ResolveTypeDef(); + if (typeDef.IsEnum) + { + return CreateTypeInfo(typeDef.GetEnumUnderlyingType()); + } + return CreateValueType(type); + } + default: throw new NotSupportedException($"{type.ElementType}"); + } + } + + protected TypeInfo CreateValueType(TypeSig type) + { + return new TypeInfo(ParamOrReturnType.STRUCT, type, _nextStructId++); + } + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ABI/TypeCreator.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ABI/TypeCreator.cs.meta new file mode 100644 index 0000000..7452840 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ABI/TypeCreator.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0b1df5760b488fa43a68843c46fda63a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ABI/TypeInfo.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ABI/TypeInfo.cs new file mode 100644 index 0000000..6d0b404 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ABI/TypeInfo.cs @@ -0,0 +1,116 @@ +锘縰sing dnlib.DotNet; +using HybridCLR.Editor.Meta; +using System; +using System.Collections.Generic; +using System.Reflection; +using UnityEngine; + +namespace HybridCLR.Editor.ABI +{ + public class TypeInfo : IEquatable<TypeInfo> + { + + public static readonly TypeInfo s_void = new TypeInfo(ParamOrReturnType.VOID); + public static readonly TypeInfo s_i1 = new TypeInfo(ParamOrReturnType.I1); + public static readonly TypeInfo s_u1 = new TypeInfo(ParamOrReturnType.U1); + public static readonly TypeInfo s_i2 = new TypeInfo(ParamOrReturnType.I2); + public static readonly TypeInfo s_u2 = new TypeInfo(ParamOrReturnType.U2); + public static readonly TypeInfo s_i4 = new TypeInfo(ParamOrReturnType.I4); + public static readonly TypeInfo s_u4 = new TypeInfo(ParamOrReturnType.U4); + public static readonly TypeInfo s_i8 = new TypeInfo(ParamOrReturnType.I8); + public static readonly TypeInfo s_u8 = new TypeInfo(ParamOrReturnType.U8); + public static readonly TypeInfo s_r4 = new TypeInfo(ParamOrReturnType.R4); + public static readonly TypeInfo s_r8 = new TypeInfo(ParamOrReturnType.R8); + public static readonly TypeInfo s_i = new TypeInfo(ParamOrReturnType.I); + public static readonly TypeInfo s_u = new TypeInfo(ParamOrReturnType.U); + public static readonly TypeInfo s_typedByRef = new TypeInfo(ParamOrReturnType.TYPEDBYREF); + + public const string strTypedByRef = "typedbyref"; + + public TypeInfo(ParamOrReturnType portype, TypeSig klass = null, int typeId = 0) + { + PorType = portype; + Klass = klass; + _typeId = typeId; + } + + public ParamOrReturnType PorType { get; } + + public TypeSig Klass { get; } + + public bool IsStruct => PorType == ParamOrReturnType.STRUCT; + + public bool IsPrimitiveType => PorType <= ParamOrReturnType.U; + + private readonly int _typeId; + + public int TypeId => _typeId; + + public bool Equals(TypeInfo other) + { + return PorType == other.PorType && TypeEqualityComparer.Instance.Equals(Klass, other.Klass); + } + + public override bool Equals(object obj) + { + return Equals((TypeInfo)obj); + } + + public override int GetHashCode() + { + return (int)PorType * 23 + (Klass != null ? TypeEqualityComparer.Instance.GetHashCode(Klass) : 0); + } + + public bool NeedExpandValue() + { + return PorType >= ParamOrReturnType.I1 && PorType <= ParamOrReturnType.U2; + } + + public string CreateSigName() + { + switch (PorType) + { + case ParamOrReturnType.VOID: return "v"; + case ParamOrReturnType.I1: return "i1"; + case ParamOrReturnType.U1: return "u1"; + case ParamOrReturnType.I2: return "i2"; + case ParamOrReturnType.U2: return "u2"; + case ParamOrReturnType.I4: return "i4"; + case ParamOrReturnType.U4: return "u4"; + case ParamOrReturnType.I8: return "i8"; + case ParamOrReturnType.U8: return "u8"; + case ParamOrReturnType.R4: return "r4"; + case ParamOrReturnType.R8: return "r8"; + case ParamOrReturnType.I: return "i"; + case ParamOrReturnType.U: return "u"; + case ParamOrReturnType.TYPEDBYREF: return strTypedByRef; + case ParamOrReturnType.STRUCT: return $"s{_typeId}"; + default: throw new NotSupportedException(PorType.ToString()); + }; + } + + public string GetTypeName() + { + switch (PorType) + { + case ParamOrReturnType.VOID: return "void"; + case ParamOrReturnType.I1: return "int8_t"; + case ParamOrReturnType.U1: return "uint8_t"; + case ParamOrReturnType.I2: return "int16_t"; + case ParamOrReturnType.U2: return "uint16_t"; + case ParamOrReturnType.I4: return "int32_t"; + case ParamOrReturnType.U4: return "uint32_t"; + case ParamOrReturnType.I8: return "int64_t"; + case ParamOrReturnType.U8: return "uint64_t"; + case ParamOrReturnType.R4: return "float"; + case ParamOrReturnType.R8: return "double"; + case ParamOrReturnType.I: return "intptr_t"; + case ParamOrReturnType.U: return "uintptr_t"; + case ParamOrReturnType.TYPEDBYREF: return "Il2CppTypedRef"; + case ParamOrReturnType.STRUCT: return $"__struct_{_typeId}__"; + default: throw new NotImplementedException(PorType.ToString()); + }; + } + + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ABI/TypeInfo.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ABI/TypeInfo.cs.meta new file mode 100644 index 0000000..5df8577 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ABI/TypeInfo.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ffafce7f1f0bf614d95b48ca39385377 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ABI/ValueTypeSizeAligmentCalculator.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ABI/ValueTypeSizeAligmentCalculator.cs new file mode 100644 index 0000000..a97dd02 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ABI/ValueTypeSizeAligmentCalculator.cs @@ -0,0 +1,181 @@ +锘縰sing dnlib.DotNet; +using HybridCLR.Editor.Meta; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; +using UnityEngine; + +namespace HybridCLR.Editor.ABI +{ + public class ValueTypeSizeAligmentCalculator + { + public static ValueTypeSizeAligmentCalculator Caculator64 { get; } = new ValueTypeSizeAligmentCalculator(false); + + public static ValueTypeSizeAligmentCalculator Caculator32 { get; } = new ValueTypeSizeAligmentCalculator(true); + + public ValueTypeSizeAligmentCalculator(bool arch32) + { + _referenceSize = arch32 ? 4 : 8; + } + + private readonly int _referenceSize; + + private static bool IsIgnoreField(FieldDef field) + { + var ignoreAttr = field.CustomAttributes.Where(a => a.AttributeType.FullName == "UnityEngine.Bindings.IgnoreAttribute").FirstOrDefault(); + if (ignoreAttr == null) + { + return false; + } + CANamedArgument arg = ignoreAttr.GetProperty("DoesNotContributeToSize"); + if(arg != null && (bool)arg.Value) + { + //Debug.Log($"IgnoreField.DoesNotContributeToSize = true:{field}"); + return true; + } + return false; + } + + private (int Size, int Aligment) SizeAndAligmentOfStruct(TypeSig type) + { + int totalSize = 0; + int packAligment = 8; + int maxAligment = 1; + + TypeDef typeDef = type.ToTypeDefOrRef().ResolveTypeDefThrow(); + + List<TypeSig> klassInst = type.ToGenericInstSig()?.GenericArguments?.ToList(); + GenericArgumentContext ctx = klassInst != null ? new GenericArgumentContext(klassInst, null) : null; + + ClassLayout sa = typeDef.ClassLayout; + if (sa != null && sa.PackingSize > 0) + { + packAligment = sa.PackingSize; + } + bool useSLSize = true; + foreach (FieldDef field in typeDef.Fields) + { + if (field.IsStatic) + { + continue; + } + TypeSig fieldType = ctx != null ? MetaUtil.Inflate(field.FieldType, ctx) : field.FieldType; + var (fs, fa) = SizeAndAligmentOf(fieldType); + fa = Math.Min(fa, packAligment); + if (fa > maxAligment) + { + maxAligment = fa; + } + if (IsIgnoreField(field)) + { + continue; + } + if (typeDef.Layout.HasFlag(dnlib.DotNet.TypeAttributes.ExplicitLayout)) + { + int offset = (int)field.FieldOffset.Value; + totalSize = Math.Max(totalSize, offset + fs); + if (sa != null && offset > sa.ClassSize) + { + useSLSize = false; + } + } + else + { + if (totalSize % fa != 0) + { + totalSize = (totalSize + fa - 1) / fa * fa; + } + totalSize += fs; + if (sa != null && totalSize > sa.ClassSize) + { + useSLSize = false; + } + } + } + if (totalSize == 0) + { + totalSize = maxAligment; + } + if (totalSize % maxAligment != 0) + { + totalSize = (totalSize + maxAligment - 1) / maxAligment * maxAligment; + } + if (sa != null && sa.ClassSize > 0) + { + if (/*sa.Value == LayoutKind.Explicit &&*/ useSLSize) + { + totalSize = (int)sa.ClassSize; + while(totalSize % maxAligment != 0) + { + maxAligment /= 2; + } + } + } + return (totalSize, maxAligment); + } + + public (int Size, int Aligment) SizeAndAligmentOf(TypeSig type) + { + type = type.RemovePinnedAndModifiers(); + if (type.IsByRef || !type.IsValueType || type.IsArray) + return (_referenceSize, _referenceSize); + + switch (type.ElementType) + { + case ElementType.Void: throw new NotSupportedException(type.ToString()); + case ElementType.Boolean: + case ElementType.I1: + case ElementType.U1: return (1, 1); + case ElementType.Char: + case ElementType.I2: + case ElementType.U2: return (2, 2); + case ElementType.I4: + case ElementType.U4: return (4, 4); + case ElementType.I8: + case ElementType.U8: return (8, 8); + case ElementType.R4: return (4, 4); + case ElementType.R8: return (8, 8); + case ElementType.I: + case ElementType.U: + case ElementType.String: + case ElementType.Ptr: + case ElementType.ByRef: + case ElementType.Class: + case ElementType.Array: + case ElementType.SZArray: + case ElementType.FnPtr: + case ElementType.Object: + case ElementType.Module: return (_referenceSize, _referenceSize); + case ElementType.TypedByRef: return SizeAndAligmentOfStruct(type); + case ElementType.ValueType: + { + TypeDef typeDef = type.ToTypeDefOrRef().ResolveTypeDef(); + if (typeDef.IsEnum) + { + return SizeAndAligmentOf(typeDef.GetEnumUnderlyingType()); + } + return SizeAndAligmentOfStruct(type); + } + case ElementType.GenericInst: + { + GenericInstSig gis = (GenericInstSig)type; + if (!gis.GenericType.IsValueType) + { + return (_referenceSize, _referenceSize); + } + TypeDef typeDef = gis.GenericType.ToTypeDefOrRef().ResolveTypeDef(); + if (typeDef.IsEnum) + { + return SizeAndAligmentOf(typeDef.GetEnumUnderlyingType()); + } + return SizeAndAligmentOfStruct(type); + } + default: throw new NotSupportedException(type.ToString()); + } + } + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ABI/ValueTypeSizeAligmentCalculator.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ABI/ValueTypeSizeAligmentCalculator.cs.meta new file mode 100644 index 0000000..4b83d63 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ABI/ValueTypeSizeAligmentCalculator.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b7af32bdf1cf55c42bfc449820d401cb +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/AOT.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/AOT.meta new file mode 100644 index 0000000..9b9539f --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/AOT.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b4071bf66ac9c544487ae88b5ee9b20a +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/AOT/AOTAssemblyMetadataStripper.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/AOT/AOTAssemblyMetadataStripper.cs new file mode 100644 index 0000000..37c8952 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/AOT/AOTAssemblyMetadataStripper.cs @@ -0,0 +1,56 @@ +锘縰sing dnlib.DotNet; +using dnlib.DotNet.Writer; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace HybridCLR.Editor.AOT +{ + public class AOTAssemblyMetadataStripper + { + public static byte[] Strip(byte[] assemblyBytes) + { + var context = ModuleDef.CreateModuleContext(); + var readerOption = new ModuleCreationOptions(context) + { + Runtime = CLRRuntimeReaderKind.Mono + }; + var mod = ModuleDefMD.Load(assemblyBytes, readerOption); + // remove all resources + mod.Resources.Clear(); + foreach (var type in mod.GetTypes()) + { + if (type.HasGenericParameters) + { + continue; + } + foreach (var method in type.Methods) + { + if (!method.HasBody || method.HasGenericParameters) + { + continue; + } + method.Body = null; + } + } + var writer = new System.IO.MemoryStream(); + var options = new ModuleWriterOptions(mod); + options.MetadataOptions.Flags |= MetadataFlags.PreserveRids; + mod.Write(writer, options); + writer.Flush(); + return writer.ToArray(); + } + + public static void Strip(string originalAssemblyPath, string strippedAssemblyPath) + { + byte[] originDllBytes = System.IO.File.ReadAllBytes(originalAssemblyPath); + byte[] strippedDllBytes = Strip(originDllBytes); + UnityEngine.Debug.Log($"aot dll:{originalAssemblyPath}, length: {originDllBytes.Length} -> {strippedDllBytes.Length}, stripping rate:{(originDllBytes.Length - strippedDllBytes.Length)/(double)originDllBytes.Length} "); + Directory.CreateDirectory(System.IO.Path.GetDirectoryName(strippedAssemblyPath)); + System.IO.File.WriteAllBytes(strippedAssemblyPath, strippedDllBytes); + } + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/AOT/AOTAssemblyMetadataStripper.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/AOT/AOTAssemblyMetadataStripper.cs.meta new file mode 100644 index 0000000..f7642f9 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/AOT/AOTAssemblyMetadataStripper.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7e9e6a048682dcb4fab806251411f29f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/AOT/Analyzer.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/AOT/Analyzer.cs new file mode 100644 index 0000000..dcd2a87 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/AOT/Analyzer.cs @@ -0,0 +1,231 @@ +锘縰sing dnlib.DotNet; +using HybridCLR.Editor.Meta; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UnityEngine; + +namespace HybridCLR.Editor.AOT +{ + + public class Analyzer + { + public class Options + { + public AssemblyReferenceDeepCollector Collector { get; set; } + + public int MaxIterationCount { get; set; } + + public bool ComputeAotAssembly { get; set; } + } + + private readonly int _maxInterationCount; + + private readonly AssemblyReferenceDeepCollector _assemblyCollector; + + private readonly bool _computeAotAssembly; + + private readonly HashSet<GenericClass> _genericTypes = new HashSet<GenericClass>(); + private readonly HashSet<GenericMethod> _genericMethods = new HashSet<GenericMethod>(); + + private List<GenericMethod> _processingMethods = new List<GenericMethod>(); + private List<GenericMethod> _newMethods = new List<GenericMethod>(); + + public IReadOnlyCollection<GenericClass> GenericTypes => _genericTypes; + + public IReadOnlyCollection<GenericMethod> GenericMethods => _genericMethods; + + private readonly MethodReferenceAnalyzer _methodReferenceAnalyzer; + + private readonly HashSet<string> _hotUpdateAssemblyFiles; + + public ConstraintContext ConstraintContext { get; } = new ConstraintContext(); + + public List<GenericClass> AotGenericTypes { get; } = new List<GenericClass>(); + + public List<GenericMethod> AotGenericMethods { get; } = new List<GenericMethod>(); + + public Analyzer(Options options) + { + _assemblyCollector = options.Collector; + _maxInterationCount = options.MaxIterationCount; + _computeAotAssembly = options.ComputeAotAssembly; + _methodReferenceAnalyzer = new MethodReferenceAnalyzer(this.OnNewMethod); + _hotUpdateAssemblyFiles = new HashSet<string>(options.Collector.GetRootAssemblyNames().Select(assName => assName + ".dll")); + } + + private void TryAddAndWalkGenericType(GenericClass gc) + { + if (gc == null) + { + return; + } + gc = gc.ToGenericShare(); + if (_genericTypes.Add(gc) && NeedWalk(null, gc.Type)) + { + WalkType(gc); + } + } + + private bool NeedWalk(MethodDef callFrom, TypeDef type) + { + return _hotUpdateAssemblyFiles.Contains(type.Module.Name) || callFrom == null || callFrom.HasGenericParameters; + } + + private bool IsAotType(TypeDef type) + { + return _computeAotAssembly || !_hotUpdateAssemblyFiles.Contains(type.Module.Name); + } + + private bool IsAotGenericMethod(MethodDef method) + { + return IsAotType(method.DeclaringType) && method.HasGenericParameters; + } + + private void OnNewMethod(MethodDef methodDef, List<TypeSig> klassGenericInst, List<TypeSig> methodGenericInst, GenericMethod method) + { + if(method == null) + { + return; + } + if (NeedWalk(methodDef, method.Method.DeclaringType) && _genericMethods.Add(method)) + { + _newMethods.Add(method); + } + if (method.KlassInst != null) + { + TryAddAndWalkGenericType(new GenericClass(method.Method.DeclaringType, method.KlassInst)); + } + } + + private void TryAddMethodNotWalkType(GenericMethod method) + { + if (method == null) + { + return; + } + if (NeedWalk(null, method.Method.DeclaringType) && _genericMethods.Add(method)) + { + _newMethods.Add(method); + } + } + + private void WalkType(GenericClass gc) + { + //Debug.Log($"typespec:{sig} {sig.GenericType} {sig.GenericType.TypeDefOrRef.ResolveTypeDef()}"); + //Debug.Log($"== walk generic type:{new GenericInstSig(gc.Type.ToTypeSig().ToClassOrValueTypeSig(), gc.KlassInst)}"); + ITypeDefOrRef baseType = gc.Type.BaseType; + if (baseType != null && baseType.TryGetGenericInstSig() != null) + { + GenericClass parentType = GenericClass.ResolveClass((TypeSpec)baseType, new GenericArgumentContext(gc.KlassInst, null)); + TryAddAndWalkGenericType(parentType); + } + foreach (var method in gc.Type.Methods) + { + if (method.HasGenericParameters || !method.HasBody || method.Body.Instructions == null) + { + continue; + } + var gm = new GenericMethod(method, gc.KlassInst, null).ToGenericShare(); + //Debug.Log($"add method:{gm.Method} {gm.KlassInst}"); + TryAddMethodNotWalkType(gm); + } + } + + private void WalkType(TypeDef typeDef) + { + if (typeDef.HasGenericParameters) + { + return; + } + ITypeDefOrRef baseType = typeDef.BaseType; + if (baseType != null && baseType.TryGetGenericInstSig() != null) + { + GenericClass gc = GenericClass.ResolveClass((TypeSpec)baseType, null); + TryAddAndWalkGenericType(gc); + } + } + + private void Prepare() + { + // 灏嗘墍鏈夐潪娉涘瀷鍑芥暟鍏ㄩ儴鍔犲叆鍑芥暟鍒楄〃锛屽悓鏃剁珛椹瑆alk杩欎簺method銆� + // 鍚庣画杩唬涓皢鍙亶鍘哅ethodSpec + foreach (var ass in _assemblyCollector.GetLoadedModulesOfRootAssemblies()) + { + foreach (TypeDef typeDef in ass.GetTypes()) + { + WalkType(typeDef); + } + + for (uint rid = 1, n = ass.Metadata.TablesStream.TypeSpecTable.Rows; rid <= n; rid++) + { + var ts = ass.ResolveTypeSpec(rid); + var cs = GenericClass.ResolveClass(ts, null)?.ToGenericShare(); + if (cs != null) + { + TryAddAndWalkGenericType(cs); + } + } + + for (uint rid = 1, n = ass.Metadata.TablesStream.MethodSpecTable.Rows; rid <= n; rid++) + { + var ms = ass.ResolveMethodSpec(rid); + var gm = GenericMethod.ResolveMethod(ms, null)?.ToGenericShare(); + TryAddMethodNotWalkType(gm); + } + } + Debug.Log($"PostPrepare genericTypes:{_genericTypes.Count} genericMethods:{_genericMethods.Count} newMethods:{_newMethods.Count}"); + } + + private void RecursiveCollect() + { + for (int i = 0; i < _maxInterationCount && _newMethods.Count > 0; i++) + { + var temp = _processingMethods; + _processingMethods = _newMethods; + _newMethods = temp; + _newMethods.Clear(); + + foreach (var method in _processingMethods) + { + _methodReferenceAnalyzer.WalkMethod(method.Method, method.KlassInst, method.MethodInst); + } + Debug.Log($"iteration:[{i}] genericClass:{_genericTypes.Count} genericMethods:{_genericMethods.Count} newMethods:{_newMethods.Count}"); + } + } + + private bool IsNotShareableAOTGenericType(TypeDef typeDef) + { + if (!IsAotType(typeDef)) + { + return false; + } + return typeDef.GenericParameters.Any(c => !c.HasReferenceTypeConstraint); + } + + private bool IsNotShareableAOTGenericMethod(MethodDef method) + { + if (!IsAotGenericMethod(method)) + { + return false; + } + return method.GenericParameters.Concat(method.DeclaringType.GenericParameters).Any(c => !c.HasReferenceTypeConstraint); + } + + private void FilterAOTGenericTypeAndMethods() + { + ConstraintContext cc = this.ConstraintContext; + AotGenericTypes.AddRange(_genericTypes.Where(type => IsNotShareableAOTGenericType(type.Type)).Select(gc => cc.ApplyConstraints(gc))); + AotGenericMethods.AddRange(_genericMethods.Where(method => IsNotShareableAOTGenericMethod(method.Method)).Select(gm => cc.ApplyConstraints(gm))); + } + + public void Run() + { + Prepare(); + RecursiveCollect(); + FilterAOTGenericTypeAndMethods(); + } + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/AOT/Analyzer.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/AOT/Analyzer.cs.meta new file mode 100644 index 0000000..2e573fc --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/AOT/Analyzer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 30bbf4a80a6cf3a43b3f489747d9dd6a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/AOT/ConstraintContext.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/AOT/ConstraintContext.cs new file mode 100644 index 0000000..4a9cd3c --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/AOT/ConstraintContext.cs @@ -0,0 +1,73 @@ +锘縰sing dnlib.DotNet; +using HybridCLR.Editor.Meta; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace HybridCLR.Editor.AOT +{ + + public class ConstraintContext + { + public class ImplType + { + public TypeSig BaseType { get; } + + public List<TypeSig> Interfaces { get; } + + public bool ValueType { get; } + + private readonly int _hash; + + public ImplType(TypeSig baseType, List<TypeSig> interfaces, bool valueType) + { + BaseType = baseType; + Interfaces = interfaces; + ValueType = valueType; + _hash = ComputHash(); + } + + public override bool Equals(object obj) + { + ImplType o = (ImplType)obj; + return MetaUtil.EqualsTypeSig(this.BaseType, o.BaseType) + && MetaUtil.EqualsTypeSigArray(this.Interfaces, o.Interfaces) + && this.ValueType == o.ValueType; + } + + public override int GetHashCode() + { + return _hash; + } + + private int ComputHash() + { + int hash = 0; + if (BaseType != null) + { + hash = HashUtil.CombineHash(hash, TypeEqualityComparer.Instance.GetHashCode(BaseType)); + } + if (Interfaces.Count > 0) + { + hash = HashUtil.CombineHash(hash, HashUtil.ComputHash(Interfaces)); + } + + return hash; + } + } + + public HashSet<ImplType> ImplTypes { get; } = new HashSet<ImplType>(); + + public GenericClass ApplyConstraints(GenericClass gc) + { + return gc; + } + + public GenericMethod ApplyConstraints(GenericMethod gm) + { + return gm; + } + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/AOT/ConstraintContext.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/AOT/ConstraintContext.cs.meta new file mode 100644 index 0000000..3e99cab --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/AOT/ConstraintContext.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 812d81a75b690394bbe16ef5f0bcbc46 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/AOT/GenericReferenceWriter.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/AOT/GenericReferenceWriter.cs new file mode 100644 index 0000000..1b6021f --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/AOT/GenericReferenceWriter.cs @@ -0,0 +1,139 @@ +锘縰sing HybridCLR.Editor.Meta; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using UnityEngine; + +namespace HybridCLR.Editor.AOT +{ + public class GenericReferenceWriter + { + private static readonly Dictionary<Type, string> _typeNameMapping = new Dictionary<Type, string> + { + {typeof(bool), "bool" }, + {typeof(byte), "byte" }, + {typeof(sbyte), "sbyte" }, + {typeof(short), "short" }, + {typeof(ushort), "ushort" }, + {typeof(int), "int" }, + {typeof(uint), "uint" }, + {typeof(long), "long" }, + {typeof(ulong), "ulong" }, + {typeof(float), "float" }, + {typeof(double), "double" }, + {typeof(object), "object" }, + {typeof(string), "string" }, + }; + + private readonly Dictionary<string, string> _typeSimpleNameMapping = new Dictionary<string, string>(); + private readonly Regex _systemTypePattern; + private readonly Regex _genericPattern = new Regex(@"`\d+"); + + public GenericReferenceWriter() + { + foreach (var e in _typeNameMapping) + { + _typeSimpleNameMapping.Add(e.Key.FullName, e.Value); + } + _systemTypePattern = new Regex(string.Join("|", _typeSimpleNameMapping.Keys.Select (k => $@"\b{Regex.Escape(k)}\b"))); + } + + public string PrettifyTypeSig(string typeSig) + { + string s = _genericPattern.Replace(typeSig, "").Replace('/', '.'); + return _systemTypePattern.Replace(s, m => _typeSimpleNameMapping[m.Groups[0].Value]); + } + + public string PrettifyMethodSig(string methodSig) + { + string s = PrettifyTypeSig(methodSig).Replace("::", "."); + if (s.Contains(".ctor(")) + { + s = "new " + s.Replace(".ctor(", "("); + } + return s; + } + + public void Write(List<GenericClass> types, List<GenericMethod> methods, string outputFile) + { + string parentDir = Directory.GetParent(outputFile).FullName; + Directory.CreateDirectory(parentDir); + + List<string> codes = new List<string>(); + codes.Add("using System.Collections.Generic;"); + codes.Add("public class AOTGenericReferences : UnityEngine.MonoBehaviour"); + codes.Add("{"); + + codes.Add(""); + codes.Add("\t// {{ AOT assemblies"); + codes.Add("\tpublic static readonly IReadOnlyList<string> PatchedAOTAssemblyList = new List<string>"); + codes.Add("\t{"); + List<dnlib.DotNet.ModuleDef> modules = new HashSet<dnlib.DotNet.ModuleDef>( + types.Select(t => t.Type.Module).Concat(methods.Select(m => m.Method.Module))).ToList(); + modules.Sort((a, b) => a.Name.CompareTo(b.Name)); + foreach (dnlib.DotNet.ModuleDef module in modules) + { + codes.Add($"\t\t\"{module.Name}\","); + } + codes.Add("\t};"); + codes.Add("\t// }}"); + + + codes.Add(""); + codes.Add("\t// {{ constraint implement type"); + + codes.Add("\t// }} "); + + codes.Add(""); + codes.Add("\t// {{ AOT generic types"); + + List<string> typeNames = types.Select(t => PrettifyTypeSig(t.ToTypeSig().ToString())).ToList(); + typeNames.Sort(string.CompareOrdinal); + foreach(var typeName in typeNames) + { + codes.Add($"\t// {typeName}"); + } + + codes.Add("\t// }}"); + + codes.Add(""); + codes.Add("\tpublic void RefMethods()"); + codes.Add("\t{"); + + List<(string, string, string)> methodTypeAndNames = methods.Select(m => + (PrettifyTypeSig(m.Method.DeclaringType.ToString()), PrettifyMethodSig(m.Method.Name), PrettifyMethodSig(m.ToMethodSpec().ToString()))) + .ToList(); + methodTypeAndNames.Sort((a, b) => + { + int c = String.Compare(a.Item1, b.Item1, StringComparison.Ordinal); + if (c != 0) + { + return c; + } + + c = String.Compare(a.Item2, b.Item2, StringComparison.Ordinal); + if (c != 0) + { + return c; + } + return String.Compare(a.Item3, b.Item3, StringComparison.Ordinal); + }); + foreach(var method in methodTypeAndNames) + { + codes.Add($"\t\t// {PrettifyMethodSig(method.Item3)}"); + } + codes.Add("\t}"); + + codes.Add("}"); + + + var utf8WithoutBom = new System.Text.UTF8Encoding(false); + File.WriteAllText(outputFile, string.Join("\n", codes), utf8WithoutBom); + Debug.Log($"[GenericReferenceWriter] write {outputFile}"); + } + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/AOT/GenericReferenceWriter.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/AOT/GenericReferenceWriter.cs.meta new file mode 100644 index 0000000..9fc1497 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/AOT/GenericReferenceWriter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d1243cf04685361478972f93b5ca868a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors.meta new file mode 100644 index 0000000..428a0a1 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f80d2287f01c89642a74b0a60f7a3305 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/AddLil2cppSourceCodeToXcodeproj2019.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/AddLil2cppSourceCodeToXcodeproj2019.cs new file mode 100644 index 0000000..b879aff --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/AddLil2cppSourceCodeToXcodeproj2019.cs @@ -0,0 +1,258 @@ +using System; +using HybridCLR.Editor.Installer; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using UnityEditor; +using System.Reflection; +using HybridCLR.Editor.Settings; +#if UNITY_2019 && (UNITY_IOS || UNITY_TVOS) +using UnityEditor.Build; +using UnityEditor.Callbacks; +using UnityEditor.iOS.Xcode; +using UnityEngine; + +namespace HybridCLR.Editor.BuildProcessors +{ + public static class AddLil2cppSourceCodeToXcodeproj2019 + { + [PostProcessBuild] + public static void OnPostProcessBuild(BuildTarget target, string pathToBuiltProject) + { + if (!HybridCLRSettings.Instance.enable) + return; + /* + * 1. 鐢熸垚lump锛屽苟涓旀坊鍔犲埌宸ョ▼ + 3. 灏唋ibil2cpp鐩綍澶嶅埗鍒� Library/. 鍒犻櫎鏃х殑. search paths閲屼慨鏀� libil2cpp/include涓簂ibil2cpp + 3. Libraries/bdwgc/include -> Libraries/external/bdwgc/include + 4. 灏唀xternal鐩綍澶嶅埗鍒� Library/external銆傚垹闄ゆ棫鐩綍 + 5. 灏哃ibrary/external/baselib/Platforms/OSX鏀瑰悕涓� IOS 鍏ㄥぇ鍐� + 6. 灏� external/zlib涓媍 鏂囦欢娣诲姞鍒板伐绋� + 7. 绉婚櫎libil2cpp.a + 8. Include path add libil2cpp/os/ClassLibraryPAL/brotli/include + 9. add external/xxHash + 10. add "#include <stdio.h>" to Classes/Prefix.pch + */ + + string pbxprojFile = BuildProcessorUtil.GetXcodeProjectFile(pathToBuiltProject); + string srcLibil2cppDir = $"{SettingsUtil.LocalIl2CppDir}/libil2cpp"; + string dstLibil2cppDir = $"{pathToBuiltProject}/Libraries/libil2cpp"; + string lumpDir = $"{pathToBuiltProject}/Libraries/lumps"; + string srcExternalDir = $"{SettingsUtil.LocalIl2CppDir}/external"; + string dstExternalDir = $"{pathToBuiltProject}/Libraries/external"; + //RemoveExternalLibil2cppOption(srcExternalDir, dstExternalDir); + CopyLibil2cppToXcodeProj(srcLibil2cppDir, dstLibil2cppDir); + CopyExternalToXcodeProj(srcExternalDir, dstExternalDir); + var lumpFiles = CreateLumps(dstLibil2cppDir, lumpDir); + var extraSources = GetExtraSourceFiles(dstExternalDir, dstLibil2cppDir); + var cflags = new List<string>() + { + "-DIL2CPP_MONO_DEBUGGER_DISABLED", + }; + ModifyPBXProject(pathToBuiltProject, pbxprojFile, lumpFiles, extraSources, cflags); + AddSystemHeaderToPrefixPch(pathToBuiltProject); + } + + private static void AddSystemHeaderToPrefixPch(string pathToBuiltProject) + { + // 濡傛灉涓嶅皢 stdio.h 娣诲姞鍒� Prefix.pch, zutil.c浼氭湁缂栬瘧閿欒 + string prefixPchFile = $"{pathToBuiltProject}/Classes/Prefix.pch"; + string fileContent = File.ReadAllText(prefixPchFile, Encoding.UTF8); + if (!fileContent.Contains("stdio.h")) + { + string newFileContent = fileContent + "\n#include <stdio.h>\n"; + File.WriteAllText(prefixPchFile, newFileContent, Encoding.UTF8); + UnityEngine.Debug.Log($"append header to {prefixPchFile}"); + } + } + + private static string GetRelativePathFromProj(string path) + { + return path.Substring(path.IndexOf("Libraries", StringComparison.Ordinal)).Replace('\\', '/'); + } + + private static void ModifyPBXProject(string pathToBuiltProject, string pbxprojFile, List<LumpFile> lumpFiles, List<string> extraFiles, List<string> cflags) + { + var proj = new PBXProject(); + proj.ReadFromFile(pbxprojFile); + string targetGUID = proj.GetUnityFrameworkTargetGuid(); + // 绉婚櫎鏃х殑libil2cpp.a + var libil2cppGUID = proj.FindFileGuidByProjectPath("Libraries/libil2cpp.a"); + if (!string.IsNullOrEmpty(libil2cppGUID)) + { + proj.RemoveFileFromBuild(targetGUID, libil2cppGUID); + proj.RemoveFile(libil2cppGUID); + File.Delete(Path.Combine(pathToBuiltProject, "Libraries", "libil2cpp.a")); + } + + //var lumpGroupGuid = proj.AddFile("Lumps", $"Classes/Lumps", PBXSourceTree.Group); + + foreach (var lumpFile in lumpFiles) + { + string lumpFileName = Path.GetFileName(lumpFile.lumpFile); + string projPathOfFile = $"Classes/Lumps/{lumpFileName}"; + string relativePathOfFile = GetRelativePathFromProj(lumpFile.lumpFile); + string lumpGuid = proj.FindFileGuidByProjectPath(projPathOfFile); + if (!string.IsNullOrEmpty(lumpGuid)) + { + proj.RemoveFileFromBuild(targetGUID, lumpGuid); + proj.RemoveFile(lumpGuid); + } + lumpGuid = proj.AddFile(relativePathOfFile, projPathOfFile, PBXSourceTree.Source); + proj.AddFileToBuild(targetGUID, lumpGuid); + } + + foreach (var extraFile in extraFiles) + { + string projPathOfFile = $"Classes/Extrals/{Path.GetFileName(extraFile)}"; + string extraFileGuid = proj.FindFileGuidByProjectPath(projPathOfFile); + if (!string.IsNullOrEmpty(extraFileGuid)) + { + proj.RemoveFileFromBuild(targetGUID, extraFileGuid); + proj.RemoveFile(extraFileGuid); + //Debug.LogWarning($"remove exist extra file:{projPathOfFile} guid:{extraFileGuid}"); + } + var lumpGuid = proj.AddFile(GetRelativePathFromProj(extraFile), projPathOfFile, PBXSourceTree.Source); + proj.AddFileToBuild(targetGUID, lumpGuid); + } + + foreach(var configName in proj.BuildConfigNames()) + { + //Debug.Log($"build config:{bcn}"); + string configGuid = proj.BuildConfigByName(targetGUID, configName); + string headerSearchPaths = "HEADER_SEARCH_PATHS"; + string hspProp = proj.GetBuildPropertyForConfig(configGuid, headerSearchPaths); + //Debug.Log($"config guid:{configGuid} prop:{hspProp}"); + string newPro = hspProp.Replace("libil2cpp/include", "libil2cpp") + .Replace("Libraries/bdwgc", "Libraries/external/bdwgc"); + + //if (!newPro.Contains("Libraries/libil2cpp/os/ClassLibraryPAL/brotli/include")) + //{ + // newPro += " $(SRCROOT)/Libraries/libil2cpp/os/ClassLibraryPAL/brotli/include"; + //} + if (!newPro.Contains("Libraries/external/xxHash")) + { + newPro += " $(SRCROOT)/Libraries/external/xxHash"; + } + newPro += " $(SRCR00T)/Libraries/external/mono"; + //Debug.Log($"config:{bcn} new prop:{newPro}"); + proj.SetBuildPropertyForConfig(configGuid, headerSearchPaths, newPro); + + string cflagKey = "OTHER_CFLAGS"; + string cfProp = proj.GetBuildPropertyForConfig(configGuid, cflagKey); + foreach (var flag in cflags) + { + if (!cfProp.Contains(flag)) + { + cfProp += " " + flag; + } + } + if (configName.Contains("Debug") && !cfProp.Contains("-DIL2CPP_DEBUG=")) + { + cfProp += " -DIL2CPP_DEBUG=1 -DDEBUG=1"; + } + proj.SetBuildPropertyForConfig(configGuid, cflagKey, cfProp); + + } + proj.WriteToFile(pbxprojFile); + } + + private static void CopyLibil2cppToXcodeProj(string srcLibil2cppDir, string dstLibil2cppDir) + { + BashUtil.RemoveDir(dstLibil2cppDir); + BashUtil.CopyDir(srcLibil2cppDir, dstLibil2cppDir, true); + } + + + private static void CopyExternalToXcodeProj(string srcExternalDir, string dstExternalDir) + { + BashUtil.RemoveDir(dstExternalDir); + BashUtil.CopyDir(srcExternalDir, dstExternalDir, true); + + //string baselibPlatfromsDir = $"{dstExternalDir}/baselib/Platforms"; + //BashUtil.RemoveDir($"{baselibPlatfromsDir}/IOS"); + //BashUtil.CopyDir($"{baselibPlatfromsDir}/OSX", $"{baselibPlatfromsDir}/IOS", true); + } + + class LumpFile + { + public List<string> cppFiles = new List<string>(); + + public readonly string lumpFile; + + public readonly string il2cppConfigFile; + + public LumpFile(string lumpFile, string il2cppConfigFile) + { + this.lumpFile = lumpFile; + this.il2cppConfigFile = il2cppConfigFile; + this.cppFiles.Add(il2cppConfigFile); + } + + public void SaveFile() + { + var lumpFileContent = new List<string>(); + foreach (var file in cppFiles) + { + lumpFileContent.Add($"#include \"{GetRelativePathFromProj(file)}\""); + } + File.WriteAllLines(lumpFile, lumpFileContent, Encoding.UTF8); + Debug.Log($"create lump file:{lumpFile}"); + } + } + + private static List<LumpFile> CreateLumps(string libil2cppDir, string outputDir) + { + BashUtil.RecreateDir(outputDir); + + string il2cppConfigFile = $"{libil2cppDir}/il2cpp-config.h"; + var lumpFiles = new List<LumpFile>(); + int lumpFileIndex = 0; + foreach (var cppDir in Directory.GetDirectories(libil2cppDir, "*", SearchOption.AllDirectories).Concat(new string[] {libil2cppDir})) + { + var lumpFile = new LumpFile($"{outputDir}/lump_{Path.GetFileName(cppDir)}_{lumpFileIndex}.cpp", il2cppConfigFile); + foreach (var file in Directory.GetFiles(cppDir, "*.cpp", SearchOption.TopDirectoryOnly)) + { + lumpFile.cppFiles.Add(file); + } + lumpFile.SaveFile(); + lumpFiles.Add(lumpFile); + ++lumpFileIndex; + } + + var mmFiles = Directory.GetFiles(libil2cppDir, "*.mm", SearchOption.AllDirectories); + if (mmFiles.Length > 0) + { + var lumpFile = new LumpFile($"{outputDir}/lump_mm.mm", il2cppConfigFile); + foreach (var file in mmFiles) + { + lumpFile.cppFiles.Add(file); + } + lumpFile.SaveFile(); + lumpFiles.Add(lumpFile); + } + return lumpFiles; + } + + private static List<string> GetExtraSourceFiles(string externalDir, string libil2cppDir) + { + var files = new List<string>(); + foreach (string extraDir in new string[] + { + $"{externalDir}/zlib", + $"{externalDir}/xxHash", + $"{libil2cppDir}/os/ClassLibraryPAL/brotli", + }) + { + if (!Directory.Exists(extraDir)) + { + continue; + } + files.AddRange(Directory.GetFiles(extraDir, "*.c", SearchOption.AllDirectories)); + } + return files; + } + } +} +#endif \ No newline at end of file diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/AddLil2cppSourceCodeToXcodeproj2019.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/AddLil2cppSourceCodeToXcodeproj2019.cs.meta new file mode 100644 index 0000000..64df093 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/AddLil2cppSourceCodeToXcodeproj2019.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d2f62ca12f2eb4f2fba8e9cb51279421 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/AddLil2cppSourceCodeToXcodeproj2020Or2021.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/AddLil2cppSourceCodeToXcodeproj2020Or2021.cs new file mode 100644 index 0000000..a7ebc3a --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/AddLil2cppSourceCodeToXcodeproj2020Or2021.cs @@ -0,0 +1,244 @@ +using System; +using HybridCLR.Editor.Installer; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using UnityEditor; +using System.Reflection; +using HybridCLR.Editor.Settings; +#if (UNITY_2020 || UNITY_2021) && (UNITY_IOS || UNITY_TVOS) +using UnityEditor.Build; +using UnityEditor.Callbacks; +using UnityEditor.iOS.Xcode; +using UnityEngine; + +namespace HybridCLR.Editor.BuildProcessors +{ + public static class AddLil2cppSourceCodeToXcodeproj2020Or2021 + { + + [PostProcessBuild] + public static void OnPostProcessBuild(BuildTarget target, string pathToBuiltProject) + { + if (!HybridCLRSettings.Instance.enable) + return; + /* + * 1. 鐢熸垚lump锛屽苟涓旀坊鍔犲埌宸ョ▼ + 3. 灏唋ibil2cpp鐩綍澶嶅埗鍒� Library/. 鍒犻櫎鏃х殑. search paths閲屼慨鏀� libil2cpp/include涓簂ibil2cpp + 3. Libraries/bdwgc/include -> Libraries/external/bdwgc/include + 4. 灏唀xternal鐩綍澶嶅埗鍒� Library/external銆傚垹闄ゆ棫鐩綍 + 5. 灏哃ibrary/external/baselib/Platforms/OSX鏀瑰悕涓� IOS 鍏ㄥぇ鍐� + 6. 灏� external/zlib涓媍 鏂囦欢娣诲姞鍒板伐绋� + 7. 绉婚櫎libil2cpp.a + 8. Include path add libil2cpp/os/ClassLibraryPAL/brotli/include + 9. add external/xxHash + */ + + string pbxprojFile = BuildProcessorUtil.GetXcodeProjectFile(pathToBuiltProject); + string srcLibil2cppDir = $"{SettingsUtil.LocalIl2CppDir}/libil2cpp"; + string dstLibil2cppDir = $"{pathToBuiltProject}/Libraries/libil2cpp"; + string lumpDir = $"{pathToBuiltProject}/Libraries/lumps"; + string srcExternalDir = $"{SettingsUtil.LocalIl2CppDir}/external"; + string dstExternalDir = $"{pathToBuiltProject}/Libraries/external"; + //RemoveExternalLibil2cppOption(srcExternalDir, dstExternalDir); + CopyLibil2cppToXcodeProj(srcLibil2cppDir, dstLibil2cppDir); + CopyExternalToXcodeProj(srcExternalDir, dstExternalDir); + var lumpFiles = CreateLumps(dstLibil2cppDir, lumpDir); + var extraSources = GetExtraSourceFiles(dstExternalDir, dstLibil2cppDir); + var cflags = new List<string>() + { + "-DIL2CPP_MONO_DEBUGGER_DISABLED", + }; + ModifyPBXProject(pathToBuiltProject, pbxprojFile, lumpFiles, extraSources, cflags); + } + + private static string GetRelativePathFromProj(string path) + { + return path.Substring(path.IndexOf("Libraries", StringComparison.Ordinal)).Replace('\\', '/'); + } + + private static void ModifyPBXProject(string pathToBuiltProject, string pbxprojFile, List<LumpFile> lumpFiles, List<string> extraFiles, List<string> cflags) + { + var proj = new PBXProject(); + proj.ReadFromFile(pbxprojFile); + string targetGUID = proj.GetUnityFrameworkTargetGuid(); + // 绉婚櫎鏃х殑libil2cpp.a + var libil2cppGUID = proj.FindFileGuidByProjectPath("Libraries/libil2cpp.a"); + if (!string.IsNullOrEmpty(libil2cppGUID)) + { + proj.RemoveFileFromBuild(targetGUID, libil2cppGUID); + proj.RemoveFile(libil2cppGUID); + File.Delete(Path.Combine(pathToBuiltProject, "Libraries", "libil2cpp.a")); + } + + //var lumpGroupGuid = proj.AddFile("Lumps", $"Classes/Lumps", PBXSourceTree.Group); + + foreach (var lumpFile in lumpFiles) + { + string lumpFileName = Path.GetFileName(lumpFile.lumpFile); + string projPathOfFile = $"Classes/Lumps/{lumpFileName}"; + string relativePathOfFile = GetRelativePathFromProj(lumpFile.lumpFile); + string lumpGuid = proj.FindFileGuidByProjectPath(projPathOfFile); + if (!string.IsNullOrEmpty(lumpGuid)) + { + proj.RemoveFileFromBuild(targetGUID, lumpGuid); + proj.RemoveFile(lumpGuid); + } + lumpGuid = proj.AddFile(relativePathOfFile, projPathOfFile, PBXSourceTree.Source); + proj.AddFileToBuild(targetGUID, lumpGuid); + } + + foreach (var extraFile in extraFiles) + { + string projPathOfFile = $"Classes/Extrals/{Path.GetFileName(extraFile)}"; + string extraFileGuid = proj.FindFileGuidByProjectPath(projPathOfFile); + if (!string.IsNullOrEmpty(extraFileGuid)) + { + proj.RemoveFileFromBuild(targetGUID, extraFileGuid); + proj.RemoveFile(extraFileGuid); + //Debug.LogWarning($"remove exist extra file:{projPathOfFile} guid:{extraFileGuid}"); + } + var lumpGuid = proj.AddFile(GetRelativePathFromProj(extraFile), projPathOfFile, PBXSourceTree.Source); + proj.AddFileToBuild(targetGUID, lumpGuid); + } + + foreach(var configName in proj.BuildConfigNames()) + { + //Debug.Log($"build config:{bcn}"); + string configGuid = proj.BuildConfigByName(targetGUID, configName); + string headerSearchPaths = "HEADER_SEARCH_PATHS"; + string hspProp = proj.GetBuildPropertyForConfig(configGuid, headerSearchPaths); + //Debug.Log($"config guid:{configGuid} prop:{hspProp}"); + string newPro = hspProp.Replace("libil2cpp/include", "libil2cpp") + .Replace("Libraries/bdwgc", "Libraries/external/bdwgc"); + + if (!newPro.Contains("Libraries/libil2cpp/os/ClassLibraryPAL/brotli/include")) + { + newPro += " $(SRCROOT)/Libraries/libil2cpp/os/ClassLibraryPAL/brotli/include"; + } + if (!newPro.Contains("Libraries/external/xxHash")) + { + newPro += " $(SRCROOT)/Libraries/external/xxHash"; + } + newPro += " $(SRCR00T)/Libraries/external/mono"; + //Debug.Log($"config:{bcn} new prop:{newPro}"); + proj.SetBuildPropertyForConfig(configGuid, headerSearchPaths, newPro); + + string cflagKey = "OTHER_CFLAGS"; + string cfProp = proj.GetBuildPropertyForConfig(configGuid, cflagKey); + foreach (var flag in cflags) + { + if (!cfProp.Contains(flag)) + { + cfProp += " " + flag; + } + } + if (configName.Contains("Debug") && !cfProp.Contains("-DIL2CPP_DEBUG=")) + { + cfProp += " -DIL2CPP_DEBUG=1 -DDEBUG=1"; + } + proj.SetBuildPropertyForConfig(configGuid, cflagKey, cfProp); + + } + proj.WriteToFile(pbxprojFile); + } + + private static void CopyLibil2cppToXcodeProj(string srcLibil2cppDir, string dstLibil2cppDir) + { + BashUtil.RemoveDir(dstLibil2cppDir); + BashUtil.CopyDir(srcLibil2cppDir, dstLibil2cppDir, true); + } + + + private static void CopyExternalToXcodeProj(string srcExternalDir, string dstExternalDir) + { + BashUtil.RemoveDir(dstExternalDir); + BashUtil.CopyDir(srcExternalDir, dstExternalDir, true); + + string baselibPlatfromsDir = $"{dstExternalDir}/baselib/Platforms"; + BashUtil.RemoveDir($"{baselibPlatfromsDir}/IOS"); + BashUtil.CopyDir($"{baselibPlatfromsDir}/OSX", $"{baselibPlatfromsDir}/IOS", true); + } + + class LumpFile + { + public List<string> cppFiles = new List<string>(); + + public readonly string lumpFile; + + public readonly string il2cppConfigFile; + + public LumpFile(string lumpFile, string il2cppConfigFile) + { + this.lumpFile = lumpFile; + this.il2cppConfigFile = il2cppConfigFile; + this.cppFiles.Add(il2cppConfigFile); + } + + public void SaveFile() + { + var lumpFileContent = new List<string>(); + foreach (var file in cppFiles) + { + lumpFileContent.Add($"#include \"{GetRelativePathFromProj(file)}\""); + } + File.WriteAllLines(lumpFile, lumpFileContent, Encoding.UTF8); + Debug.Log($"create lump file:{lumpFile}"); + } + } + + private static List<LumpFile> CreateLumps(string libil2cppDir, string outputDir) + { + BashUtil.RecreateDir(outputDir); + + string il2cppConfigFile = $"{libil2cppDir}/il2cpp-config.h"; + var lumpFiles = new List<LumpFile>(); + int lumpFileIndex = 0; + foreach (var cppDir in Directory.GetDirectories(libil2cppDir, "*", SearchOption.AllDirectories).Concat(new string[] {libil2cppDir})) + { + var lumpFile = new LumpFile($"{outputDir}/lump_{Path.GetFileName(cppDir)}_{lumpFileIndex}.cpp", il2cppConfigFile); + foreach (var file in Directory.GetFiles(cppDir, "*.cpp", SearchOption.TopDirectoryOnly)) + { + lumpFile.cppFiles.Add(file); + } + lumpFile.SaveFile(); + lumpFiles.Add(lumpFile); + ++lumpFileIndex; + } + + var mmFiles = Directory.GetFiles(libil2cppDir, "*.mm", SearchOption.AllDirectories); + if (mmFiles.Length > 0) + { + var lumpFile = new LumpFile($"{outputDir}/lump_mm.mm", il2cppConfigFile); + foreach (var file in mmFiles) + { + lumpFile.cppFiles.Add(file); + } + lumpFile.SaveFile(); + lumpFiles.Add(lumpFile); + } + return lumpFiles; + } + + private static List<string> GetExtraSourceFiles(string externalDir, string libil2cppDir) + { + var files = new List<string>(); + foreach (string extraDir in new string[] + { + $"{externalDir}/zlib", + $"{externalDir}/xxHash", + $"{libil2cppDir}/os/ClassLibraryPAL/brotli", + }) + { + if (!Directory.Exists(extraDir)) + { + continue; + } + files.AddRange(Directory.GetFiles(extraDir, "*.c", SearchOption.AllDirectories)); + } + return files; + } + } +} +#endif \ No newline at end of file diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/AddLil2cppSourceCodeToXcodeproj2020Or2021.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/AddLil2cppSourceCodeToXcodeproj2020Or2021.cs.meta new file mode 100644 index 0000000..7eba538 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/AddLil2cppSourceCodeToXcodeproj2020Or2021.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 61948fcb1bc40ba47b8c10b0ae801ebb +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/AddLil2cppSourceCodeToXcodeproj2022OrNewer.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/AddLil2cppSourceCodeToXcodeproj2022OrNewer.cs new file mode 100644 index 0000000..084e388 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/AddLil2cppSourceCodeToXcodeproj2022OrNewer.cs @@ -0,0 +1,82 @@ +using HybridCLR.Editor.Installer; +using HybridCLR.Editor.Settings; +using System.IO; +using System.Text; +using System.Text.RegularExpressions; +using UnityEditor; +using UnityEditor.Build; +using UnityEditor.Callbacks; +using UnityEngine; + +#if UNITY_2022 && (UNITY_IOS || UNITY_TVOS || UNITY_VISIONOS) + +namespace HybridCLR.Editor.BuildProcessors +{ + public static class AddLil2cppSourceCodeToXcodeproj2022OrNewer + { + + [PostProcessBuild] + public static void OnPostProcessBuild(BuildTarget target, string pathToBuiltProject) + { + if (!HybridCLRSettings.Instance.enable) + return; + string pbxprojFile = BuildProcessorUtil.GetXcodeProjectFile(pathToBuiltProject); + RemoveExternalLibil2cppOption(pbxprojFile); + CopyLibil2cppToXcodeProj(pathToBuiltProject); + } + + private static string TryRemoveDunplicateShellScriptSegment(string pbxprojFile, string pbxprojContent) + { + // will appear duplicated Shell Script segment when append to existed xcode project. + // This is unity bug. + // we remove duplicated Shell Script to avoid build error. + string copyFileComment = @"/\* CopyFiles \*/,\s+([A-Z0-9]{24}) /\* ShellScript \*/,\s+([A-Z0-9]{24}) /\* ShellScript \*/,"; + var m = Regex.Match(pbxprojContent, copyFileComment, RegexOptions.Multiline); + if (!m.Success) + { + return pbxprojContent; + } + + if (m.Groups[1].Value != m.Groups[2].Value) + { + throw new BuildFailedException($"find invalid /* ShellScript */ segment"); + } + + int startIndexOfDupShellScript = m.Groups[2].Index; + int endIndexOfDupShellScript = pbxprojContent.IndexOf(",", startIndexOfDupShellScript); + + pbxprojContent = pbxprojContent.Remove(startIndexOfDupShellScript, endIndexOfDupShellScript + 1 - startIndexOfDupShellScript); + Debug.LogWarning($"[AddLil2cppSourceCodeToXcodeproj] remove duplicated '/* ShellScript */' from file '{pbxprojFile}'"); + return pbxprojContent; + } + + private static void RemoveExternalLibil2cppOption(string pbxprojFile) + { + string pbxprojContent = File.ReadAllText(pbxprojFile, Encoding.UTF8); + string removeBuildOption = @"--external-lib-il2-cpp=\""$PROJECT_DIR/Libraries/libil2cpp.a\"""; + if (pbxprojContent.Contains(removeBuildOption)) + { + pbxprojContent = pbxprojContent.Replace(removeBuildOption, ""); + Debug.Log($"[AddLil2cppSourceCodeToXcodeproj] remove il2cpp build option '{removeBuildOption}' from file '{pbxprojFile}'"); + } + else + { + Debug.LogWarning($"[AddLil2cppSourceCodeToXcodeproj] project.pbxproj remove building option:'{removeBuildOption}' fail. This may occur when 'Append' to existing xcode project in building"); + } + + pbxprojContent = TryRemoveDunplicateShellScriptSegment(pbxprojFile, pbxprojContent); + + + File.WriteAllText(pbxprojFile, pbxprojContent, Encoding.UTF8); + } + + private static void CopyLibil2cppToXcodeProj(string pathToBuiltProject) + { + string srcLibil2cppDir = $"{SettingsUtil.LocalIl2CppDir}/libil2cpp"; + string destLibil2cppDir = $"{pathToBuiltProject}/Il2CppOutputProject/IL2CPP/libil2cpp"; + BashUtil.RemoveDir(destLibil2cppDir); + BashUtil.CopyDir(srcLibil2cppDir, destLibil2cppDir, true); + } + } +} +#endif \ No newline at end of file diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/AddLil2cppSourceCodeToXcodeproj2022OrNewer.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/AddLil2cppSourceCodeToXcodeproj2022OrNewer.cs.meta new file mode 100644 index 0000000..e71a765 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/AddLil2cppSourceCodeToXcodeproj2022OrNewer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a4ce072f7e4a17248a3d9ebfd011356b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/AddLil2cppSourceCodeToXcodeproj2023OrNewer.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/AddLil2cppSourceCodeToXcodeproj2023OrNewer.cs new file mode 100644 index 0000000..a3c880c --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/AddLil2cppSourceCodeToXcodeproj2023OrNewer.cs @@ -0,0 +1,34 @@ +using HybridCLR.Editor.Installer; +using HybridCLR.Editor.Settings; +using System.IO; +using System.Text; +using UnityEditor; +using UnityEditor.Build; +using UnityEditor.Callbacks; +using UnityEngine; + +#if UNITY_2023_1_OR_NEWER && (UNITY_IOS || UNITY_TVOS || UNITY_VISIONOS) + +namespace HybridCLR.Editor.BuildProcessors +{ + public static class AddLil2cppSourceCodeToXcodeproj2022OrNewer + { + + [PostProcessBuild] + public static void OnPostProcessBuild(BuildTarget target, string pathToBuiltProject) + { + if (!HybridCLRSettings.Instance.enable) + return; + CopyLibil2cppToXcodeProj(pathToBuiltProject); + } + + private static void CopyLibil2cppToXcodeProj(string pathToBuiltProject) + { + string srcLibil2cppDir = $"{SettingsUtil.LocalIl2CppDir}/libil2cpp"; + string destLibil2cppDir = $"{pathToBuiltProject}/Il2CppOutputProject/IL2CPP/libil2cpp"; + BashUtil.RemoveDir(destLibil2cppDir); + BashUtil.CopyDir(srcLibil2cppDir, destLibil2cppDir, true); + } + } +} +#endif \ No newline at end of file diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/AddLil2cppSourceCodeToXcodeproj2023OrNewer.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/AddLil2cppSourceCodeToXcodeproj2023OrNewer.cs.meta new file mode 100644 index 0000000..af06bb0 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/AddLil2cppSourceCodeToXcodeproj2023OrNewer.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 2fa46135129b046a28014d58fdfd18ca \ No newline at end of file diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/BuildProcessorUtil.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/BuildProcessorUtil.cs new file mode 100644 index 0000000..7bb4f77 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/BuildProcessorUtil.cs @@ -0,0 +1,25 @@ +锘縰sing System; +using System.IO; +using UnityEditor.Build; + +namespace HybridCLR.Editor.BuildProcessors +{ + + public static class BuildProcessorUtil + { + + public static string GetXcodeProjectFile(string pathToBuiltProject) + { + foreach (string dir in Directory.GetDirectories(pathToBuiltProject, "*.xcodeproj", SearchOption.TopDirectoryOnly)) + { + string pbxprojFile = $"{dir}/project.pbxproj"; + if (File.Exists(pbxprojFile)) + { + return pbxprojFile; + } + } + throw new BuildFailedException($"can't find xxxx.xcodeproj/project.pbxproj in {pathToBuiltProject}"); + } + } +} + diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/BuildProcessorUtil.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/BuildProcessorUtil.cs.meta new file mode 100644 index 0000000..6cd79d2 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/BuildProcessorUtil.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c680e56f90f2745298a90803c04f6efc +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/CheckSettings.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/CheckSettings.cs new file mode 100644 index 0000000..994683b --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/CheckSettings.cs @@ -0,0 +1,94 @@ +锘縰sing HybridCLR.Editor.Settings; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using UnityEditor; +using UnityEditor.Build; +using UnityEditor.Build.Reporting; +using UnityEngine; +using static UnityEngine.GraphicsBuffer; + +namespace HybridCLR.Editor.BuildProcessors +{ + internal class CheckSettings : IPreprocessBuildWithReport + { + public int callbackOrder => 0; + + public static bool DisableMethodBridgeDevelopmentFlagChecking { get; set; } + + public void OnPreprocessBuild(BuildReport report) + { + HybridCLRSettings globalSettings = SettingsUtil.HybridCLRSettings; + if (!globalSettings.enable || globalSettings.useGlobalIl2cpp) + { + string oldIl2cppPath = Environment.GetEnvironmentVariable("UNITY_IL2CPP_PATH"); + if (!string.IsNullOrEmpty(oldIl2cppPath)) + { + Environment.SetEnvironmentVariable("UNITY_IL2CPP_PATH", ""); + Debug.Log($"[CheckSettings] clean process environment variable: UNITY_IL2CPP_PATH, old vlaue:'{oldIl2cppPath}'"); + } + } + else + { + string curIl2cppPath = Environment.GetEnvironmentVariable("UNITY_IL2CPP_PATH"); + if (curIl2cppPath != SettingsUtil.LocalIl2CppDir) + { + Environment.SetEnvironmentVariable("UNITY_IL2CPP_PATH", SettingsUtil.LocalIl2CppDir); + Debug.Log($"[CheckSettings] UNITY_IL2CPP_PATH old value:'{curIl2cppPath}'锛� new value:'{SettingsUtil.LocalIl2CppDir}'"); + } + } + if (!globalSettings.enable) + { + return; + } + BuildTargetGroup buildTargetGroup = BuildPipeline.GetBuildTargetGroup(EditorUserBuildSettings.activeBuildTarget); + ScriptingImplementation curScriptingImplementation = PlayerSettings.GetScriptingBackend(buildTargetGroup); + ScriptingImplementation targetScriptingImplementation = ScriptingImplementation.IL2CPP; + if (curScriptingImplementation != targetScriptingImplementation) + { + Debug.LogError($"[CheckSettings] current ScriptingBackend:{curScriptingImplementation}锛宧ave been switched to:{targetScriptingImplementation} automatically"); + PlayerSettings.SetScriptingBackend(buildTargetGroup, targetScriptingImplementation); + } + + var installer = new Installer.InstallerController(); + if (!installer.HasInstalledHybridCLR()) + { + throw new BuildFailedException($"You have not initialized HybridCLR, please install it via menu 'HybridCLR/Installer'"); + } + + if (installer.PackageVersion != installer.InstalledLibil2cppVersion) + { + throw new BuildFailedException($"You must run `HybridCLR/Installer` after upgrading package"); + } + + HybridCLRSettings gs = SettingsUtil.HybridCLRSettings; + if (((gs.hotUpdateAssemblies?.Length + gs.hotUpdateAssemblyDefinitions?.Length) ?? 0) == 0) + { + Debug.LogWarning("[CheckSettings] No hot update modules configured in HybridCLRSettings"); + } + + if (!DisableMethodBridgeDevelopmentFlagChecking) + { + string methodBridgeFile = $"{SettingsUtil.GeneratedCppDir}/MethodBridge.cpp"; + var match = Regex.Match(File.ReadAllText(methodBridgeFile), @"// DEVELOPMENT=(\d)"); + if (match.Success) + { + int developmentFlagInMethodBridge = int.Parse(match.Groups[1].Value); + int developmentFlagInEditorSettings = EditorUserBuildSettings.development ? 1 : 0; + if (developmentFlagInMethodBridge != developmentFlagInEditorSettings) + { + Debug.LogError($"[CheckSettings] MethodBridge.cpp DEVELOPMENT flag:{developmentFlagInMethodBridge} is inconsistent with EditorUserBuildSettings.development:{developmentFlagInEditorSettings}. Please run 'HybridCLR/Generate/All' before building."); + } + } + else + { + Debug.LogError("[CheckSettings] MethodBridge.cpp DEVELOPMENT flag not found. Please run 'HybridCLR/Generate/All' before building."); + } + } + } + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/CheckSettings.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/CheckSettings.cs.meta new file mode 100644 index 0000000..0cc3643 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/CheckSettings.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: fb4ba063068b17247b2d0233420aa5f0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/CopyStrippedAOTAssemblies.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/CopyStrippedAOTAssemblies.cs new file mode 100644 index 0000000..9630316 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/CopyStrippedAOTAssemblies.cs @@ -0,0 +1,134 @@ +using HybridCLR.Editor.Installer; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UnityEditor; +using UnityEditor.Build; +using UnityEditor.Build.Reporting; +using UnityEditor.UnityLinker; +using UnityEngine; +#if !UNITY_2021_1_OR_NEWER +using UnityEditor.Il2Cpp; +#endif + +namespace HybridCLR.Editor.BuildProcessors +{ + internal class CopyStrippedAOTAssemblies : IPostprocessBuildWithReport, IPreprocessBuildWithReport +#if !UNITY_2021_1_OR_NEWER + , IIl2CppProcessor +#endif + { + + public int callbackOrder => 0; + +#if UNITY_2021_1_OR_NEWER + public static string GetStripAssembliesDir2021(BuildTarget target) + { + string projectDir = SettingsUtil.ProjectDir; + switch (target) + { + case BuildTarget.StandaloneWindows: + case BuildTarget.StandaloneWindows64: + return $"{projectDir}/Library/Bee/artifacts/WinPlayerBuildProgram/ManagedStripped"; + case BuildTarget.StandaloneLinux64: + return $"{projectDir}/Library/Bee/artifacts/LinuxPlayerBuildProgram/ManagedStripped"; + case BuildTarget.WSAPlayer: + return $"{projectDir}/Library/Bee/artifacts/UWPPlayerBuildProgram/ManagedStripped"; + case BuildTarget.Android: + return $"{projectDir}/Library/Bee/artifacts/Android/ManagedStripped"; +#if TUANJIE_2022_3_OR_NEWER + case BuildTarget.HMIAndroid: + return $"{projectDir}/Library/Bee/artifacts/HMIAndroid/ManagedStripped"; +#endif + case BuildTarget.iOS: +#if UNITY_TVOS + case BuildTarget.tvOS: +#endif + return $"{projectDir}/Library/Bee/artifacts/iOS/ManagedStripped"; +#if UNITY_VISIONOS + case BuildTarget.VisionOS: +#if UNITY_6000_0_OR_NEWER + return $"{projectDir}/Library/Bee/artifacts/VisionOS/ManagedStripped"; +#else + return $"{projectDir}/Library/Bee/artifacts/iOS/ManagedStripped"; +#endif +#endif + case BuildTarget.WebGL: + return $"{projectDir}/Library/Bee/artifacts/WebGL/ManagedStripped"; + case BuildTarget.StandaloneOSX: + return $"{projectDir}/Library/Bee/artifacts/MacStandalonePlayerBuildProgram/ManagedStripped"; + case BuildTarget.PS4: + return $"{projectDir}/Library/Bee/artifacts/PS4PlayerBuildProgram/ManagedStripped"; + case BuildTarget.PS5: + return $"{projectDir}/Library/Bee/artifacts/PS5PlayerBuildProgram/ManagedStripped"; +#if UNITY_WEIXINMINIGAME + case BuildTarget.WeixinMiniGame: + return $"{projectDir}/Library/Bee/artifacts/WeixinMiniGame/ManagedStripped"; +#endif +#if UNITY_OPENHARMONY + case BuildTarget.OpenHarmony: + return $"{projectDir}/Library/Bee/artifacts/OpenHarmonyPlayerBuildProgram/ManagedStripped"; +#endif + default: return ""; + } + } +#else + private string GetStripAssembliesDir2020(BuildTarget target) + { + string subPath = target == BuildTarget.Android ? + "assets/bin/Data/Managed" : + "Data/Managed/"; + return $"{SettingsUtil.ProjectDir}/Temp/StagingArea/{subPath}"; + } + + public void OnBeforeConvertRun(BuildReport report, Il2CppBuildPipelineData data) + { + BuildTarget target = report.summary.platform; + CopyStripDlls(GetStripAssembliesDir2020(target), target); + } +#endif + + public static void CopyStripDlls(string srcStripDllPath, BuildTarget target) + { + if (!SettingsUtil.Enable) + { + Debug.Log($"[CopyStrippedAOTAssemblies] disabled"); + return; + } + Debug.Log($"[CopyStrippedAOTAssemblies] CopyScripDlls. src:{srcStripDllPath} target:{target}"); + + var dstPath = SettingsUtil.GetAssembliesPostIl2CppStripDir(target); + + Directory.CreateDirectory(dstPath); + + foreach (var fileFullPath in Directory.GetFiles(srcStripDllPath, "*.dll")) + { + var file = Path.GetFileName(fileFullPath); + Debug.Log($"[CopyStrippedAOTAssemblies] copy strip dll {fileFullPath} ==> {dstPath}/{file}"); + File.Copy($"{fileFullPath}", $"{dstPath}/{file}", true); + } + } + + public void OnPostprocessBuild(BuildReport report) + { +#if UNITY_2021_1_OR_NEWER + BuildTarget target = report.summary.platform; + string srcStripDllPath = GetStripAssembliesDir2021(target); + if (!string.IsNullOrEmpty(srcStripDllPath) && Directory.Exists(srcStripDllPath)) + { + CopyStripDlls(srcStripDllPath, target); + } +#endif + } + + public void OnPreprocessBuild(BuildReport report) + { + BuildTarget target = report.summary.platform; + var dstPath = SettingsUtil.GetAssembliesPostIl2CppStripDir(target); + BashUtil.RecreateDir(dstPath); + } + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/CopyStrippedAOTAssemblies.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/CopyStrippedAOTAssemblies.cs.meta new file mode 100644 index 0000000..3ebc0e1 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/CopyStrippedAOTAssemblies.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f7884710ec2f8e545b3fe9aa05def5a8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/FilterHotFixAssemblies.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/FilterHotFixAssemblies.cs new file mode 100644 index 0000000..1cb56b6 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/FilterHotFixAssemblies.cs @@ -0,0 +1,68 @@ +锘縰sing HybridCLR.Editor.Meta; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UnityEditor; +using UnityEditor.Build; +using UnityEngine; + +namespace HybridCLR.Editor.BuildProcessors +{ + /// <summary> + /// 灏嗙儹鏇存柊dll浠嶣uild杩囩▼涓繃婊わ紝闃叉鎵撳寘鍒颁富宸ョ▼涓� + /// </summary> + internal class FilterHotFixAssemblies : IFilterBuildAssemblies + { + public int callbackOrder => 0; + + public string[] OnFilterAssemblies(BuildOptions buildOptions, string[] assemblies) + { + if (!SettingsUtil.Enable) + { + Debug.Log($"[FilterHotFixAssemblies] disabled"); + return assemblies; + } + List<string> allHotUpdateDllNames = SettingsUtil.HotUpdateAssemblyNamesExcludePreserved; + + // 妫�鏌ユ槸鍚﹂噸澶嶅~鍐� + var hotUpdateDllSet = new HashSet<string>(); + foreach(var hotUpdateDll in allHotUpdateDllNames) + { + if (string.IsNullOrWhiteSpace(hotUpdateDll)) + { + throw new BuildFailedException($"hot update assembly name cann't be empty"); + } + if (!hotUpdateDllSet.Add(hotUpdateDll)) + { + throw new BuildFailedException($"hot update assembly:{hotUpdateDll} is duplicated"); + } + } + + var assResolver = MetaUtil.CreateHotUpdateAssemblyResolver(EditorUserBuildSettings.activeBuildTarget, allHotUpdateDllNames); + // 妫�鏌ユ槸鍚﹀~鍐欎簡姝g‘鐨刣ll鍚嶇О + foreach (var hotUpdateDllName in allHotUpdateDllNames) + { + if (assemblies.Select(Path.GetFileNameWithoutExtension).All(ass => ass != hotUpdateDllName) + && string.IsNullOrEmpty(assResolver.ResolveAssembly(hotUpdateDllName, false))) + { + throw new BuildFailedException($"hot update assembly:{hotUpdateDllName} doesn't exist"); + } + } + + // 灏嗙儹鏇磀ll浠庢墦鍖呭垪琛ㄤ腑绉婚櫎 + return assemblies.Where(ass => + { + string assName = Path.GetFileNameWithoutExtension(ass); + bool reserved = allHotUpdateDllNames.All(dll => !assName.Equals(dll, StringComparison.Ordinal)); + if (!reserved) + { + Debug.Log($"[FilterHotFixAssemblies] filter assembly:{assName}"); + } + return reserved; + }).ToArray(); + } + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/FilterHotFixAssemblies.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/FilterHotFixAssemblies.cs.meta new file mode 100644 index 0000000..2ab4ba5 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/FilterHotFixAssemblies.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9dec2922e3df5464aa047b636eb19e0d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/MsvcStdextWorkaround.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/MsvcStdextWorkaround.cs new file mode 100644 index 0000000..f01a4dc --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/MsvcStdextWorkaround.cs @@ -0,0 +1,32 @@ +#if UNITY_EDITOR +using System; +using UnityEditor.Build; +using UnityEditor.Build.Reporting; + +namespace HybridCLR.Editor.BuildProcessors +{ + + public class MsvcStdextWorkaround : IPreprocessBuildWithReport + { + const string kWorkaroundFlag = "/D_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS"; + + public int callbackOrder => 0; + + public void OnPreprocessBuild(BuildReport report) + { + var clEnv = Environment.GetEnvironmentVariable("_CL_"); + + if (string.IsNullOrEmpty(clEnv)) + { + Environment.SetEnvironmentVariable("_CL_", kWorkaroundFlag); + } + else if (!clEnv.Contains(kWorkaroundFlag)) + { + clEnv += " " + kWorkaroundFlag; + Environment.SetEnvironmentVariable("_CL_", clEnv); + } + } + } +} + +#endif // UNITY_EDITOR diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/MsvcStdextWorkaround.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/MsvcStdextWorkaround.cs.meta new file mode 100644 index 0000000..ef28c51 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/MsvcStdextWorkaround.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8bff6cadf0b8db54b87ba51b24d080f6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/PatchScriptingAssemblyList.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/PatchScriptingAssemblyList.cs new file mode 100644 index 0000000..b376fc5 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/PatchScriptingAssemblyList.cs @@ -0,0 +1,189 @@ +锘縰sing HybridCLR.Editor.UnityBinFileReader; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UnityEditor; +using UnityEditor.Android; +using UnityEditor.Build; +using UnityEditor.Build.Reporting; +using UnityEditor.UnityLinker; +using UnityEngine; +using UnityFS; +#if !UNITY_2023_1_OR_NEWER +using UnityEditor.Il2Cpp; +#endif + +namespace HybridCLR.Editor.BuildProcessors +{ + public class PatchScriptingAssemblyList : +#if UNITY_ANDROID + IPostGenerateGradleAndroidProject, +#elif UNITY_OPENHARMONY + UnityEditor.OpenHarmony.IPostGenerateOpenHarmonyProject, +#endif + IPostprocessBuildWithReport +#if !UNITY_2021_1_OR_NEWER && UNITY_WEBGL + , IIl2CppProcessor +#endif + +#if UNITY_PS5 + , IUnityLinkerProcessor +#endif + + { + public int callbackOrder => 0; + + public void OnPostGenerateGradleAndroidProject(string path) + { + // 濡傛灉鐩存帴鎵撳寘apk锛屾病鏈夋満浼氬湪PostprocessBuild涓慨鏀筍criptingAssemblies.json銆� + // 鍥犳闇�瑕佸湪杩欎釜鏃舵満澶勭悊 + // Unity鏈塨ug锛屽伓鐒舵儏鍐典笅浼氫紶鍏pk鐨勮矾寰勶紝瀵艰嚧鏇挎崲澶辫触 + if (Directory.Exists(path)) + { + PathScriptingAssembilesFile(path); + } + else + { + PathScriptingAssembilesFile($"{SettingsUtil.ProjectDir}/Library"); + } + } + +#if UNITY_OPENHARMONY + + public void OnPostGenerateOpenHarmonyProject(string path) + { + OnPostGenerateGradleAndroidProject(path); + } + +#endif + + public void OnPostprocessBuild(BuildReport report) + { + // 濡傛灉target涓篈ndroid,鐢变簬宸茬粡鍦∣nPostGenerateGradelAndroidProject涓鐞嗚繃锛� + // 杩欓噷涓嶅啀閲嶅澶勭悊 +#if !UNITY_ANDROID && !UNITY_WEBGL && !UNITY_OPENHARMONY + PathScriptingAssembilesFile(report.summary.outputPath); +#endif + } + +#if UNITY_PS5 + /// <summary> + /// 鎵撳寘妯″紡濡傛灉鏄� Package 闇�瑕佸湪杩欎釜闃舵鎻愬墠澶勭悊 .json , PC Hosted 鍜� GP5 妯″紡涓嶅彈褰卞搷 + /// </summary> + + public string GenerateAdditionalLinkXmlFile(UnityEditor.Build.Reporting.BuildReport report, UnityEditor.UnityLinker.UnityLinkerBuildPipelineData data) + { + string path = $"{SettingsUtil.ProjectDir}/Library/PlayerDataCache/PS5/Data"; + PathScriptingAssembilesFile(path); + return null; + } +#endif + public void PathScriptingAssembilesFile(string path) + { + if (!SettingsUtil.Enable) + { + Debug.Log($"[PatchScriptingAssemblyList] disabled"); + return; + } + Debug.Log($"[PatchScriptingAssemblyList]. path:{path}"); + if (!Directory.Exists(path)) + { + path = Path.GetDirectoryName(path); + Debug.Log($"[PatchScriptingAssemblyList] get path parent:{path}"); + } +#if UNITY_2020_1_OR_NEWER + AddHotFixAssembliesToScriptingAssembliesJson(path); +#else + AddHotFixAssembliesToBinFile(path); +#endif + } + + private void AddHotFixAssembliesToScriptingAssembliesJson(string path) + { + Debug.Log($"[PatchScriptingAssemblyList]. path:{path}"); + /* + * ScriptingAssemblies.json 鏂囦欢涓褰曚簡鎵�鏈夌殑dll鍚嶇О锛屾鍒楄〃鍦ㄦ父鎴忓惎鍔ㄦ椂鑷姩鍔犺浇锛� + * 涓嶅湪姝ゅ垪琛ㄤ腑鐨刣ll鍦ㄨ祫婧愬弽搴忓垪鍖栨椂鏃犳硶琚壘鍒板叾绫诲瀷 + * 鍥犳 OnFilterAssemblies 涓Щ闄ょ殑鏉$洰闇�瑕佸啀鍔犲洖鏉� + */ + string[] jsonFiles = Directory.GetFiles(path, SettingsUtil.ScriptingAssembliesJsonFile, SearchOption.AllDirectories); + + if (jsonFiles.Length == 0) + { + Debug.LogWarning($"can not find file {SettingsUtil.ScriptingAssembliesJsonFile}"); + return; + } + + foreach (string file in jsonFiles) + { + var patcher = new ScriptingAssembliesJsonPatcher(); + patcher.Load(file); + patcher.AddScriptingAssemblies(SettingsUtil.HotUpdateAssemblyFilesIncludePreserved); + patcher.Save(file); + } + } + private void AddHotFixAssembliesToBinFile(string path) + { +#if UNITY_STANDALONE_OSX + path = Path.GetDirectoryName(path); +#endif + if (AddHotFixAssembliesToGlobalgamemanagers(path)) + { + return; + } + if (AddHotFixAssembliesTodataunity3d(path)) + { + return; + } + Debug.LogError($"[PatchScriptingAssemblyList] can not find file '{SettingsUtil.GlobalgamemanagersBinFile}' or '{SettingsUtil.Dataunity3dBinFile}' in '{path}'"); + } + + private bool AddHotFixAssembliesToGlobalgamemanagers(string path) + { + string[] binFiles = Directory.GetFiles(path, SettingsUtil.GlobalgamemanagersBinFile, SearchOption.AllDirectories); + + if (binFiles.Length == 0) + { + return false; + } + + foreach (string binPath in binFiles) + { + var binFile = new UnityBinFile(); + binFile.Load(binPath); + binFile.AddScriptingAssemblies(SettingsUtil.HotUpdateAssemblyFilesIncludePreserved); + binFile.Save(binPath); + Debug.Log($"[PatchScriptingAssemblyList] patch {binPath}"); + } + return true; + } + + private bool AddHotFixAssembliesTodataunity3d(string path) + { + string[] binFiles = Directory.GetFiles(path, SettingsUtil.Dataunity3dBinFile, SearchOption.AllDirectories); + + if (binFiles.Length == 0) + { + return false; + } + + foreach (string binPath in binFiles) + { + var patcher = new Dataunity3dPatcher(); + patcher.ApplyPatch(binPath, SettingsUtil.HotUpdateAssemblyFilesIncludePreserved); + Debug.Log($"[PatchScriptingAssemblyList] patch {binPath}"); + } + return true; + } + +#if UNITY_WEBGL && !UNITY_2022_3_OR_NEWER + public void OnBeforeConvertRun(BuildReport report, Il2CppBuildPipelineData data) + { + PathScriptingAssembilesFile($"{SettingsUtil.ProjectDir}/Temp/StagingArea/Data"); + } +#endif + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/PatchScriptingAssemblyList.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/PatchScriptingAssemblyList.cs.meta new file mode 100644 index 0000000..0affdc7 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/PatchScriptingAssemblyList.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9bb6e2908d8948648979c9ff6bb7937d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/ScriptingAssembliesJsonPatcher.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/ScriptingAssembliesJsonPatcher.cs new file mode 100644 index 0000000..a124e34 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/ScriptingAssembliesJsonPatcher.cs @@ -0,0 +1,50 @@ +锘縰sing System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UnityEngine; + +namespace HybridCLR.Editor.BuildProcessors +{ + public class ScriptingAssembliesJsonPatcher + { + [Serializable] + private class ScriptingAssemblies + { + public List<string> names; + public List<int> types; + } + + private string _file; + ScriptingAssemblies _scriptingAssemblies; + + public void Load(string file) + { + _file = file; + string content = File.ReadAllText(file); + _scriptingAssemblies = JsonUtility.FromJson<ScriptingAssemblies>(content); + } + + public void AddScriptingAssemblies(List<string> assemblies) + { + foreach (string name in assemblies) + { + if (!_scriptingAssemblies.names.Contains(name)) + { + _scriptingAssemblies.names.Add(name); + _scriptingAssemblies.types.Add(16); // user dll type + Debug.Log($"[PatchScriptAssembliesJson] add hotfix assembly:{name} to {_file}"); + } + } + } + + public void Save(string jsonFile) + { + string content = JsonUtility.ToJson(_scriptingAssemblies); + + File.WriteAllText(jsonFile, content); + } + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/ScriptingAssembliesJsonPatcher.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/ScriptingAssembliesJsonPatcher.cs.meta new file mode 100644 index 0000000..c4c07e0 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/BuildProcessors/ScriptingAssembliesJsonPatcher.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4455f7304f8678f408dd6cf21734f55e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Commands.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Commands.meta new file mode 100644 index 0000000..c61c778 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Commands.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 92f51c069d2607447ae2f61de80540fb +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Commands/AOTReferenceGeneratorCommand.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Commands/AOTReferenceGeneratorCommand.cs new file mode 100644 index 0000000..b4dfb41 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Commands/AOTReferenceGeneratorCommand.cs @@ -0,0 +1,132 @@ +锘縰sing HybridCLR.Editor.AOT; +using HybridCLR.Editor.Meta; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UnityEditor; +using UnityEngine; + +namespace HybridCLR.Editor.Commands +{ + using Analyzer = HybridCLR.Editor.AOT.Analyzer; + public static class AOTReferenceGeneratorCommand + { + + [MenuItem("HybridCLR/Generate/AOTGenericReference", priority = 102)] + public static void CompileAndGenerateAOTGenericReference() + { + BuildTarget target = EditorUserBuildSettings.activeBuildTarget; + CompileDllCommand.CompileDll(target); + GenerateAOTGenericReference(target); + } + + /// <summary> + /// 璁$畻鐑洿浠g爜涓殑娉涘瀷寮曠敤 + /// </summary> + /// <param name="target"></param> + public static void GenerateAOTGenericReference(BuildTarget target) + { + var gs = SettingsUtil.HybridCLRSettings; + List<string> hotUpdateDllNames = SettingsUtil.HotUpdateAssemblyNamesExcludePreserved; + + AssemblyReferenceDeepCollector collector = new AssemblyReferenceDeepCollector(MetaUtil.CreateHotUpdateAndAOTAssemblyResolver(target, hotUpdateDllNames), hotUpdateDllNames); + var analyzer = new Analyzer(new Analyzer.Options + { + MaxIterationCount = Math.Min(20, gs.maxGenericReferenceIteration), + Collector = collector, + }); + + analyzer.Run(); + + var writer = new GenericReferenceWriter(); + writer.Write(analyzer.AotGenericTypes.ToList(), analyzer.AotGenericMethods.ToList(), $"{Application.dataPath}/{gs.outputAOTGenericReferenceFile}"); + AssetDatabase.Refresh(); + } + + + + //[MenuItem("HybridCLR/Generate/AOTGenericReference2", priority = 103)] + //public static void GeneratedAOTGenericReferenceExcludeExists() + //{ + // GeneratedAOTGenericReferenceExcludeExists(EditorUserBuildSettings.activeBuildTarget); + //} + + /// <summary> + /// 璁$畻鐑洿鏂颁唬鐮佷腑鐨勬硾鍨嬪紩鐢紝浣嗘帓闄OT宸茬粡瀛樺湪鐨勬硾鍨嬪紩鐢� + /// </summary> + /// <param name="target"></param> + /// + public static void GeneratedAOTGenericReferenceExcludeExistsAOTClassAndMethods(BuildTarget target) + { + + var gs = SettingsUtil.HybridCLRSettings; + List<string> hotUpdateDllNames = SettingsUtil.HotUpdateAssemblyNamesExcludePreserved; + + AssemblyReferenceDeepCollector hotUpdateCollector = new AssemblyReferenceDeepCollector(MetaUtil.CreateHotUpdateAndAOTAssemblyResolver(target, hotUpdateDllNames), hotUpdateDllNames); + var hotUpdateAnalyzer = new Analyzer(new Analyzer.Options + { + MaxIterationCount = Math.Min(10, gs.maxGenericReferenceIteration), + Collector = hotUpdateCollector, + }); + + hotUpdateAnalyzer.Run(); + + + string aotDllDir = SettingsUtil.GetAssembliesPostIl2CppStripDir(target); + List<string> aotAssemblyNames = Directory.Exists(aotDllDir) ? + Directory.GetFiles(aotDllDir, "*.dll", SearchOption.TopDirectoryOnly).Select(Path.GetFileNameWithoutExtension).ToList() + : new List<string>(); + if (aotAssemblyNames.Count == 0) + { + throw new Exception($"no aot assembly found. please run `HybridCLR/Generate/All` or `HybridCLR/Generate/AotDlls` to generate aot dlls before runing `HybridCLR/Generate/AOTGenericReference`"); + } + AssemblyReferenceDeepCollector aotCollector = new AssemblyReferenceDeepCollector(MetaUtil.CreateAOTAssemblyResolver(target), aotAssemblyNames); + var aotAnalyzer = new Analyzer(new Analyzer.Options + { + MaxIterationCount = Math.Min(10, gs.maxGenericReferenceIteration), + Collector = aotCollector, + ComputeAotAssembly = true, + }); + + aotAnalyzer.Run(); + + var (resultTypes, resultMethods) = ExcludeExistAOTGenericTypeAndMethodss(hotUpdateAnalyzer.AotGenericTypes.ToList(), hotUpdateAnalyzer.AotGenericMethods.ToList(), aotAnalyzer.AotGenericTypes.ToList(), aotAnalyzer.AotGenericMethods.ToList()); + var writer = new GenericReferenceWriter(); + writer.Write(resultTypes, resultMethods, $"{Application.dataPath}/{gs.outputAOTGenericReferenceFile}"); + AssetDatabase.Refresh(); + } + + + private static (List<GenericClass>, List<GenericMethod>) ExcludeExistAOTGenericTypeAndMethodss(List<GenericClass> hotUpdateTypes, List<GenericMethod> hotUpdateMethods, List<GenericClass> aotTypes, List<GenericMethod> aotMethods) + { + var types = new List<GenericClass>(); + + var typeSig2Type = hotUpdateTypes.ToDictionary(t => t.Type.DefinitionAssembly.Name + ":" + t.ToTypeSig(), t => t); + foreach (var t in aotTypes) + { + string key = t.Type.DefinitionAssembly.Name + ":" + t.ToTypeSig(); + if (typeSig2Type.TryGetValue(key, out var removedType)) + { + typeSig2Type.Remove(key); + Debug.Log($"remove AOT type:{removedType.ToTypeSig()} "); + } + } + + var methodSig2Method = hotUpdateMethods.ToDictionary(m => m.Method.DeclaringType.DefinitionAssembly.Name + ":" + m.ToMethodSpec().ToString(), m => m); + foreach (var m in aotMethods) + { + string key = m.Method.DeclaringType.DefinitionAssembly.Name + ":" + m.ToMethodSpec().ToString(); + if (methodSig2Method.TryGetValue(key, out var removedMethod)) + { + methodSig2Method.Remove(key); + Debug.Log($"remove AOT method:{removedMethod.ToMethodSpec()} "); + } + } + + return (typeSig2Type.Values.ToList(), methodSig2Method.Values.ToList()); + } + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Commands/AOTReferenceGeneratorCommand.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Commands/AOTReferenceGeneratorCommand.cs.meta new file mode 100644 index 0000000..39760e8 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Commands/AOTReferenceGeneratorCommand.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2b464872c07f6ba4f9a4e4a02ca9a28c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Commands/CompileDllCommand.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Commands/CompileDllCommand.cs new file mode 100644 index 0000000..a80706a --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Commands/CompileDllCommand.cs @@ -0,0 +1,101 @@ +锘縰sing System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UnityEditor; +using UnityEditor.Build.Player; +using UnityEngine; + +namespace HybridCLR.Editor.Commands +{ + public class CompileDllCommand + { + public static void CompileDll(string buildDir, BuildTarget target, bool developmentBuild) + { + var group = BuildPipeline.GetBuildTargetGroup(target); + + ScriptCompilationSettings scriptCompilationSettings = new ScriptCompilationSettings(); + scriptCompilationSettings.group = group; + scriptCompilationSettings.target = target; + scriptCompilationSettings.options = developmentBuild ? ScriptCompilationOptions.DevelopmentBuild : ScriptCompilationOptions.None; + Directory.CreateDirectory(buildDir); + ScriptCompilationResult scriptCompilationResult = PlayerBuildInterface.CompilePlayerScripts(scriptCompilationSettings, buildDir); +#if UNITY_2022 + UnityEditor.EditorUtility.ClearProgressBar(); +#endif + Debug.Log($"compile finish!!! buildDir:{buildDir} target:{target} development:{developmentBuild}"); + } + + public static void CompileDll(BuildTarget target) + { + CompileDll(EditorUserBuildSettings.activeBuildTarget, EditorUserBuildSettings.development); + } + + public static void CompileDll(BuildTarget target, bool developmentBuild) + { + CompileDll(SettingsUtil.GetHotUpdateDllsOutputDirByTarget(target), target, developmentBuild); + } + + [MenuItem("HybridCLR/CompileDll/ActiveBuildTarget", priority = 100)] + public static void CompileDllActiveBuildTarget() + { + CompileDll(EditorUserBuildSettings.activeBuildTarget, EditorUserBuildSettings.development); + } + + [MenuItem("HybridCLR/CompileDll/ActiveBuildTarget_Release", priority = 102)] + public static void CompileDllActiveBuildTargetRelease() + { + CompileDll(EditorUserBuildSettings.activeBuildTarget, false); + } + + [MenuItem("HybridCLR/CompileDll/ActiveBuildTarget_Development", priority = 104)] + public static void CompileDllActiveBuildTargetDevelopment() + { + CompileDll(EditorUserBuildSettings.activeBuildTarget, true); + } + + [MenuItem("HybridCLR/CompileDll/Win32", priority = 200)] + public static void CompileDllWin32() + { + CompileDll(BuildTarget.StandaloneWindows); + } + + [MenuItem("HybridCLR/CompileDll/Win64", priority = 201)] + public static void CompileDllWin64() + { + CompileDll(BuildTarget.StandaloneWindows64); + } + + [MenuItem("HybridCLR/CompileDll/MacOS", priority = 202)] + public static void CompileDllMacOS() + { + CompileDll(BuildTarget.StandaloneOSX); + } + + [MenuItem("HybridCLR/CompileDll/Linux", priority = 203)] + public static void CompileDllLinux() + { + CompileDll(BuildTarget.StandaloneLinux64); + } + + [MenuItem("HybridCLR/CompileDll/Android", priority = 210)] + public static void CompileDllAndroid() + { + CompileDll(BuildTarget.Android); + } + + [MenuItem("HybridCLR/CompileDll/IOS", priority = 220)] + public static void CompileDllIOS() + { + CompileDll(BuildTarget.iOS); + } + + [MenuItem("HybridCLR/CompileDll/WebGL", priority = 230)] + public static void CompileDllWebGL() + { + CompileDll(BuildTarget.WebGL); + } + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Commands/CompileDllCommand.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Commands/CompileDllCommand.cs.meta new file mode 100644 index 0000000..88b2e30 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Commands/CompileDllCommand.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: bf11b6c8bbc5afd4cb4a11921e5bd81e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Commands/Il2CppDefGeneratorCommand.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Commands/Il2CppDefGeneratorCommand.cs new file mode 100644 index 0000000..44890ee --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Commands/Il2CppDefGeneratorCommand.cs @@ -0,0 +1,33 @@ +锘縰sing HybridCLR.Editor.Link; +using HybridCLR.Editor.Settings; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using UnityEditor; +using UnityEngine; + +namespace HybridCLR.Editor.Commands +{ + + public static class Il2CppDefGeneratorCommand + { + + [MenuItem("HybridCLR/Generate/Il2CppDef", priority = 104)] + public static void GenerateIl2CppDef() + { + var options = new Il2CppDef.Il2CppDefGenerator.Options() + { + UnityVersion = Application.unityVersion, + HotUpdateAssemblies = SettingsUtil.HotUpdateAssemblyNamesIncludePreserved, + UnityVersionTemplateFile = $"{SettingsUtil.TemplatePathInPackage}/UnityVersion.h.tpl", + UnityVersionOutputFile = $"{SettingsUtil.LocalIl2CppDir}/libil2cpp/hybridclr/generated/UnityVersion.h", + AssemblyManifestTemplateFile = $"{SettingsUtil.TemplatePathInPackage}/AssemblyManifest.cpp.tpl", + AssemblyManifestOutputFile = $"{SettingsUtil.LocalIl2CppDir}/libil2cpp/hybridclr/generated/AssemblyManifest.cpp", + }; + + var g = new Il2CppDef.Il2CppDefGenerator(options); + g.Generate(); + } + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Commands/Il2CppDefGeneratorCommand.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Commands/Il2CppDefGeneratorCommand.cs.meta new file mode 100644 index 0000000..21f9427 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Commands/Il2CppDefGeneratorCommand.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5165a065d05497c43a2fff885f31ed07 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Commands/LinkGeneratorCommand.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Commands/LinkGeneratorCommand.cs new file mode 100644 index 0000000..c545ff5 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Commands/LinkGeneratorCommand.cs @@ -0,0 +1,39 @@ +锘縰sing HybridCLR.Editor.Link; +using HybridCLR.Editor.Meta; +using System; +using System.Collections.Generic; +using System.Reflection; +using UnityEditor; +using UnityEngine; + +namespace HybridCLR.Editor.Commands +{ + using Analyzer = HybridCLR.Editor.Link.Analyzer; + + public static class LinkGeneratorCommand + { + + [MenuItem("HybridCLR/Generate/LinkXml", priority = 100)] + public static void GenerateLinkXml() + { + BuildTarget target = EditorUserBuildSettings.activeBuildTarget; + CompileDllCommand.CompileDll(target); + GenerateLinkXml(target); + } + + public static void GenerateLinkXml(BuildTarget target) + { + var ls = SettingsUtil.HybridCLRSettings; + + List<string> hotfixAssemblies = SettingsUtil.HotUpdateAssemblyNamesExcludePreserved; + + var analyzer = new Analyzer(MetaUtil.CreateHotUpdateAndAOTAssemblyResolver(target, hotfixAssemblies)); + var refTypes = analyzer.CollectRefs(hotfixAssemblies); + + Debug.Log($"[LinkGeneratorCommand] hotfix assembly count:{hotfixAssemblies.Count}, ref type count:{refTypes.Count} output:{Application.dataPath}/{ls.outputLinkFile}"); + var linkXmlWriter = new LinkXmlWriter(); + linkXmlWriter.Write($"{Application.dataPath}/{ls.outputLinkFile}", refTypes); + AssetDatabase.Refresh(); + } + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Commands/LinkGeneratorCommand.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Commands/LinkGeneratorCommand.cs.meta new file mode 100644 index 0000000..0eeba1f --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Commands/LinkGeneratorCommand.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4f5b96abdbc4c424eb1bc3bc34b3a1a4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Commands/MethodBridgeGeneratorCommand.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Commands/MethodBridgeGeneratorCommand.cs new file mode 100644 index 0000000..c828264 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Commands/MethodBridgeGeneratorCommand.cs @@ -0,0 +1,95 @@ +锘縰sing HybridCLR.Editor; +using HybridCLR.Editor.ABI; +using HybridCLR.Editor.Meta; +using HybridCLR.Editor.MethodBridge; +using HybridCLR.Editor.ReversePInvokeWrap; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; +using UnityEditor; +using UnityEditor.Build; +using UnityEngine; + +namespace HybridCLR.Editor.Commands +{ + using Analyzer = HybridCLR.Editor.MethodBridge.Analyzer; + public class MethodBridgeGeneratorCommand + { + + public static void CleanIl2CppBuildCache() + { + string il2cppBuildCachePath = SettingsUtil.Il2CppBuildCacheDir; + if (!Directory.Exists(il2cppBuildCachePath)) + { + return; + } + Debug.Log($"clean il2cpp build cache:{il2cppBuildCachePath}"); + Directory.Delete(il2cppBuildCachePath, true); + } + + private static void GenerateMethodBridgeCppFile(IReadOnlyCollection<GenericMethod> genericMethods, List<RawReversePInvokeMethodInfo> reversePInvokeMethods, IReadOnlyCollection<RawCalliMethodSignatureInfo> calliMethodSignatures, string tempFile, string outputFile) + { + string templateCode = File.ReadAllText(tempFile, Encoding.UTF8); + var g = new Generator(new Generator.Options() + { + TemplateCode = templateCode, + OutputFile = outputFile, + GenericMethods = genericMethods, + ReversePInvokeMethods = reversePInvokeMethods, + CalliMethodSignatures = calliMethodSignatures, + Development = EditorUserBuildSettings.development, + }); + + g.Generate(); + Debug.LogFormat("[MethodBridgeGeneratorCommand] output:{0}", outputFile); + } + + [MenuItem("HybridCLR/Generate/MethodBridgeAndReversePInvokeWrapper", priority = 101)] + public static void GenerateMethodBridgeAndReversePInvokeWrapper() + { + BuildTarget target = EditorUserBuildSettings.activeBuildTarget; + GenerateMethodBridgeAndReversePInvokeWrapper(target); + } + + public static void GenerateMethodBridgeAndReversePInvokeWrapper(BuildTarget target) + { + string aotDllDir = SettingsUtil.GetAssembliesPostIl2CppStripDir(target); + List<string> aotAssemblyNames = Directory.Exists(aotDllDir) ? + Directory.GetFiles(aotDllDir, "*.dll", SearchOption.TopDirectoryOnly).Select(Path.GetFileNameWithoutExtension).ToList() + : new List<string>(); + if (aotAssemblyNames.Count == 0) + { + throw new Exception($"no aot assembly found. please run `HybridCLR/Generate/All` or `HybridCLR/Generate/AotDlls` to generate aot dlls before runing `HybridCLR/Generate/MethodBridge`"); + } + AssemblyReferenceDeepCollector collector = new AssemblyReferenceDeepCollector(MetaUtil.CreateAOTAssemblyResolver(target), aotAssemblyNames); + + var methodBridgeAnalyzer = new Analyzer(new Analyzer.Options + { + MaxIterationCount = Math.Min(20, SettingsUtil.HybridCLRSettings.maxMethodBridgeGenericIteration), + Collector = collector, + }); + + methodBridgeAnalyzer.Run(); + + List<string> hotUpdateDlls = SettingsUtil.HotUpdateAssemblyNamesExcludePreserved; + var cache = new AssemblyCache(MetaUtil.CreateHotUpdateAndAOTAssemblyResolver(target, hotUpdateDlls)); + + var reversePInvokeAnalyzer = new ReversePInvokeWrap.Analyzer(cache, hotUpdateDlls); + reversePInvokeAnalyzer.Run(); + + var calliAnalyzer = new CalliAnalyzer(cache, hotUpdateDlls); + calliAnalyzer.Run(); + + string templateFile = $"{SettingsUtil.TemplatePathInPackage}/MethodBridge.cpp.tpl"; + string outputFile = $"{SettingsUtil.GeneratedCppDir}/MethodBridge.cpp"; + + GenerateMethodBridgeCppFile(methodBridgeAnalyzer.GenericMethods, reversePInvokeAnalyzer.ReversePInvokeMethods, calliAnalyzer.CalliMethodSignatures, templateFile, outputFile); + + CleanIl2CppBuildCache(); + } + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Commands/MethodBridgeGeneratorCommand.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Commands/MethodBridgeGeneratorCommand.cs.meta new file mode 100644 index 0000000..9827997 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Commands/MethodBridgeGeneratorCommand.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 46bc62d5236f5e941850776c435a9560 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Commands/PrebuildCommand.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Commands/PrebuildCommand.cs new file mode 100644 index 0000000..3278802 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Commands/PrebuildCommand.cs @@ -0,0 +1,39 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UnityEditor; +using UnityEditor.Build; + +namespace HybridCLR.Editor.Commands +{ + public static class PrebuildCommand + { + /// <summary> + /// 鎸夌収蹇呰鐨勯『搴忥紝鎵ц鎵�鏈夌敓鎴愭搷浣滐紝閫傚悎鎵撳寘鍓嶆搷浣� + /// </summary> + [MenuItem("HybridCLR/Generate/All", priority = 200)] + public static void GenerateAll() + { + var installer = new Installer.InstallerController(); + if (!installer.HasInstalledHybridCLR()) + { + throw new BuildFailedException($"You have not initialized HybridCLR, please install it via menu 'HybridCLR/Installer'"); + } + BuildTarget target = EditorUserBuildSettings.activeBuildTarget; + CompileDllCommand.CompileDll(target, EditorUserBuildSettings.development); + Il2CppDefGeneratorCommand.GenerateIl2CppDef(); + + // 杩欏嚑涓敓鎴愪緷璧朒otUpdateDlls + LinkGeneratorCommand.GenerateLinkXml(target); + + // 鐢熸垚瑁佸壀鍚庣殑aot dll + StripAOTDllCommand.GenerateStripedAOTDlls(target); + + // 妗ユ帴鍑芥暟鐢熸垚渚濊禆浜嶢OT dll锛屽繀椤讳繚璇佸凡缁廱uild杩囷紝鐢熸垚AOT dll + MethodBridgeGeneratorCommand.GenerateMethodBridgeAndReversePInvokeWrapper(target); + AOTReferenceGeneratorCommand.GenerateAOTGenericReference(target); + } + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Commands/PrebuildCommand.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Commands/PrebuildCommand.cs.meta new file mode 100644 index 0000000..a27aea2 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Commands/PrebuildCommand.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c20f09bfbe3f32143aae872d3813d9e9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Commands/StripAOTDllCommand.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Commands/StripAOTDllCommand.cs new file mode 100644 index 0000000..eae6421 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Commands/StripAOTDllCommand.cs @@ -0,0 +1,199 @@ +锘縰sing HybridCLR.Editor.BuildProcessors; +using HybridCLR.Editor.Installer; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; +using UnityEditor; +using UnityEngine; +using static UnityEngine.Networking.UnityWebRequest; + +namespace HybridCLR.Editor.Commands +{ + public static class StripAOTDllCommand + { + [MenuItem("HybridCLR/Generate/AOTDlls", priority = 105)] + public static void GenerateStripedAOTDlls() + { + GenerateStripedAOTDlls(EditorUserBuildSettings.activeBuildTarget); + } + + static BuildOptions GetBuildPlayerOptions(BuildTarget buildTarget) + { + BuildOptions options = BuildOptions.None; + bool development = EditorUserBuildSettings.development; + if (development) + { + options |= BuildOptions.Development; + } + + if (EditorUserBuildSettings.allowDebugging && development) + { + options |= BuildOptions.AllowDebugging; + } + + if (EditorUserBuildSettings.connectProfiler && (development || buildTarget == BuildTarget.WSAPlayer)) + { + options |= BuildOptions.ConnectWithProfiler; + } + + if (EditorUserBuildSettings.buildWithDeepProfilingSupport && development) + { + options |= BuildOptions.EnableDeepProfilingSupport; + } + +#if UNITY_2021_2_OR_NEWER + options |= BuildOptions.CleanBuildCache; +#endif + + return options; + } + + private static string GetLocationPathName(string buildDir, BuildTarget target) + { + switch(target) + { + case BuildTarget.StandaloneWindows: + case BuildTarget.StandaloneWindows64: return $"{buildDir}/{PlayerSettings.productName}.exe"; + case BuildTarget.StandaloneOSX: return buildDir; + case BuildTarget.iOS: return buildDir; + case BuildTarget.Android: return buildDir; + case BuildTarget.StandaloneLinux64: return $"{buildDir}/{PlayerSettings.productName}"; + default: return buildDir; + } + } + + public static void GenerateStripedAOTDlls(BuildTarget target) + { + string outputPath = $"{SettingsUtil.HybridCLRDataDir}/StrippedAOTDllsTempProj/{target}"; + BashUtil.RemoveDir(outputPath); + + var buildOptions = GetBuildPlayerOptions(target); +#if UNITY_2021_2_OR_NEWER + buildOptions |= BuildOptions.CleanBuildCache; +#endif + + bool oldExportAndroidProj = EditorUserBuildSettings.exportAsGoogleAndroidProject; +#if UNITY_EDITOR_OSX + bool oldCreateSolution = UnityEditor.OSXStandalone.UserBuildSettings.createXcodeProject; +#elif UNITY_EDITOR_WIN + bool oldCreateSolution = UnityEditor.WindowsStandalone.UserBuildSettings.createSolution; +#endif +#if TUANJIE_2022_3_OR_NEWER + bool oldOpenHarmonyProj = EditorUserBuildSettings.exportAsOpenHarmonyProject; +#endif + bool oldBuildScriptsOnly = EditorUserBuildSettings.buildScriptsOnly; + + string oldBuildLocation = EditorUserBuildSettings.GetBuildLocation(target); + try + { + CheckSettings.DisableMethodBridgeDevelopmentFlagChecking = true; + EditorUserBuildSettings.buildScriptsOnly = true; + + string location = GetLocationPathName(outputPath, target); + EditorUserBuildSettings.SetBuildLocation(target, location); + + switch (target) + { + case BuildTarget.StandaloneWindows: + case BuildTarget.StandaloneWindows64: + { + #if UNITY_EDITOR_WIN + UnityEditor.WindowsStandalone.UserBuildSettings.createSolution = true; + #endif + break; + } + case BuildTarget.StandaloneOSX: + { + #if UNITY_EDITOR_OSX + UnityEditor.OSXStandalone.UserBuildSettings.createXcodeProject = true; + #endif + break; + } + #if TUANJIE_2022_3_OR_NEWER + case BuildTarget.HMIAndroid: + #endif + case BuildTarget.Android: + { + EditorUserBuildSettings.exportAsGoogleAndroidProject = true; + break; + } + #if TUANJIE_2022_3_OR_NEWER + case BuildTarget.OpenHarmony: + { + EditorUserBuildSettings.exportAsOpenHarmonyProject = true; + break; + } + #endif + } + + Debug.Log($"GenerateStripedAOTDlls build option:{buildOptions}"); + + BuildPlayerOptions buildPlayerOptions = new BuildPlayerOptions() + { + scenes = EditorBuildSettings.scenes.Where(s => s.enabled).Select(s => s.path).ToArray(), + locationPathName = location, + options = buildOptions, + target = target, + targetGroup = BuildPipeline.GetBuildTargetGroup(target), +#if UNITY_2021_1_OR_NEWER + subtarget = (int)EditorUserBuildSettings.standaloneBuildSubtarget, +#endif + }; + + var report = BuildPipeline.BuildPlayer(buildPlayerOptions); + + + + if (report.summary.result != UnityEditor.Build.Reporting.BuildResult.Succeeded) + { + throw new Exception("GenerateStripedAOTDlls failed"); + } + } + finally + { + CheckSettings.DisableMethodBridgeDevelopmentFlagChecking = false; + EditorUserBuildSettings.buildScriptsOnly = oldBuildScriptsOnly; + EditorUserBuildSettings.SetBuildLocation(target, oldBuildLocation); + + switch (target) + { + case BuildTarget.StandaloneWindows: + case BuildTarget.StandaloneWindows64: + { +#if UNITY_EDITOR_WIN + UnityEditor.WindowsStandalone.UserBuildSettings.createSolution = oldCreateSolution; +#endif + break; + } + case BuildTarget.StandaloneOSX: + { +#if UNITY_EDITOR_OSX + UnityEditor.OSXStandalone.UserBuildSettings.createXcodeProject = oldCreateSolution; +#endif + break; + } +#if TUANJIE_2022_3_OR_NEWER + case BuildTarget.HMIAndroid: +#endif + case BuildTarget.Android: + { + EditorUserBuildSettings.exportAsGoogleAndroidProject = oldExportAndroidProj; + break; + } +#if TUANJIE_2022_3_OR_NEWER + case BuildTarget.OpenHarmony: + { + EditorUserBuildSettings.exportAsOpenHarmonyProject = oldOpenHarmonyProj; + break; + } +#endif + } + } + Debug.Log($"GenerateStripedAOTDlls target:{target} path:{outputPath}"); + } + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Commands/StripAOTDllCommand.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Commands/StripAOTDllCommand.cs.meta new file mode 100644 index 0000000..3979b80 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Commands/StripAOTDllCommand.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 21fb0a02f23185141a4a3df67fe61789 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/HashUtil.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/HashUtil.cs new file mode 100644 index 0000000..38e83e3 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/HashUtil.cs @@ -0,0 +1,28 @@ +锘縰sing dnlib.DotNet; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace HybridCLR.Editor +{ + public static class HashUtil + { + public static int CombineHash(int hash1, int hash2) + { + return hash1 * 1566083941 + hash2; + } + + public static int ComputHash(List<TypeSig> sigs) + { + int hash = 135781321; + TypeEqualityComparer tc = TypeEqualityComparer.Instance; + foreach (var sig in sigs) + { + hash = hash * 1566083941 + tc.GetHashCode(sig); + } + return hash; + } + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/HashUtil.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/HashUtil.cs.meta new file mode 100644 index 0000000..9cdce22 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/HashUtil.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5d4ae4a5c0bba49469c525887d812717 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/HotUpdate.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/HotUpdate.meta new file mode 100644 index 0000000..7b7bf3d --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/HotUpdate.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e60a8b17b0e23a94a8ae875716208030 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/HotUpdate/MissingMetadataChecker.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/HotUpdate/MissingMetadataChecker.cs new file mode 100644 index 0000000..2459b48 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/HotUpdate/MissingMetadataChecker.cs @@ -0,0 +1,109 @@ +锘縰sing dnlib.DotNet; +using HybridCLR.Editor.Meta; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace HybridCLR.Editor.HotUpdate +{ + public class MissingMetadataChecker + { + private readonly HashSet<string> _aotAssNames; + + private readonly HashSet<string> _hotUpdateAssNames; + + private readonly AssemblyCache _assCache; + + public MissingMetadataChecker(string aotDllDir, IEnumerable<string> hotUpdateAssNames) + { + + _hotUpdateAssNames = new HashSet<string>(hotUpdateAssNames ?? new List<string>()); + _aotAssNames = new HashSet<string>(); + foreach (var aotFile in Directory.GetFiles(aotDllDir, "*.dll")) + { + string aotAssName = Path.GetFileNameWithoutExtension(aotFile); + if (_hotUpdateAssNames.Contains(aotAssName)) + { + continue; + } + _aotAssNames.Add(aotAssName); + } + _assCache = new AssemblyCache(new PathAssemblyResolver(aotDllDir)); + } + + public bool Check(string hotUpdateDllPath) + { + bool anyMissing = false; + + ModuleDef mod = ModuleDefMD.Load(File.ReadAllBytes(hotUpdateDllPath), _assCache.ModCtx); + + foreach (var refass in mod.GetAssemblyRefs()) + { + string refAssName = refass.Name; + if (_aotAssNames.Contains(refAssName)) + { + _assCache.LoadModule(refass.Name, true); + } + else if (!_hotUpdateAssNames.Contains(refAssName)) + { + UnityEngine.Debug.LogError($"Missing AOT Assembly: {refAssName}"); + anyMissing = true; + } + } + + + foreach (TypeRef typeRef in mod.GetTypeRefs()) + { + string defAssName = typeRef.DefinitionAssembly.Name; + if (!_aotAssNames.Contains(defAssName)) + { + continue; + } + if (typeRef.ResolveTypeDef() == null) + { + UnityEngine.Debug.LogError($"Missing Type: {typeRef.FullName}"); + anyMissing = true; + } + } + + foreach (IMethodDefOrRef memberRef in mod.GetMemberRefs()) + { + if (memberRef.DeclaringType.DefinitionAssembly == null) + { + continue; + } + string defAssName = memberRef.DeclaringType.DefinitionAssembly.Name; + if (!_aotAssNames.Contains(defAssName)) + { + continue; + } + if (memberRef.IsField) + { + IField field = (IField)memberRef; + if (field.ResolveFieldDef() == null) + { + UnityEngine.Debug.LogError($"Missing Field: {memberRef.FullName}"); + anyMissing = true; + } + } + else if (memberRef.IsMethod) + { + TypeSig declaringTypeSig = memberRef.DeclaringType.ToTypeSig(); + if (memberRef.ResolveMethodDef() == null) + { + if (declaringTypeSig.ElementType == ElementType.Array || declaringTypeSig.ElementType == ElementType.SZArray) + { + continue; + } + UnityEngine.Debug.LogError($"Missing Method: {memberRef.FullName}"); + anyMissing = true; + } + } + } + return !anyMissing; + } + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/HotUpdate/MissingMetadataChecker.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/HotUpdate/MissingMetadataChecker.cs.meta new file mode 100644 index 0000000..bc58ca1 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/HotUpdate/MissingMetadataChecker.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: bdd260aca2a6deb44b20210f01faa86b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/HybridCLR.Editor.asmdef b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/HybridCLR.Editor.asmdef new file mode 100644 index 0000000..4612a6d --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/HybridCLR.Editor.asmdef @@ -0,0 +1,18 @@ +{ + "name": "HybridCLR.Editor", + "rootNamespace": "", + "references": [ + "HybridCLR.Runtime" + ], + "includePlatforms": [ + "Editor" + ], + "excludePlatforms": [], + "allowUnsafeCode": true, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +} \ No newline at end of file diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/HybridCLR.Editor.asmdef.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/HybridCLR.Editor.asmdef.meta new file mode 100644 index 0000000..be1417b --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/HybridCLR.Editor.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 2373f786d14518f44b0f475db77ba4de +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Il2CppDef.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Il2CppDef.meta new file mode 100644 index 0000000..dc951ca --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Il2CppDef.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: da46bc9f1a4dece41a5c193166be9a30 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Il2CppDef/Il2CppDefGenerator.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Il2CppDef/Il2CppDefGenerator.cs new file mode 100644 index 0000000..0632750 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Il2CppDef/Il2CppDefGenerator.cs @@ -0,0 +1,107 @@ +锘縰sing HybridCLR.Editor.ABI; +using HybridCLR.Editor.Template; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using UnityEngine; + +namespace HybridCLR.Editor.Il2CppDef +{ + public class Il2CppDefGenerator + { + public class Options + { + public List<string> HotUpdateAssemblies { get; set; } + + public string UnityVersionTemplateFile { get; set; } + + public string UnityVersionOutputFile { get; set; } + + public string AssemblyManifestTemplateFile { get; set; } + + public string AssemblyManifestOutputFile { get; set; } + + public string UnityVersion { get; set; } + } + + private readonly Options _options; + public Il2CppDefGenerator(Options options) + { + _options = options; + } + + + private static readonly Regex s_unityVersionPat = new Regex(@"(\d+)\.(\d+)\.(\d+)"); + + public void Generate() + { + GenerateIl2CppConfig(); + GeneratePlaceHolderAssemblies(); + } + + private void GenerateIl2CppConfig() + { + var frr = new FileRegionReplace(File.ReadAllText(_options.UnityVersionTemplateFile)); + + List<string> lines = new List<string>(); + + var match = s_unityVersionPat.Matches(_options.UnityVersion)[0]; + int majorVer = int.Parse(match.Groups[1].Value); + int minorVer1 = int.Parse(match.Groups[2].Value); + int minorVer2 = int.Parse(match.Groups[3].Value); + + lines.Add($"#define HYBRIDCLR_UNITY_VERSION {majorVer}{minorVer1.ToString("D2")}{minorVer2.ToString("D2")}"); + lines.Add($"#define HYBRIDCLR_UNITY_{majorVer} 1"); + for (int ver = 2019; ver <= 2023; ver++) + { + if (majorVer >= ver) + { + lines.Add($"#define HYBRIDCLR_UNITY_{ver}_OR_NEW 1"); + } + } + for (int ver = 6000; ver <= 6100; ver++) + { + if (majorVer >= ver) + { + lines.Add($"#define HYBRIDCLR_UNITY_{ver}_OR_NEW 1"); + } + } + +#if TUANJIE_1_1_OR_NEWER + var tuanjieMatch = Regex.Matches(Application.tuanjieVersion, @"(\d+)\.(\d+)\.(\d+)"); + int tuanjieMajorVer = int.Parse(tuanjieMatch[0].Groups[1].Value); + int tuanjieMinorVer1 = int.Parse(tuanjieMatch[0].Groups[2].Value); + int tuanjieMinorVer2 = int.Parse(tuanjieMatch[0].Groups[3].Value); + lines.Add($"#define HYBRIDCLR_TUANJIE_VERSION {tuanjieMajorVer}{tuanjieMinorVer1.ToString("D2")}{tuanjieMinorVer2.ToString("D2")}"); +#elif TUANJIE_2022_3_OR_NEWER + lines.Add($"#define HYBRIDCLR_TUANJIE_VERSION 10000"); +#endif + + frr.Replace("UNITY_VERSION", string.Join("\n", lines)); + + frr.Commit(_options.UnityVersionOutputFile); + Debug.Log($"[HybridCLR.Editor.Il2CppDef.Generator] output:{_options.UnityVersionOutputFile}"); + } + + private void GeneratePlaceHolderAssemblies() + { + var frr = new FileRegionReplace(File.ReadAllText(_options.AssemblyManifestTemplateFile)); + + List<string> lines = new List<string>(); + + foreach (var ass in _options.HotUpdateAssemblies) + { + lines.Add($"\t\t\"{ass}\","); + } + + frr.Replace("PLACE_HOLDER", string.Join("\n", lines)); + + frr.Commit(_options.AssemblyManifestOutputFile); + Debug.Log($"[HybridCLR.Editor.Il2CppDef.Generator] output:{_options.AssemblyManifestOutputFile}"); + } + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Il2CppDef/Il2CppDefGenerator.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Il2CppDef/Il2CppDefGenerator.cs.meta new file mode 100644 index 0000000..b7fe9d7 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Il2CppDef/Il2CppDefGenerator.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 590419ee7e82ac24cbac9b8a48891fe0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Installer.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Installer.meta new file mode 100644 index 0000000..b27774d --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Installer.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a2c8f84b297371d4cbcd5ca655bf360d +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Installer/BashUtil.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Installer/BashUtil.cs new file mode 100644 index 0000000..90e4259 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Installer/BashUtil.cs @@ -0,0 +1,143 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace HybridCLR.Editor.Installer +{ + public static class BashUtil + { + public static int RunCommand(string workingDir, string program, string[] args, bool log = true) + { + using (Process p = new Process()) + { + p.StartInfo.WorkingDirectory = workingDir; + p.StartInfo.FileName = program; + p.StartInfo.UseShellExecute = false; + p.StartInfo.CreateNoWindow = true; + string argsStr = string.Join(" ", args.Select(arg => "\"" + arg + "\"")); + p.StartInfo.Arguments = argsStr; + if (log) + { + UnityEngine.Debug.Log($"[BashUtil] run => {program} {argsStr}"); + } + p.Start(); + p.WaitForExit(); + return p.ExitCode; + } + } + + + public static (int ExitCode, string StdOut, string StdErr) RunCommand2(string workingDir, string program, string[] args, bool log = true) + { + using (Process p = new Process()) + { + p.StartInfo.WorkingDirectory = workingDir; + p.StartInfo.FileName = program; + p.StartInfo.UseShellExecute = false; + p.StartInfo.CreateNoWindow = true; + p.StartInfo.RedirectStandardOutput = true; + p.StartInfo.RedirectStandardError = true; + string argsStr = string.Join(" ", args); + p.StartInfo.Arguments = argsStr; + if (log) + { + UnityEngine.Debug.Log($"[BashUtil] run => {program} {argsStr}"); + } + p.Start(); + p.WaitForExit(); + + string stdOut = p.StandardOutput.ReadToEnd(); + string stdErr = p.StandardError.ReadToEnd(); + return (p.ExitCode, stdOut, stdErr); + } + } + + + public static void RemoveDir(string dir, bool log = false) + { + if (log) + { + UnityEngine.Debug.Log($"[BashUtil] RemoveDir dir:{dir}"); + } + + int maxTryCount = 5; + for (int i = 0; i < maxTryCount; ++i) + { + try + { + if (!Directory.Exists(dir)) + { + return; + } + foreach (var file in Directory.GetFiles(dir)) + { + File.SetAttributes(file, FileAttributes.Normal); + File.Delete(file); + } + foreach (var subDir in Directory.GetDirectories(dir)) + { + RemoveDir(subDir); + } + Directory.Delete(dir, true); + break; + } + catch (Exception e) + { + UnityEngine.Debug.LogError($"[BashUtil] RemoveDir:{dir} with exception:{e}. try count:{i}"); + Thread.Sleep(100); + } + } + } + + public static void RecreateDir(string dir) + { + if(Directory.Exists(dir)) + { + RemoveDir(dir, true); + } + Directory.CreateDirectory(dir); + } + + private static void CopyWithCheckLongFile(string srcFile, string dstFile) + { + var maxPathLength = 255; +#if UNITY_EDITOR_OSX + maxPathLength = 1024; +#endif + if (srcFile.Length > maxPathLength) + { + UnityEngine.Debug.LogError($"srcFile:{srcFile} path is too long. skip copy!"); + return; + } + if (dstFile.Length > maxPathLength) + { + UnityEngine.Debug.LogError($"dstFile:{dstFile} path is too long. skip copy!"); + return; + } + File.Copy(srcFile, dstFile); + } + + public static void CopyDir(string src, string dst, bool log = false) + { + if (log) + { + UnityEngine.Debug.Log($"[BashUtil] CopyDir {src} => {dst}"); + } + RemoveDir(dst); + Directory.CreateDirectory(dst); + foreach(var file in Directory.GetFiles(src)) + { + CopyWithCheckLongFile(file, $"{dst}/{Path.GetFileName(file)}"); + } + foreach(var subDir in Directory.GetDirectories(src)) + { + CopyDir(subDir, $"{dst}/{Path.GetFileName(subDir)}"); + } + } + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Installer/BashUtil.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Installer/BashUtil.cs.meta new file mode 100644 index 0000000..ef7e11d --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Installer/BashUtil.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 960a0257c3a17f64b810193308ce1558 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Installer/InstallerController.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Installer/InstallerController.cs new file mode 100644 index 0000000..fd40dbd --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Installer/InstallerController.cs @@ -0,0 +1,308 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using UnityEditor; +using UnityEngine; +using Debug = UnityEngine.Debug; +using System.Text.RegularExpressions; +using System.Linq; +using HybridCLR.Editor.Settings; + +namespace HybridCLR.Editor.Installer +{ + + public class InstallerController + { + private const string hybridclr_repo_path = "hybridclr_repo"; + + private const string il2cpp_plus_repo_path = "il2cpp_plus_repo"; + + public int MajorVersion => _curVersion.major; + + private readonly UnityVersion _curVersion; + + private readonly HybridclrVersionManifest _versionManifest; + private readonly HybridclrVersionInfo _curDefaultVersion; + + public string PackageVersion { get; private set; } + + public string InstalledLibil2cppVersion { get; private set; } + + public InstallerController() + { + _curVersion = ParseUnityVersion(Application.unityVersion); + _versionManifest = GetHybridCLRVersionManifest(); + _curDefaultVersion = _versionManifest.versions.FirstOrDefault(v => _curVersion.isTuanjieEngine ? v.unity_version == $"{_curVersion.major}-tuanjie" : v.unity_version == _curVersion.major.ToString()); + PackageVersion = LoadPackageInfo().version; + InstalledLibil2cppVersion = ReadLocalVersion(); + } + + private HybridclrVersionManifest GetHybridCLRVersionManifest() + { + string versionFile = $"{SettingsUtil.ProjectDir}/{SettingsUtil.HybridCLRDataPathInPackage}/hybridclr_version.json"; + return JsonUtility.FromJson<HybridclrVersionManifest>(File.ReadAllText(versionFile, Encoding.UTF8)); + } + + private PackageInfo LoadPackageInfo() + { + string packageJson = $"{SettingsUtil.ProjectDir}/Packages/{SettingsUtil.PackageName}/package.json"; + return JsonUtility.FromJson<PackageInfo>(File.ReadAllText(packageJson, Encoding.UTF8)); + } + + + [Serializable] + class PackageInfo + { + public string name; + + public string version; + } + + [Serializable] + class VersionDesc + { + public string branch; + + //public string hash; + } + + [Serializable] + class HybridclrVersionInfo + { + public string unity_version; + + public VersionDesc hybridclr; + + public VersionDesc il2cpp_plus; + } + + [Serializable] + class HybridclrVersionManifest + { + public List<HybridclrVersionInfo> versions; + } + + private class UnityVersion + { + public int major; + public int minor1; + public int minor2; + public bool isTuanjieEngine; + + public override string ToString() + { + return $"{major}.{minor1}.{minor2}"; + } + } + + private static readonly Regex s_unityVersionPat = new Regex(@"(\d+)\.(\d+)\.(\d+)"); + + private UnityVersion ParseUnityVersion(string versionStr) + { + var matches = s_unityVersionPat.Matches(versionStr); + if (matches.Count == 0) + { + return null; + } + Match match = matches[matches.Count - 1]; + int major = int.Parse(match.Groups[1].Value); + int minor1 = int.Parse(match.Groups[2].Value); + int minor2 = int.Parse(match.Groups[3].Value); + bool isTuanjieEngine = versionStr.Contains("t"); + return new UnityVersion { major = major, minor1 = minor1, minor2 = minor2, isTuanjieEngine = isTuanjieEngine }; + } + + public string GetCurrentUnityVersionMinCompatibleVersionStr() + { + return GetMinCompatibleVersion(MajorVersion); + } + + public string GetMinCompatibleVersion(int majorVersion) + { + switch(majorVersion) + { + case 2019: return "2019.4.0"; + case 2020: return "2020.3.0"; + case 2021: return "2021.3.0"; + case 2022: return "2022.3.0"; + case 2023: return "2023.2.0"; + case 6000: return "6000.0.0"; + default: return $"2020.3.0"; + } + } + + public enum CompatibleType + { + Compatible, + MaybeIncompatible, + Incompatible, + } + + public CompatibleType GetCompatibleType() + { + UnityVersion version = _curVersion; + if (version == null) + { + return CompatibleType.Incompatible; + } + if ((version.major == 2019 && version.minor1 < 4) + || (version.major >= 2020 && version.major <= 2022 && version.minor1 < 3)) + { + return CompatibleType.MaybeIncompatible; + } + return CompatibleType.Compatible; + } + + public string HybridclrLocalVersion => _curDefaultVersion?.hybridclr?.branch; + + public string Il2cppPlusLocalVersion => _curDefaultVersion?.il2cpp_plus?.branch; + + + private string GetIl2CppPathByContentPath(string contentPath) + { + return $"{contentPath}/il2cpp"; + } + + public string ApplicationIl2cppPath => GetIl2CppPathByContentPath(EditorApplication.applicationContentsPath); + + public string LocalVersionFile => $"{SettingsUtil.LocalIl2CppDir}/libil2cpp/hybridclr/generated/libil2cpp-version.txt"; + + private string ReadLocalVersion() + { + if (!File.Exists(LocalVersionFile)) + { + return null; + } + return File.ReadAllText(LocalVersionFile, Encoding.UTF8); + } + + public void WriteLocalVersion() + { + InstalledLibil2cppVersion = PackageVersion; + File.WriteAllText(LocalVersionFile, PackageVersion, Encoding.UTF8); + Debug.Log($"Write installed version:'{PackageVersion}' to {LocalVersionFile}"); + } + + public void InstallDefaultHybridCLR() + { + InstallFromLocal(PrepareLibil2cppWithHybridclrFromGitRepo()); + } + + public bool HasInstalledHybridCLR() + { + return Directory.Exists($"{SettingsUtil.LocalIl2CppDir}/libil2cpp/hybridclr"); + } + + private string GetUnityIl2CppDllInstallLocation() + { +#if UNITY_EDITOR_WIN + return $"{SettingsUtil.LocalIl2CppDir}/build/deploy/net471/Unity.IL2CPP.dll"; +#else + return $"{SettingsUtil.LocalIl2CppDir}/build/deploy/il2cppcore/Unity.IL2CPP.dll"; +#endif + } + + private string GetUnityIl2CppDllModifiedPath(string curVersionStr) + { +#if UNITY_EDITOR_WIN + return $"{SettingsUtil.ProjectDir}/{SettingsUtil.HybridCLRDataPathInPackage}/ModifiedUnityAssemblies/{curVersionStr}/Unity.IL2CPP-Win.dll"; +#else + return $"{SettingsUtil.ProjectDir}/{SettingsUtil.HybridCLRDataPathInPackage}/ModifiedUnityAssemblies/{curVersionStr}/Unity.IL2CPP-Mac.dll"; +#endif + } + + void CloneBranch(string workDir, string repoUrl, string branch, string repoDir) + { + BashUtil.RemoveDir(repoDir); + BashUtil.RunCommand(workDir, "git", new string[] {"clone", "-b", branch, "--depth", "1", repoUrl, repoDir}); + } + + private string PrepareLibil2cppWithHybridclrFromGitRepo() + { + string workDir = SettingsUtil.HybridCLRDataDir; + Directory.CreateDirectory(workDir); + //BashUtil.RecreateDir(workDir); + + // clone hybridclr + string hybridclrRepoURL = HybridCLRSettings.Instance.hybridclrRepoURL; + string hybridclrRepoDir = $"{workDir}/{hybridclr_repo_path}"; + CloneBranch(workDir, hybridclrRepoURL, _curDefaultVersion.hybridclr.branch, hybridclrRepoDir); + + if (!Directory.Exists(hybridclrRepoDir)) + { + throw new Exception($"clone hybridclr fail. url: {hybridclrRepoURL}"); + } + + // clone il2cpp_plus + string il2cppPlusRepoURL = HybridCLRSettings.Instance.il2cppPlusRepoURL; + string il2cppPlusRepoDir = $"{workDir}/{il2cpp_plus_repo_path}"; + CloneBranch(workDir, il2cppPlusRepoURL, _curDefaultVersion.il2cpp_plus.branch, il2cppPlusRepoDir); + + if (!Directory.Exists(il2cppPlusRepoDir)) + { + throw new Exception($"clone il2cpp_plus fail. url: {il2cppPlusRepoDir}"); + } + + Directory.Move($"{hybridclrRepoDir}/hybridclr", $"{il2cppPlusRepoDir}/libil2cpp/hybridclr"); + return $"{il2cppPlusRepoDir}/libil2cpp"; + } + + public void InstallFromLocal(string libil2cppWithHybridclrSourceDir) + { + RunInitLocalIl2CppData(ApplicationIl2cppPath, libil2cppWithHybridclrSourceDir, _curVersion); + } + + private void RunInitLocalIl2CppData(string editorIl2cppPath, string libil2cppWithHybridclrSourceDir, UnityVersion version) + { + if (GetCompatibleType() == CompatibleType.Incompatible) + { + Debug.LogError($"Incompatible with current version, minimum compatible version: {GetCurrentUnityVersionMinCompatibleVersionStr()}"); + return; + } + string workDir = SettingsUtil.HybridCLRDataDir; + Directory.CreateDirectory(workDir); + + // create LocalIl2Cpp + string localUnityDataDir = SettingsUtil.LocalUnityDataDir; + BashUtil.RecreateDir(localUnityDataDir); + + // copy MonoBleedingEdge + BashUtil.CopyDir($"{Directory.GetParent(editorIl2cppPath)}/MonoBleedingEdge", $"{localUnityDataDir}/MonoBleedingEdge", true); + + // copy il2cpp + BashUtil.CopyDir(editorIl2cppPath, SettingsUtil.LocalIl2CppDir, true); + + // replace libil2cpp + string dstLibil2cppDir = $"{SettingsUtil.LocalIl2CppDir}/libil2cpp"; + BashUtil.CopyDir($"{libil2cppWithHybridclrSourceDir}", dstLibil2cppDir, true); + + // clean Il2cppBuildCache + BashUtil.RemoveDir($"{SettingsUtil.ProjectDir}/Library/Il2cppBuildCache", true); + if (version.major == 2019) + { + string curVersionStr = version.ToString(); + string srcIl2CppDll = GetUnityIl2CppDllModifiedPath(curVersionStr); + if (File.Exists(srcIl2CppDll)) + { + string dstIl2CppDll = GetUnityIl2CppDllInstallLocation(); + File.Copy(srcIl2CppDll, dstIl2CppDll, true); + Debug.Log($"copy {srcIl2CppDll} => {dstIl2CppDll}"); + } + else + { + throw new Exception($"the modified Unity.IL2CPP.dll of {curVersionStr} isn't found. please install hybridclr in 2019.4.40 first, then switch to your unity version"); + } + } + if (HasInstalledHybridCLR()) + { + WriteLocalVersion(); + Debug.Log("Install Sucessfully"); + } + else + { + Debug.LogError("Installation failed!"); + } + } + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Installer/InstallerController.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Installer/InstallerController.cs.meta new file mode 100644 index 0000000..6b30944 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Installer/InstallerController.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 44c8627d126b30d4e9560b1f738264ca +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Installer/InstallerWindow.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Installer/InstallerWindow.cs new file mode 100644 index 0000000..1869f89 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Installer/InstallerWindow.cs @@ -0,0 +1,113 @@ +using System; +using System.IO; +using System.Reflection; +using UnityEditor; +using UnityEngine; + + +namespace HybridCLR.Editor.Installer +{ + public class InstallerWindow : EditorWindow + { + private InstallerController _controller; + + private bool _installFromDir; + + private string _installLibil2cppWithHybridclrSourceDir; + + private void OnEnable() + { + _controller = new InstallerController(); + } + + private void OnGUI() + { + var rect = new Rect + { + x = EditorGUIUtility.currentViewWidth - 24, + y = 5, + width = 24, + height = 24 + }; + var content = EditorGUIUtility.IconContent("Settings"); + content.tooltip = "HybridCLR Settings"; + if (GUI.Button(rect, content, GUI.skin.GetStyle("IconButton"))) + { + SettingsService.OpenProjectSettings("Project/HybridCLR Settings"); + } + + bool hasInstall = _controller.HasInstalledHybridCLR(); + + GUILayout.Space(10f); + + EditorGUILayout.BeginVertical("box"); + EditorGUILayout.LabelField($"Installed: {hasInstall}", EditorStyles.boldLabel); + GUILayout.Space(10f); + + EditorGUILayout.LabelField($"Package Version: v{_controller.PackageVersion}"); + GUILayout.Space(5f); + EditorGUILayout.LabelField($"Installed Version: v{_controller.InstalledLibil2cppVersion ?? " Unknown"}"); + GUILayout.Space(5f); + + GUILayout.Space(10f); + + InstallerController.CompatibleType compatibleType = _controller.GetCompatibleType(); + if (compatibleType != InstallerController.CompatibleType.Incompatible) + { + if (compatibleType == InstallerController.CompatibleType.MaybeIncompatible) + { + EditorGUILayout.HelpBox($"Maybe incompatible with current version, recommend minimum compatible version:{_controller.GetCurrentUnityVersionMinCompatibleVersionStr()}", MessageType.Warning); + } + + EditorGUILayout.BeginHorizontal(); + _installFromDir = EditorGUILayout.Toggle("Copy libil2cpp from local", _installFromDir, GUILayout.MinWidth(100)); + EditorGUI.BeginDisabledGroup(!_installFromDir); + EditorGUILayout.TextField(_installLibil2cppWithHybridclrSourceDir, GUILayout.Width(400)); + if (GUILayout.Button("Choose", GUILayout.Width(100))) + { + _installLibil2cppWithHybridclrSourceDir = EditorUtility.OpenFolderPanel("Select libil2cpp", Application.dataPath, "libil2cpp"); + } + EditorGUI.EndDisabledGroup(); + EditorGUILayout.EndHorizontal(); + + GUILayout.Space(20f); + + EditorGUILayout.BeginHorizontal(); + if (GUILayout.Button("Install", GUILayout.Width(100))) + { + InstallLocalHybridCLR(); + GUIUtility.ExitGUI(); + } + EditorGUILayout.EndHorizontal(); + } + else + { + EditorGUILayout.HelpBox($"Incompatible with current version, minimum compatible version:{_controller.GetCurrentUnityVersionMinCompatibleVersionStr()}", MessageType.Error); + } + + EditorGUILayout.EndVertical(); + } + + private void InstallLocalHybridCLR() + { + if (_installFromDir) + { + if (!Directory.Exists(_installLibil2cppWithHybridclrSourceDir)) + { + Debug.LogError($"Source libil2cpp:'{_installLibil2cppWithHybridclrSourceDir}' doesn't exist."); + return; + } + if (!File.Exists($"{_installLibil2cppWithHybridclrSourceDir}/il2cpp-config.h") || !File.Exists($"{_installLibil2cppWithHybridclrSourceDir}/hybridclr/RuntimeApi.cpp")) + { + Debug.LogError($"Source libil2cpp:' {_installLibil2cppWithHybridclrSourceDir} ' is invalid"); + return; + } + _controller.InstallFromLocal(_installLibil2cppWithHybridclrSourceDir); + } + else + { + _controller.InstallDefaultHybridCLR(); + } + } + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Installer/InstallerWindow.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Installer/InstallerWindow.cs.meta new file mode 100644 index 0000000..f404c28 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Installer/InstallerWindow.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 959fbf0bb06629542969354505189240 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Link.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Link.meta new file mode 100644 index 0000000..1cad1b3 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Link.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 5186a137e0258034cb3832bdf6b16a70 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Link/Analyzer.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Link/Analyzer.cs new file mode 100644 index 0000000..ffbb93d --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Link/Analyzer.cs @@ -0,0 +1,49 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; +using dnlib.DotNet; +using HybridCLR.Editor.Meta; +using UnityEditor; +using UnityEngine; +using IAssemblyResolver = HybridCLR.Editor.Meta.IAssemblyResolver; + +namespace HybridCLR.Editor.Link +{ + public class Analyzer + { + private readonly IAssemblyResolver _resolver; + + public Analyzer(IAssemblyResolver resolver) + { + _resolver = resolver; + } + + public HashSet<TypeRef> CollectRefs(List<string> rootAssemblies) + { + var assCollector = new AssemblyCache(_resolver); + var rootAssemblyNames = new HashSet<string>(rootAssemblies); + + var typeRefs = new HashSet<TypeRef>(TypeEqualityComparer.Instance); + foreach (var rootAss in rootAssemblies) + { + var dnAss = assCollector.LoadModule(rootAss, false); + foreach (var type in dnAss.GetTypeRefs()) + { + if (type.DefinitionAssembly == null) + { + Debug.LogWarning($"assembly:{dnAss.Name} TypeRef {type.FullName} has no DefinitionAssembly"); + continue; + } + if (!rootAssemblyNames.Contains(type.DefinitionAssembly.Name.ToString())) + { + typeRefs.Add(type); + } + } + } + return typeRefs; + } + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Link/Analyzer.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Link/Analyzer.cs.meta new file mode 100644 index 0000000..0c6fa90 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Link/Analyzer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: fd3dd4871efd10e46947cb61c13797fd +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Link/LinkXmlWriter.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Link/LinkXmlWriter.cs new file mode 100644 index 0000000..ab5d448 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Link/LinkXmlWriter.cs @@ -0,0 +1,53 @@ +锘縰sing dnlib.DotNet; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace HybridCLR.Editor.Link +{ + internal class LinkXmlWriter + { + public void Write(string outputLinkXmlFile, HashSet<TypeRef> refTypes) + { + string parentDir = Directory.GetParent(outputLinkXmlFile).FullName; + Directory.CreateDirectory(parentDir); + var writer = System.Xml.XmlWriter.Create(outputLinkXmlFile, + new System.Xml.XmlWriterSettings { Encoding = Encoding.UTF8, Indent = true}); + + writer.WriteStartDocument(); + writer.WriteStartElement("linker"); + + var typesByAssembly = refTypes.GroupBy(t => t.DefinitionAssembly.Name.String).ToList(); + typesByAssembly.Sort((a, b) => String.Compare(a.Key, b.Key, StringComparison.Ordinal)); + + foreach(var assembly in typesByAssembly) + { + writer.WriteStartElement("assembly"); + writer.WriteAttributeString("fullname", assembly.Key); + List<string> assTypeNames = assembly.Select(t => t.FullName).ToList(); + assTypeNames.Sort(string.CompareOrdinal); + foreach(var typeName in assTypeNames) + { +#if UNITY_2023_1_OR_NEWER + if (typeName == "UnityEngine.Debug") + { + continue; + } +#endif + writer.WriteStartElement("type"); + writer.WriteAttributeString("fullname", typeName); + writer.WriteAttributeString("preserve", "all"); + writer.WriteEndElement(); + } + writer.WriteEndElement(); + } + writer.WriteEndElement(); + writer.WriteEndDocument(); + writer.Close(); + } + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Link/LinkXmlWriter.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Link/LinkXmlWriter.cs.meta new file mode 100644 index 0000000..4c6c61c --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Link/LinkXmlWriter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d5cc4ae4adc319b4bb1e115567d7613e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta.meta new file mode 100644 index 0000000..3291c30 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3787c7d8b775c754aa4ae06bf78e96ea +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/AssemblyCache.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/AssemblyCache.cs new file mode 100644 index 0000000..7fed930 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/AssemblyCache.cs @@ -0,0 +1,20 @@ +锘縰sing dnlib.DotNet; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; +using UnityEngine; + +namespace HybridCLR.Editor.Meta +{ + public class AssemblyCache : AssemblyCacheBase + { + + public AssemblyCache(IAssemblyResolver assemblyResolver) : base(assemblyResolver) + { + + } + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/AssemblyCache.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/AssemblyCache.cs.meta new file mode 100644 index 0000000..a99c3b2 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/AssemblyCache.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: fa4650e79a52228488aa85e0690ca52c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/AssemblyCacheBase.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/AssemblyCacheBase.cs new file mode 100644 index 0000000..04f2d15 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/AssemblyCacheBase.cs @@ -0,0 +1,99 @@ +锘縰sing dnlib.DotNet; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace HybridCLR.Editor.Meta +{ + public abstract class AssemblyCacheBase + { + private readonly IAssemblyResolver _assemblyPathResolver; + private readonly ModuleContext _modCtx; + private readonly AssemblyResolver _asmResolver; + private bool _loadedNetstandard; + + + public ModuleContext ModCtx => _modCtx; + + public Dictionary<string, ModuleDefMD> LoadedModules { get; } = new Dictionary<string, ModuleDefMD>(); + + private readonly List<ModuleDefMD> _loadedModulesIncludeNetstandard = new List<ModuleDefMD>(); + + protected AssemblyCacheBase(IAssemblyResolver assemblyResolver) + { + _assemblyPathResolver = assemblyResolver; + _modCtx = ModuleDef.CreateModuleContext(); + _asmResolver = (AssemblyResolver)_modCtx.AssemblyResolver; + _asmResolver.EnableTypeDefCache = true; + _asmResolver.UseGAC = false; + } + + + public ModuleDefMD TryLoadModule(string moduleName, bool loadReferenceAssemblies = true) + { + string dllPath = _assemblyPathResolver.ResolveAssembly(moduleName, false); + if (string.IsNullOrEmpty(dllPath)) + { + return null; + } + return LoadModule(moduleName, loadReferenceAssemblies); + } + + public ModuleDefMD LoadModule(string moduleName, bool loadReferenceAssemblies = true) + { + // Debug.Log($"load module:{moduleName}"); + if (LoadedModules.TryGetValue(moduleName, out var mod)) + { + return mod; + } + if (moduleName == "netstandard") + { + if (!_loadedNetstandard) + { + LoadNetStandard(); + } + return null; + } + mod = DoLoadModule(_assemblyPathResolver.ResolveAssembly(moduleName, true)); + LoadedModules.Add(moduleName, mod); + + if (loadReferenceAssemblies) + { + foreach (var refAsm in mod.GetAssemblyRefs()) + { + LoadModule(refAsm.Name); + } + } + + return mod; + } + + private void LoadNetStandard() + { + string netstandardDllPath = _assemblyPathResolver.ResolveAssembly("netstandard", false); + if (!string.IsNullOrEmpty(netstandardDllPath)) + { + DoLoadModule(netstandardDllPath); + } + else + { + DoLoadModule(MetaUtil.ResolveNetStandardAssemblyPath("netstandard2.0")); + DoLoadModule(MetaUtil.ResolveNetStandardAssemblyPath("netstandard2.1")); + } + _loadedNetstandard = true; + } + + private ModuleDefMD DoLoadModule(string dllPath) + { + //Debug.Log($"do load module:{dllPath}"); + ModuleDefMD mod = ModuleDefMD.Load(File.ReadAllBytes(dllPath), _modCtx); + mod.EnableTypeDefFindCache = true; + _asmResolver.AddToCache(mod); + _loadedModulesIncludeNetstandard.Add(mod); + return mod; + } + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/AssemblyCacheBase.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/AssemblyCacheBase.cs.meta new file mode 100644 index 0000000..5c02171 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/AssemblyCacheBase.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3b01fa99119e72141bfee5628c0ffce1 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/AssemblyReferenceDeepCollector.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/AssemblyReferenceDeepCollector.cs new file mode 100644 index 0000000..44c1c71 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/AssemblyReferenceDeepCollector.cs @@ -0,0 +1,50 @@ +锘縰sing dnlib.DotNet; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; +using UnityEngine; + +namespace HybridCLR.Editor.Meta +{ + public class AssemblyReferenceDeepCollector : AssemblyCacheBase + { + private readonly List<string> _rootAssemblies; + + public IReadOnlyList<string> GetRootAssemblyNames() + { + return _rootAssemblies; + } + + public List<ModuleDefMD> GetLoadedModulesExcludeRootAssemblies() + { + return LoadedModules.Where(e => !_rootAssemblies.Contains(e.Key)).Select(e => e.Value).ToList(); + } + + public List<ModuleDefMD> GetLoadedModules() + { + return LoadedModules.Select(e => e.Value).ToList(); + } + + public List<ModuleDefMD> GetLoadedModulesOfRootAssemblies() + { + return _rootAssemblies.Select(ass => LoadedModules[ass]).ToList(); + } + + public AssemblyReferenceDeepCollector(IAssemblyResolver assemblyResolver, List<string> rootAssemblies) : base(assemblyResolver) + { + _rootAssemblies = rootAssemblies; + LoadAllAssembiles(); + } + + private void LoadAllAssembiles() + { + foreach (var asm in _rootAssemblies) + { + LoadModule(asm); + } + } + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/AssemblyReferenceDeepCollector.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/AssemblyReferenceDeepCollector.cs.meta new file mode 100644 index 0000000..e93354f --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/AssemblyReferenceDeepCollector.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0342c7d8575fdea49896260c77285286 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/AssemblyResolverBase.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/AssemblyResolverBase.cs new file mode 100644 index 0000000..973619a --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/AssemblyResolverBase.cs @@ -0,0 +1,33 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace HybridCLR.Editor.Meta +{ + public abstract class AssemblyResolverBase : IAssemblyResolver + { + public string ResolveAssembly(string assemblyName, bool throwExIfNotFind) + { + if (TryResolveAssembly(assemblyName, out string assemblyPath)) + { + return assemblyPath; + } + if (throwExIfNotFind) + { + if (SettingsUtil.HotUpdateAssemblyNamesIncludePreserved.Contains(assemblyName)) + { + throw new Exception($"resolve Hot update dll:{assemblyName} failed! Please make sure that this hot update dll exists or the search path is configured in the external hot update path."); + } + else + { + throw new Exception($"resolve AOT dll:{assemblyName} failed! Please make sure that the AOT project has referenced the dll and generated the trimmed AOT dll correctly."); + } + } + return null; + } + + protected abstract bool TryResolveAssembly(string assemblyName, out string assemblyPath); + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/AssemblyResolverBase.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/AssemblyResolverBase.cs.meta new file mode 100644 index 0000000..e153d4e --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/AssemblyResolverBase.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5f8d48774b790364cbd36f1f68fd6614 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/AssemblySorter.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/AssemblySorter.cs new file mode 100644 index 0000000..3784b37 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/AssemblySorter.cs @@ -0,0 +1,105 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace HybridCLR.Editor.Meta +{ + + public class AssemblySorter + { + class Node + { + public string Name; + public List<Node> Dependencies = new List<Node>(); + + public Node(string name) + { + Name = name; + } + } + + class TopologicalSorter + { + + public static List<Node> Sort(List<Node> nodes) + { + List<Node> sorted = new List<Node>(); + HashSet<Node> visited = new HashSet<Node>(); + HashSet<Node> tempMarks = new HashSet<Node>(); + + foreach (var node in nodes) + { + if (!visited.Contains(node)) + { + Visit(node, visited, tempMarks, sorted); + } + } + return sorted; + } + + private static void Visit(Node node, HashSet<Node> visited, HashSet<Node> tempMarks, List<Node> sorted) + { + if (tempMarks.Contains(node)) + { + throw new Exception("Detected cyclic dependency!"); + } + + if (!visited.Contains(node)) + { + tempMarks.Add(node); + foreach (var dependency in node.Dependencies) + { + Visit(dependency, visited, tempMarks, sorted); + } + tempMarks.Remove(node); + visited.Add(node); + sorted.Add(node); + } + } + } + + private static List<string> SortAssemblyByReferenceOrder(IEnumerable<string> assemblies, Dictionary<string, HashSet<string>> refs) + { + var nodes = new List<Node>(); + var nodeMap = new Dictionary<string, Node>(); + foreach (var assembly in assemblies) + { + var node = new Node(assembly); + nodes.Add(node); + nodeMap.Add(assembly, node); + } + foreach (var assembly in assemblies) + { + var node = nodeMap[assembly]; + foreach (var refAssembly in refs[assembly]) + { + node.Dependencies.Add(nodeMap[refAssembly]); + } + } + var sortedNodes = TopologicalSorter.Sort(nodes); + return sortedNodes.Select(node => node.Name).ToList(); + } + + public static List<string> SortAssemblyByReferenceOrder(IEnumerable<string> assemblies, IAssemblyResolver assemblyResolver) + { + var assCache = new AssemblyCache(assemblyResolver); + var assRefAssemblies = new Dictionary<string, HashSet<string>>(); + foreach (var assName in assemblies) + { + var refAssemblies = new HashSet<string>(); + var mod = assCache.LoadModule(assName, false); + foreach (var refAss in mod.GetAssemblyRefs()) + { + if (assemblies.Contains(refAss.Name.ToString())) + { + refAssemblies.Add(refAss.Name.ToString()); + } + } + assRefAssemblies.Add(assName, refAssemblies); + } + return SortAssemblyByReferenceOrder(assemblies, assRefAssemblies); + } + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/AssemblySorter.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/AssemblySorter.cs.meta new file mode 100644 index 0000000..6fce7f9 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/AssemblySorter.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b9b8eb45398fa344daa8c6e9b9fbf291 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/CombinedAssemblyResolver.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/CombinedAssemblyResolver.cs new file mode 100644 index 0000000..31a0c51 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/CombinedAssemblyResolver.cs @@ -0,0 +1,33 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace HybridCLR.Editor.Meta +{ + public class CombinedAssemblyResolver : AssemblyResolverBase + { + private readonly IAssemblyResolver[] _resolvers; + + public CombinedAssemblyResolver(params IAssemblyResolver[] resolvers) + { + _resolvers = resolvers; + } + + protected override bool TryResolveAssembly(string assemblyName, out string assemblyPath) + { + foreach(var resolver in _resolvers) + { + var assembly = resolver.ResolveAssembly(assemblyName, false); + if (assembly != null) + { + assemblyPath = assembly; + return true; + } + } + assemblyPath = null; + return false; + } + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/CombinedAssemblyResolver.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/CombinedAssemblyResolver.cs.meta new file mode 100644 index 0000000..81b443c --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/CombinedAssemblyResolver.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 89b83906438c52d4b9af4aaef055f177 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/FixedSetAssemblyResolver.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/FixedSetAssemblyResolver.cs new file mode 100644 index 0000000..5bee4e4 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/FixedSetAssemblyResolver.cs @@ -0,0 +1,37 @@ +锘縰sing System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UnityEngine; + +namespace HybridCLR.Editor.Meta +{ + public class FixedSetAssemblyResolver : AssemblyResolverBase + { + private readonly string _rootDir; + private readonly HashSet<string> _fileNames; + + public FixedSetAssemblyResolver(string rootDir, IEnumerable<string> fileNameNotExts) + { + _rootDir = rootDir; + _fileNames = new HashSet<string>(fileNameNotExts); + } + + protected override bool TryResolveAssembly(string assemblyName, out string assemblyPath) + { + if (_fileNames.Contains(assemblyName)) + { + assemblyPath = $"{_rootDir}/{assemblyName}.dll"; + if (File.Exists(assemblyPath)) + { + Debug.Log($"[FixedSetAssemblyResolver] resolve:{assemblyName} path:{assemblyPath}"); + return true; + } + } + assemblyPath = null; + return false; + } + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/FixedSetAssemblyResolver.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/FixedSetAssemblyResolver.cs.meta new file mode 100644 index 0000000..cc4fb61 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/FixedSetAssemblyResolver.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f135accd10f42c64b9735c3aa8cb1e77 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/GenericArgumentContext.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/GenericArgumentContext.cs new file mode 100644 index 0000000..ddff3d7 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/GenericArgumentContext.cs @@ -0,0 +1,126 @@ +锘縰sing dnlib.DotNet; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace HybridCLR.Editor.Meta +{ + /// <summary> + /// Replaces generic type/method var with its generic argument + /// </summary> + public sealed class GenericArgumentContext + { + List<TypeSig> typeArgsStack = new List<TypeSig>(); + List<TypeSig> methodArgsStack = new List<TypeSig>(); + + public GenericArgumentContext(List<TypeSig> typeArgsStack, List<TypeSig> methodArgsStack) + { + this.typeArgsStack = typeArgsStack; + this.methodArgsStack = methodArgsStack; + } + + + + /// <summary> + /// Replaces a generic type/method var with its generic argument (if any). If + /// <paramref name="typeSig"/> isn't a generic type/method var or if it can't + /// be resolved, it itself is returned. Else the resolved type is returned. + /// </summary> + /// <param name="typeSig">Type signature</param> + /// <returns>New <see cref="TypeSig"/> which is never <c>null</c> unless + /// <paramref name="typeSig"/> is <c>null</c></returns> + public TypeSig Resolve(TypeSig typeSig) + { + if (!typeSig.ContainsGenericParameter) + { + return typeSig; + } + typeSig = typeSig.RemovePinnedAndModifiers(); + switch (typeSig.ElementType) + { + case ElementType.Ptr: return new PtrSig(Resolve(typeSig.Next)); + case ElementType.ByRef: return new PtrSig(Resolve(typeSig.Next)); + + case ElementType.SZArray: return new PtrSig(Resolve(typeSig.Next)); + case ElementType.Array: + { + var ara = (ArraySig)typeSig; + return new ArraySig(Resolve(typeSig.Next), ara.Rank, ara.Sizes, ara.LowerBounds); + } + + case ElementType.Var: + { + GenericVar genericVar = (GenericVar)typeSig; + var newSig = Resolve(typeArgsStack, genericVar.Number, true); + if (newSig == null) + { + throw new Exception(); + } + return newSig; + } + + case ElementType.MVar: + { + GenericMVar genericVar = (GenericMVar)typeSig; + var newSig = Resolve(methodArgsStack, genericVar.Number, true); + if (newSig == null) + { + throw new Exception(); + } + return newSig; + } + case ElementType.GenericInst: + { + var gia = (GenericInstSig)typeSig; + return new GenericInstSig(gia.GenericType, gia.GenericArguments.Select(ga => Resolve(ga)).ToList()); + } + + case ElementType.FnPtr: + { + var fptr = (FnPtrSig)typeSig; + var cs = fptr.Signature; + CallingConventionSig ccs; + switch (cs) + { + case MethodSig ms: + { + ccs = new MethodSig(ms.GetCallingConvention(), ms.GenParamCount, Resolve(ms.RetType), ms.Params.Select(p => Resolve(p)).ToList()); + break; + } + case PropertySig ps: + { + ccs = new PropertySig(ps.HasThis, Resolve(ps.RetType)); + break; + } + case GenericInstMethodSig gims: + { + ccs = new GenericInstMethodSig(gims.GenericArguments.Select(ga => Resolve(ga)).ToArray()); + break; + } + default: throw new NotSupportedException(cs.ToString()); + } + return new FnPtrSig(ccs); + } + + case ElementType.ValueArray: + { + var vas = (ValueArraySig)typeSig; + return new ValueArraySig(Resolve(vas.Next), vas.Size); + } + default: return typeSig; + } + } + + private TypeSig Resolve(List<TypeSig> args, uint number, bool isTypeVar) + { + var typeSig = args[(int)number]; + var gvar = typeSig as GenericSig; + if (gvar is null || gvar.IsTypeVar != isTypeVar) + return typeSig; + return gvar; + } + } + +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/GenericArgumentContext.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/GenericArgumentContext.cs.meta new file mode 100644 index 0000000..acb9355 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/GenericArgumentContext.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 07595a9b5b2f54c44a67022ae3e077d4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/GenericClass.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/GenericClass.cs new file mode 100644 index 0000000..0479f6f --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/GenericClass.cs @@ -0,0 +1,74 @@ +锘縰sing dnlib.DotNet; +using System.Collections.Generic; +using System.Linq; +using UnityEngine; + +namespace HybridCLR.Editor.Meta +{ + public class GenericClass + { + public TypeDef Type { get; } + + public List<TypeSig> KlassInst { get; } + + private readonly int _hashCode; + + public GenericClass(TypeDef type, List<TypeSig> classInst) + { + Type = type; + KlassInst = classInst; + _hashCode = ComputHashCode(); + } + + public GenericClass ToGenericShare() + { + return new GenericClass(Type, MetaUtil.ToShareTypeSigs(Type.Module.CorLibTypes, KlassInst)); + } + + public override bool Equals(object obj) + { + if (obj is GenericClass gc) + { + return Type == gc.Type && MetaUtil.EqualsTypeSigArray(KlassInst, gc.KlassInst); + } + return false; + } + + public override int GetHashCode() + { + return _hashCode; + } + + private int ComputHashCode() + { + int hash = TypeEqualityComparer.Instance.GetHashCode(Type); + if (KlassInst != null) + { + hash = HashUtil.CombineHash(hash, HashUtil.ComputHash(KlassInst)); + } + return hash; + } + + public TypeSig ToTypeSig() + { + return new GenericInstSig(this.Type.ToTypeSig().ToClassOrValueTypeSig(), this.KlassInst); + } + + public static GenericClass ResolveClass(TypeSpec type, GenericArgumentContext ctx) + { + var sig = type.TypeSig.ToGenericInstSig(); + if (sig == null) + { + return null; + } + TypeDef def = type.ResolveTypeDef(); + if (def == null) + { + Debug.LogWarning($"type:{type} ResolveTypeDef() == null"); + return null; + } + var klassInst = ctx != null ? sig.GenericArguments.Select(ga => MetaUtil.Inflate(ga, ctx)).ToList() : sig.GenericArguments.ToList(); + return new GenericClass(def, klassInst); + } + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/GenericClass.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/GenericClass.cs.meta new file mode 100644 index 0000000..438a1a3 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/GenericClass.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c95ff173013909548bd9e2008812f9ff +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/GenericMethod.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/GenericMethod.cs new file mode 100644 index 0000000..96252fc --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/GenericMethod.cs @@ -0,0 +1,109 @@ +锘縰sing dnlib.DotNet; +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEngine; + +namespace HybridCLR.Editor.Meta +{ + public class GenericMethod + { + public MethodDef Method { get; } + + public List<TypeSig> KlassInst { get; } + + public List<TypeSig> MethodInst { get; } + + private readonly int _hashCode; + + public GenericMethod(MethodDef method, List<TypeSig> classInst, List<TypeSig> methodInst) + { + Method = method; + KlassInst = classInst; + MethodInst = methodInst; + _hashCode = ComputHashCode(); + } + + public GenericMethod ToGenericShare() + { + ICorLibTypes corLibTypes = Method.Module.CorLibTypes; + return new GenericMethod(Method, MetaUtil.ToShareTypeSigs(corLibTypes, KlassInst), MetaUtil.ToShareTypeSigs(corLibTypes, MethodInst)); + } + + public override bool Equals(object obj) + { + GenericMethod o = (GenericMethod)obj; + return Method == o.Method + && MetaUtil.EqualsTypeSigArray(KlassInst, o.KlassInst) + && MetaUtil.EqualsTypeSigArray(MethodInst, o.MethodInst); + } + + public override int GetHashCode() + { + return _hashCode; + } + + public override string ToString() + { + return $"{Method}|{string.Join(",", (IEnumerable<TypeSig>)KlassInst ?? Array.Empty<TypeSig>())}|{string.Join(",", (IEnumerable<TypeSig>)MethodInst ?? Array.Empty<TypeSig>())}"; + } + + private int ComputHashCode() + { + int hash = MethodEqualityComparer.CompareDeclaringTypes.GetHashCode(Method); + if (KlassInst != null) + { + hash = HashUtil.CombineHash(hash, HashUtil.ComputHash(KlassInst)); + } + if (MethodInst != null) + { + hash = HashUtil.CombineHash(hash, HashUtil.ComputHash(MethodInst)); + } + return hash; + } + + public MethodSpec ToMethodSpec() + { + IMethodDefOrRef mt = KlassInst != null ? + (IMethodDefOrRef)new MemberRefUser(this.Method.Module, Method.Name, Method.MethodSig, new TypeSpecUser(new GenericInstSig(this.Method.DeclaringType.ToTypeSig().ToClassOrValueTypeSig(), this.KlassInst))) + : this.Method; + return new MethodSpecUser(mt, new GenericInstMethodSig(MethodInst)); + } + + public static GenericMethod ResolveMethod(IMethod method, GenericArgumentContext ctx) + { + //Debug.Log($"== resolve method:{method}"); + TypeDef typeDef = null; + List<TypeSig> klassInst = null; + List<TypeSig> methodInst = null; + + MethodDef methodDef = null; + + + var decalringType = method.DeclaringType; + typeDef = decalringType.ResolveTypeDef(); + if (typeDef == null) + { + return null; + } + GenericInstSig gis = decalringType.TryGetGenericInstSig(); + if (gis != null) + { + klassInst = ctx != null ? gis.GenericArguments.Select(ga => MetaUtil.Inflate(ga, ctx)).ToList() : gis.GenericArguments.ToList(); + } + methodDef = method.ResolveMethodDef(); + if (methodDef == null) + { + Debug.LogWarning($"method:{method} ResolveMethodDef() == null"); + return null; + } + if (method is MethodSpec methodSpec) + { + methodInst = ctx != null ? methodSpec.GenericInstMethodSig.GenericArguments.Select(ga => MetaUtil.Inflate(ga, ctx)).ToList() + : methodSpec.GenericInstMethodSig.GenericArguments.ToList(); + } + return new GenericMethod(methodDef, klassInst, methodInst); + } + + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/GenericMethod.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/GenericMethod.cs.meta new file mode 100644 index 0000000..ef15a5c --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/GenericMethod.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 88ecf3d52ec393b4cac142518944e487 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/IAssemblyResolver.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/IAssemblyResolver.cs new file mode 100644 index 0000000..25a6d42 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/IAssemblyResolver.cs @@ -0,0 +1,13 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace HybridCLR.Editor.Meta +{ + public interface IAssemblyResolver + { + string ResolveAssembly(string assemblyName, bool throwExIfNotFind); + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/IAssemblyResolver.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/IAssemblyResolver.cs.meta new file mode 100644 index 0000000..d56059d --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/IAssemblyResolver.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f962a018018dbb945a19f82d2e098686 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/MetaUtil.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/MetaUtil.cs new file mode 100644 index 0000000..eb95a7a --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/MetaUtil.cs @@ -0,0 +1,193 @@ +锘縰sing dnlib.DotNet; +using HybridCLR.Editor.Meta; +using HybridCLR.Editor.Settings; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UnityEditor; + +namespace HybridCLR.Editor.Meta +{ + public static class MetaUtil + { + + public static bool EqualsTypeSig(TypeSig a, TypeSig b) + { + if (a == b) + { + return true; + } + if (a != null && b != null) + { + return TypeEqualityComparer.Instance.Equals(a, b); + } + return false; + } + + public static bool EqualsTypeSigArray(List<TypeSig> a, List<TypeSig> b) + { + if (a == b) + { + return true; + } + if (a != null && b != null) + { + if (a.Count != b.Count) + { + return false; + } + for (int i = 0; i < a.Count; i++) + { + if (!TypeEqualityComparer.Instance.Equals(a[i], b[i])) + { + return false; + } + } + return true; + } + return false; + } + + public static TypeSig Inflate(TypeSig sig, GenericArgumentContext ctx) + { + if (!sig.ContainsGenericParameter) + { + return sig; + } + return ctx.Resolve(sig); + } + + public static TypeSig ToShareTypeSig(ICorLibTypes corTypes, TypeSig typeSig) + { + var a = typeSig.RemovePinnedAndModifiers(); + switch (a.ElementType) + { + case ElementType.Void: return corTypes.Void; + case ElementType.Boolean: return corTypes.Byte; + case ElementType.Char: return corTypes.UInt16; + case ElementType.I1: return corTypes.SByte; + case ElementType.U1:return corTypes.Byte; + case ElementType.I2: return corTypes.Int16; + case ElementType.U2: return corTypes.UInt16; + case ElementType.I4: return corTypes.Int32; + case ElementType.U4: return corTypes.UInt32; + case ElementType.I8: return corTypes.Int64; + case ElementType.U8: return corTypes.UInt64; + case ElementType.R4: return corTypes.Single; + case ElementType.R8: return corTypes.Double; + case ElementType.String: return corTypes.Object; + case ElementType.TypedByRef: return corTypes.TypedReference; + case ElementType.I: return corTypes.IntPtr; + case ElementType.U: return corTypes.UIntPtr; + case ElementType.Object: return corTypes.Object; + case ElementType.Sentinel: return typeSig; + case ElementType.Ptr: return corTypes.UIntPtr; + case ElementType.ByRef: return corTypes.UIntPtr; + case ElementType.SZArray: return corTypes.Object; + case ElementType.Array: return corTypes.Object; + case ElementType.ValueType: + { + TypeDef typeDef = a.ToTypeDefOrRef().ResolveTypeDef(); + if (typeDef == null) + { + throw new Exception($"type:{a} definition could not be found"); + } + if (typeDef.IsEnum) + { + return ToShareTypeSig(corTypes, typeDef.GetEnumUnderlyingType()); + } + return typeSig; + } + case ElementType.Var: + case ElementType.MVar: + case ElementType.Class: return corTypes.Object; + case ElementType.GenericInst: + { + var gia = (GenericInstSig)a; + TypeDef typeDef = gia.GenericType.ToTypeDefOrRef().ResolveTypeDef(); + if (typeDef == null) + { + throw new Exception($"type:{a} definition could not be found"); + } + if (typeDef.IsEnum) + { + return ToShareTypeSig(corTypes, typeDef.GetEnumUnderlyingType()); + } + if (!typeDef.IsValueType) + { + return corTypes.Object; + } + return new GenericInstSig(gia.GenericType, gia.GenericArguments.Select(ga => ToShareTypeSig(corTypes, ga)).ToList()); + } + case ElementType.FnPtr: return corTypes.IntPtr; + case ElementType.ValueArray: return typeSig; + case ElementType.Module: return typeSig; + default: + throw new NotSupportedException(typeSig.ToString()); + } + } + + public static List<TypeSig> ToShareTypeSigs(ICorLibTypes corTypes, IList<TypeSig> typeSigs) + { + if (typeSigs == null) + { + return null; + } + return typeSigs.Select(s => ToShareTypeSig(corTypes, s)).ToList(); + } + + public static IAssemblyResolver CreateHotUpdateAssemblyResolver(BuildTarget target, List<string> hotUpdateDlls) + { + var externalDirs = HybridCLRSettings.Instance.externalHotUpdateAssembliyDirs; + var defaultHotUpdateOutputDir = SettingsUtil.GetHotUpdateDllsOutputDirByTarget(target); + IAssemblyResolver defaultHotUpdateResolver = new FixedSetAssemblyResolver(defaultHotUpdateOutputDir, hotUpdateDlls); + if (externalDirs == null || externalDirs.Length == 0) + { + return defaultHotUpdateResolver; + } + else + { + var resolvers = new List<IAssemblyResolver>(); + foreach (var dir in externalDirs) + { + resolvers.Add(new FixedSetAssemblyResolver($"{dir}/{target}", hotUpdateDlls)); + resolvers.Add(new FixedSetAssemblyResolver(dir, hotUpdateDlls)); + } + resolvers.Add(defaultHotUpdateResolver); + return new CombinedAssemblyResolver(resolvers.ToArray()); + } + } + + public static IAssemblyResolver CreateAOTAssemblyResolver(BuildTarget target) + { + return new PathAssemblyResolver(SettingsUtil.GetAssembliesPostIl2CppStripDir(target)); + } + + public static IAssemblyResolver CreateHotUpdateAndAOTAssemblyResolver(BuildTarget target, List<string> hotUpdateDlls) + { + return new CombinedAssemblyResolver( + CreateHotUpdateAssemblyResolver(target, hotUpdateDlls), + CreateAOTAssemblyResolver(target) + ); + } + + public static string ResolveNetStandardAssemblyPath(string assemblyName) + { + return $"{SettingsUtil.HybridCLRDataPathInPackage}/NetStandard/{assemblyName}.dll"; + } + + + public static List<TypeSig> CreateDefaultGenericParams(ModuleDef module, int genericParamCount) + { + var methodGenericParams = new List<TypeSig>(); + for (int i = 0; i < genericParamCount; i++) + { + methodGenericParams.Add(module.CorLibTypes.Object); + } + return methodGenericParams; + } + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/MetaUtil.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/MetaUtil.cs.meta new file mode 100644 index 0000000..d9342a4 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/MetaUtil.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f3dbfe2e8b6a92742b18e287c5d281dd +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/MethodReferenceAnalyzer.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/MethodReferenceAnalyzer.cs new file mode 100644 index 0000000..bb36692 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/MethodReferenceAnalyzer.cs @@ -0,0 +1,79 @@ +锘縰sing dnlib.DotNet; +using HybridCLR.Editor.ABI; +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace HybridCLR.Editor.Meta +{ + public class MethodReferenceAnalyzer + { + private readonly Action<MethodDef, List<TypeSig>, List<TypeSig>, GenericMethod> _onNewMethod; + + private readonly ConcurrentDictionary<MethodDef, List<IMethod>> _methodEffectInsts = new ConcurrentDictionary<MethodDef, List<IMethod>>(); + + public MethodReferenceAnalyzer(Action<MethodDef, List<TypeSig>, List<TypeSig>, GenericMethod> onNewMethod) + { + _onNewMethod = onNewMethod; + } + + public void WalkMethod(MethodDef method, List<TypeSig> klassGenericInst, List<TypeSig> methodGenericInst) + { + var ctx = new GenericArgumentContext(klassGenericInst, methodGenericInst); + + if (_methodEffectInsts.TryGetValue(method, out var effectInsts)) + { + foreach (var met in effectInsts) + { + var resolveMet = GenericMethod.ResolveMethod(met, ctx)?.ToGenericShare(); + _onNewMethod(method, klassGenericInst, methodGenericInst, resolveMet); + } + return; + } + + var body = method.Body; + if (body == null || !body.HasInstructions) + { + return; + } + + effectInsts = new List<IMethod>(); + foreach (var inst in body.Instructions) + { + if (inst.Operand == null) + { + continue; + } + switch (inst.Operand) + { + case IMethod met: + { + if (!met.IsMethod) + { + continue; + } + var resolveMet = GenericMethod.ResolveMethod(met, ctx)?.ToGenericShare(); + if (resolveMet == null) + { + continue; + } + effectInsts.Add(met); + _onNewMethod(method, klassGenericInst, methodGenericInst, resolveMet); + break; + } + case ITokenOperand token: + { + //GenericParamContext paramContext = method.HasGenericParameters || method.DeclaringType.HasGenericParameters ? + // new GenericParamContext(method.DeclaringType, method) : default; + //method.Module.ResolveToken(token.MDToken, paramContext); + break; + } + } + } + _methodEffectInsts.TryAdd(method, effectInsts); + } + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/MethodReferenceAnalyzer.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/MethodReferenceAnalyzer.cs.meta new file mode 100644 index 0000000..7554a58 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/MethodReferenceAnalyzer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1c644b0c018fb87498d69c3202439d21 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/PathAssemblyResolver.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/PathAssemblyResolver.cs new file mode 100644 index 0000000..a356117 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/PathAssemblyResolver.cs @@ -0,0 +1,35 @@ +锘縰sing System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UnityEngine; + +namespace HybridCLR.Editor.Meta +{ + public class PathAssemblyResolver : AssemblyResolverBase + { + private readonly string[] _searchPaths; + public PathAssemblyResolver(params string[] searchPaths) + { + _searchPaths = searchPaths; + } + + protected override bool TryResolveAssembly(string assemblyName, out string assemblyPath) + { + foreach(var path in _searchPaths) + { + string assPath = Path.Combine(path, assemblyName + ".dll"); + if (File.Exists(assPath)) + { + Debug.Log($"resolve {assemblyName} at {assPath}"); + assemblyPath = assPath; + return true; + } + } + assemblyPath = null; + return false; + } + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/PathAssemblyResolver.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/PathAssemblyResolver.cs.meta new file mode 100644 index 0000000..af02cb8 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Meta/PathAssemblyResolver.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 121d574bf01969444aa6619a8f6dbb4c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/MethodBridge.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/MethodBridge.meta new file mode 100644 index 0000000..5ff8e80 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/MethodBridge.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 0c2444f09010bce41a52d951b7100c49 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/MethodBridge/Analyzer.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/MethodBridge/Analyzer.cs new file mode 100644 index 0000000..dd0fd66 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/MethodBridge/Analyzer.cs @@ -0,0 +1,205 @@ +锘縰sing dnlib.DotNet; +using HybridCLR.Editor.ABI; +using HybridCLR.Editor.Meta; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UnityEngine; + +namespace HybridCLR.Editor.MethodBridge +{ + + public class Analyzer + { + public class Options + { + public AssemblyReferenceDeepCollector Collector { get; set; } + + public int MaxIterationCount { get; set; } + } + + private readonly int _maxInterationCount; + private readonly AssemblyReferenceDeepCollector _assemblyCollector; + + private readonly object _lock = new object(); + + private readonly List<TypeDef> _typeDefs = new List<TypeDef>(); + + private readonly HashSet<GenericClass> _genericTypes = new HashSet<GenericClass>(); + private readonly HashSet<GenericMethod> _genericMethods = new HashSet<GenericMethod>(); + + private List<GenericMethod> _processingMethods = new List<GenericMethod>(); + private List<GenericMethod> _newMethods = new List<GenericMethod>(); + + public IReadOnlyList<TypeDef> TypeDefs => _typeDefs; + + public IReadOnlyCollection<GenericClass> GenericTypes => _genericTypes; + + public IReadOnlyCollection<GenericMethod> GenericMethods => _genericMethods; + + + private readonly MethodReferenceAnalyzer _methodReferenceAnalyzer; + + public Analyzer(Options options) + { + _maxInterationCount = options.MaxIterationCount; + _assemblyCollector = options.Collector; + _methodReferenceAnalyzer = new MethodReferenceAnalyzer(this.OnNewMethod); + } + + private void TryAddAndWalkGenericType(GenericClass gc) + { + if (gc == null) + { + return; + } + lock(_lock) + { + gc = StandardizeClass(gc); + if (_genericTypes.Add(gc)) + { + WalkType(gc); + } + } + } + + private GenericClass StandardizeClass(GenericClass gc) + { + TypeDef typeDef = gc.Type; + ICorLibTypes corLibTypes = typeDef.Module.CorLibTypes; + List<TypeSig> klassGenericParams = gc.KlassInst != null ? MetaUtil.ToShareTypeSigs(corLibTypes, gc.KlassInst) : (typeDef.GenericParameters.Count > 0 ? MetaUtil.CreateDefaultGenericParams(typeDef.Module, typeDef.GenericParameters.Count) : null); + return new GenericClass(typeDef, klassGenericParams); + } + + private GenericMethod StandardizeMethod(GenericMethod gm) + { + TypeDef typeDef = gm.Method.DeclaringType; + ICorLibTypes corLibTypes = typeDef.Module.CorLibTypes; + List<TypeSig> klassGenericParams = gm.KlassInst != null ? MetaUtil.ToShareTypeSigs(corLibTypes, gm.KlassInst) : (typeDef.GenericParameters.Count > 0 ? MetaUtil.CreateDefaultGenericParams(typeDef.Module, typeDef.GenericParameters.Count) : null); + List<TypeSig> methodGenericParams = gm.MethodInst != null ? MetaUtil.ToShareTypeSigs(corLibTypes, gm.MethodInst) : (gm.Method.GenericParameters.Count > 0 ? MetaUtil.CreateDefaultGenericParams(typeDef.Module, gm.Method.GenericParameters.Count) : null); + return new GenericMethod(gm.Method, klassGenericParams, methodGenericParams); + } + + private void OnNewMethod(MethodDef methodDef, List<TypeSig> klassGenericInst, List<TypeSig> methodGenericInst, GenericMethod method) + { + lock(_lock) + { + method = StandardizeMethod(method); + if (_genericMethods.Add(method)) + { + _newMethods.Add(method); + } + if (method.KlassInst != null) + { + TryAddAndWalkGenericType(new GenericClass(method.Method.DeclaringType, method.KlassInst)); + } + } + } + + private void WalkType(GenericClass gc) + { + //Debug.Log($"typespec:{sig} {sig.GenericType} {sig.GenericType.TypeDefOrRef.ResolveTypeDef()}"); + //Debug.Log($"== walk generic type:{new GenericInstSig(gc.Type.ToTypeSig().ToClassOrValueTypeSig(), gc.KlassInst)}"); + ITypeDefOrRef baseType = gc.Type.BaseType; + if (baseType != null && baseType.TryGetGenericInstSig() != null) + { + GenericClass parentType = GenericClass.ResolveClass((TypeSpec)baseType, new GenericArgumentContext(gc.KlassInst, null)); + TryAddAndWalkGenericType(parentType); + } + foreach (var method in gc.Type.Methods) + { + var gm = StandardizeMethod(new GenericMethod(method, gc.KlassInst, null)); + //Debug.Log($"add method:{gm.Method} {gm.KlassInst}"); + + if (_genericMethods.Add(gm)) + { + if (method.HasBody && method.Body.Instructions != null) + { + _newMethods.Add(gm); + } + } + } + } + + private void WalkType(TypeDef typeDef) + { + _typeDefs.Add(typeDef); + ITypeDefOrRef baseType = typeDef.BaseType; + if (baseType != null && baseType.TryGetGenericInstSig() != null) + { + GenericClass gc = GenericClass.ResolveClass((TypeSpec)baseType, null); + TryAddAndWalkGenericType(gc); + } + foreach (var method in typeDef.Methods) + { + // 瀵逛簬甯︽硾鍨嬬殑鍙傛暟锛岀粺涓�娉涘瀷鍏变韩涓簅bject + var gm = StandardizeMethod(new GenericMethod(method, null, null)); + _genericMethods.Add(gm); + } + } + + private void Prepare() + { + // 灏嗘墍鏈夐潪娉涘瀷鍑芥暟鍏ㄩ儴鍔犲叆鍑芥暟鍒楄〃锛屽悓鏃剁珛椹瑆alk杩欎簺method銆� + // 鍚庣画杩唬涓皢鍙亶鍘哅ethodSpec + foreach (var ass in _assemblyCollector.GetLoadedModules()) + { + foreach (TypeDef typeDef in ass.GetTypes()) + { + WalkType(typeDef); + } + + for (uint rid = 1, n = ass.Metadata.TablesStream.TypeSpecTable.Rows; rid <= n; rid++) + { + var ts = ass.ResolveTypeSpec(rid); + var cs = GenericClass.ResolveClass(ts, null); + if (cs != null) + { + TryAddAndWalkGenericType(cs); + } + } + + for (uint rid = 1, n = ass.Metadata.TablesStream.MethodSpecTable.Rows; rid <= n; rid++) + { + var ms = ass.ResolveMethodSpec(rid); + var gm = GenericMethod.ResolveMethod(ms, null)?.ToGenericShare(); + if (gm == null) + { + continue; + } + gm = StandardizeMethod(gm); + if (_genericMethods.Add(gm)) + { + _newMethods.Add(gm); + } + } + } + Debug.Log($"PostPrepare allMethods:{_genericMethods.Count} newMethods:{_newMethods.Count}"); + } + + private void RecursiveCollect() + { + for (int i = 0; i < _maxInterationCount && _newMethods.Count > 0; i++) + { + var temp = _processingMethods; + _processingMethods = _newMethods; + _newMethods = temp; + _newMethods.Clear(); + + Task.WaitAll(_processingMethods.Select(method => Task.Run(() => + { + _methodReferenceAnalyzer.WalkMethod(method.Method, method.KlassInst, method.MethodInst); + })).ToArray()); + Debug.Log($"iteration:[{i}] genericClass:{_genericTypes.Count} genericMethods:{_genericMethods.Count} newMethods:{_newMethods.Count}"); + } + } + + public void Run() + { + Prepare(); + RecursiveCollect(); + } + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/MethodBridge/Analyzer.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/MethodBridge/Analyzer.cs.meta new file mode 100644 index 0000000..4fd796f --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/MethodBridge/Analyzer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ee1ec106190e514489c7ba32bc7bc2e7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/MethodBridge/CalliAnalyzer.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/MethodBridge/CalliAnalyzer.cs new file mode 100644 index 0000000..2027135 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/MethodBridge/CalliAnalyzer.cs @@ -0,0 +1,70 @@ +锘縰sing dnlib.DotNet; +using HybridCLR.Editor.Meta; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UnityEngine; + +namespace HybridCLR.Editor.MethodBridge +{ + + public class RawCalliMethodSignatureInfo + { + public MethodSig MethodSig { get; set; } + } + + public class CalliAnalyzer + { + private readonly List<ModuleDefMD> _rootModules = new List<ModuleDefMD>(); + + private readonly List<RawCalliMethodSignatureInfo> _calliMethodSignatures = new List<RawCalliMethodSignatureInfo>(); + + public List<RawCalliMethodSignatureInfo> CalliMethodSignatures => _calliMethodSignatures; + + public CalliAnalyzer(AssemblyCache cache, List<string> assemblyNames) + { + foreach (var assemblyName in assemblyNames) + { + _rootModules.Add(cache.LoadModule(assemblyName)); + } + } + + private void CollectCalli() + { + foreach (var mod in _rootModules) + { + Debug.Log($"ass:{mod.FullName} methodcount:{mod.Metadata.TablesStream.MethodTable.Rows}"); + for (uint rid = 1, n = mod.Metadata.TablesStream.MethodTable.Rows; rid <= n; rid++) + { + var method = mod.ResolveMethod(rid); + //Debug.Log($"method:{method}"); + if (!method.HasBody) + { + continue; + } + + foreach (var il in method.Body.Instructions) + { + if (il.OpCode.Code == dnlib.DotNet.Emit.Code.Calli) + { + MethodSig methodSig = (MethodSig)il.Operand; + + _calliMethodSignatures.Add(new RawCalliMethodSignatureInfo() + { + MethodSig = methodSig, + }); + Debug.Log($"method:{method} calli method signature:{methodSig}"); + } + } + } + } + } + + public void Run() + { + CollectCalli(); + } + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/MethodBridge/CalliAnalyzer.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/MethodBridge/CalliAnalyzer.cs.meta new file mode 100644 index 0000000..620c7c7 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/MethodBridge/CalliAnalyzer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6ce33c8e48da5a649b261ba3a60fd3b9 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/MethodBridge/Generator.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/MethodBridge/Generator.cs new file mode 100644 index 0000000..73a29e1 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/MethodBridge/Generator.cs @@ -0,0 +1,1256 @@ +锘縰sing dnlib.DotNet; +using HybridCLR.Editor.ABI; +using HybridCLR.Editor.Meta; +using HybridCLR.Editor.ReversePInvokeWrap; +using HybridCLR.Editor.Template; +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; +using UnityEditor; +using UnityEngine; +using TypeInfo = HybridCLR.Editor.ABI.TypeInfo; +using CallingConvention = System.Runtime.InteropServices.CallingConvention; +using TypeAttributes = dnlib.DotNet.TypeAttributes; +using System.Runtime.InteropServices; + +namespace HybridCLR.Editor.MethodBridge +{ + public class Generator + { + public class Options + { + public string TemplateCode { get; set; } + + public string OutputFile { get; set; } + + public IReadOnlyCollection<GenericMethod> GenericMethods { get; set; } + + public List<RawReversePInvokeMethodInfo> ReversePInvokeMethods { get; set; } + + public IReadOnlyCollection<RawCalliMethodSignatureInfo> CalliMethodSignatures { get; set; } + + public bool Development { get; set; } + } + + private class ABIReversePInvokeMethodInfo + { + public MethodDesc Method { get; set; } + + public CallingConvention Callvention { get; set; } + + public int Count { get; set; } + + public string Signature { get; set; } + } + + private class CalliMethodInfo + { + public MethodDesc Method { get; set; } + + public CallingConvention Callvention { get; set; } + + public string Signature { get; set; } + } + + private readonly List<GenericMethod> _genericMethods; + + private readonly List<RawReversePInvokeMethodInfo> _originalReversePInvokeMethods; + + private readonly List<RawCalliMethodSignatureInfo> _originalCalliMethodSignatures; + + private readonly string _templateCode; + + private readonly string _outputFile; + + private readonly bool _development; + + private readonly TypeCreator _typeCreator; + + private readonly HashSet<MethodDesc> _managed2nativeMethodSet = new HashSet<MethodDesc>(); + + private readonly HashSet<MethodDesc> _native2managedMethodSet = new HashSet<MethodDesc>(); + + private readonly HashSet<MethodDesc> _adjustThunkMethodSet = new HashSet<MethodDesc>(); + + private List<ABIReversePInvokeMethodInfo> _reversePInvokeMethods; + + private List<CalliMethodInfo> _callidMethods; + + public Generator(Options options) + { + List<(GenericMethod, string)> genericMethodInfo = options.GenericMethods.Select(m => (m, m.ToString())).ToList(); + genericMethodInfo.Sort((a, b) => string.CompareOrdinal(a.Item2, b.Item2)); + _genericMethods = genericMethodInfo.Select(m => m.Item1).ToList(); + _originalReversePInvokeMethods = options.ReversePInvokeMethods; + _originalCalliMethodSignatures = options.CalliMethodSignatures.ToList(); + + _templateCode = options.TemplateCode; + _outputFile = options.OutputFile; + _typeCreator = new TypeCreator(); + _development = options.Development; + } + + private readonly Dictionary<string, TypeInfo> _sig2Types = new Dictionary<string, TypeInfo>(); + + private TypeInfo GetSharedTypeInfo(TypeSig type) + { + var typeInfo = _typeCreator.CreateTypeInfo(type); + if (!typeInfo.IsStruct) + { + return typeInfo; + } + string sigName = ToFullName(typeInfo.Klass); + if (!_sig2Types.TryGetValue(sigName, out var sharedTypeInfo)) + { + sharedTypeInfo = typeInfo; + _sig2Types.Add(sigName, sharedTypeInfo); + } + return sharedTypeInfo; + } + + private MethodDesc CreateMethodDesc(MethodDef methodDef, bool forceRemoveThis, TypeSig returnType, List<TypeSig> parameters) + { + var paramInfos = new List<ParamInfo>(); + if (forceRemoveThis && !methodDef.IsStatic) + { + parameters.RemoveAt(0); + } + if (returnType.ContainsGenericParameter) + { + throw new Exception($"[PreservedMethod] method:{methodDef} has generic parameters"); + } + foreach (var paramInfo in parameters) + { + if (paramInfo.ContainsGenericParameter) + { + throw new Exception($"[PreservedMethod] method:{methodDef} has generic parameters"); + } + paramInfos.Add(new ParamInfo() { Type = GetSharedTypeInfo(paramInfo) }); + } + var mbs = new MethodDesc() + { + MethodDef = methodDef, + ReturnInfo = new ReturnInfo() { Type = returnType != null ? GetSharedTypeInfo(returnType) : TypeInfo.s_void }, + ParamInfos = paramInfos, + }; + return mbs; + } + + private MethodDesc CreateMethodDesc(TypeSig returnType, List<TypeSig> parameters) + { + var paramInfos = new List<ParamInfo>(); + if (returnType.ContainsGenericParameter) + { + throw new Exception($"[PreservedMethod] method has generic parameters"); + } + foreach (var paramInfo in parameters) + { + if (paramInfo.ContainsGenericParameter) + { + throw new Exception($"[PreservedMethod] method has generic parameters"); + } + paramInfos.Add(new ParamInfo() { Type = GetSharedTypeInfo(paramInfo) }); + } + var mbs = new MethodDesc() + { + MethodDef = null, + ReturnInfo = new ReturnInfo() { Type = returnType != null ? GetSharedTypeInfo(returnType) : TypeInfo.s_void }, + ParamInfos = paramInfos, + }; + return mbs; + } + + private void AddManaged2NativeMethod(MethodDesc method) + { + method.Init(); + _managed2nativeMethodSet.Add(method); + } + + private void AddNative2ManagedMethod(MethodDesc method) + { + method.Init(); + _native2managedMethodSet.Add(method); + } + + private void AddAdjustThunkMethod(MethodDesc method) + { + method.Init(); + _adjustThunkMethodSet.Add(method); + } + + private void ProcessMethod(MethodDef method, List<TypeSig> klassInst, List<TypeSig> methodInst) + { + if (method.IsPrivate || (method.IsAssembly && !method.IsPublic && !method.IsFamily)) + { + if (klassInst == null && methodInst == null) + { + return; + } + else + { + //Debug.Log($"[PreservedMethod] method:{method}"); + } + } + ICorLibTypes corLibTypes = method.Module.CorLibTypes; + TypeSig returnType; + List<TypeSig> parameters; + if (klassInst == null && methodInst == null) + { + if (method.HasGenericParameters) + { + throw new Exception($"[PreservedMethod] method:{method} has generic parameters"); + } + returnType = MetaUtil.ToShareTypeSig(corLibTypes, method.ReturnType); + parameters = method.Parameters.Select(p => MetaUtil.ToShareTypeSig(corLibTypes, p.Type)).ToList(); + } + else + { + var gc = new GenericArgumentContext(klassInst, methodInst); + returnType = MetaUtil.ToShareTypeSig(corLibTypes, MetaUtil.Inflate(method.ReturnType, gc)); + parameters = method.Parameters.Select(p => MetaUtil.ToShareTypeSig(corLibTypes, MetaUtil.Inflate(p.Type, gc))).ToList(); + } + + var m2nMethod = CreateMethodDesc(method, false, returnType, parameters); + AddManaged2NativeMethod(m2nMethod); + + if (method.IsVirtual) + { + if (method.DeclaringType.IsInterface) + { + AddAdjustThunkMethod(m2nMethod); + } + //var adjustThunkMethod = CreateMethodDesc(method, true, returnType, parameters); + AddNative2ManagedMethod(m2nMethod); + } + if (method.Name == "Invoke" && method.DeclaringType.IsDelegate) + { + var openMethod = CreateMethodDesc(method, true, returnType, parameters); + AddNative2ManagedMethod(openMethod); + } + } + + private void PrepareMethodBridges() + { + foreach (var method in _genericMethods) + { + ProcessMethod(method.Method, method.KlassInst, method.MethodInst); + } + foreach (var reversePInvokeMethod in _originalReversePInvokeMethods) + { + MethodDef method = reversePInvokeMethod.Method; + ICorLibTypes corLibTypes = method.Module.CorLibTypes; + + var returnType = MetaUtil.ToShareTypeSig(corLibTypes, method.ReturnType); + var parameters = method.Parameters.Select(p => MetaUtil.ToShareTypeSig(corLibTypes, p.Type)).ToList(); + var sharedMethod = CreateMethodDesc(method, true, returnType, parameters); + sharedMethod.Init(); + AddNative2ManagedMethod(sharedMethod); + } + } + + static void CheckUnique(IEnumerable<string> names) + { + var set = new HashSet<string>(); + foreach (var name in names) + { + if (!set.Add(name)) + { + throw new Exception($"[CheckUnique] duplicate name:{name}"); + } + } + } + + + private List<MethodDesc> _managed2NativeMethodList0; + private List<MethodDesc> _native2ManagedMethodList0; + private List<MethodDesc> _adjustThunkMethodList0; + + private List<TypeInfo> _structTypes0; + + private void CollectTypesAndMethods() + { + _managed2NativeMethodList0 = _managed2nativeMethodSet.ToList(); + _managed2NativeMethodList0.Sort((a, b) => string.CompareOrdinal(a.Sig, b.Sig)); + + _native2ManagedMethodList0 = _native2managedMethodSet.ToList(); + _native2ManagedMethodList0.Sort((a, b) => string.CompareOrdinal(a.Sig, b.Sig)); + + _adjustThunkMethodList0 = _adjustThunkMethodSet.ToList(); + _adjustThunkMethodList0.Sort((a, b) => string.CompareOrdinal(a.Sig, b.Sig)); + + + var structTypeSet = new HashSet<TypeInfo>(); + CollectStructDefs(_managed2NativeMethodList0, structTypeSet); + CollectStructDefs(_native2ManagedMethodList0, structTypeSet); + CollectStructDefs(_adjustThunkMethodList0, structTypeSet); + _structTypes0 = structTypeSet.ToList(); + _structTypes0.Sort((a, b) => a.TypeId - b.TypeId); + + CheckUnique(_structTypes0.Select(t => ToFullName(t.Klass))); + CheckUnique(_structTypes0.Select(t => t.CreateSigName())); + + Debug.LogFormat("== before optimization struct:{3} managed2native:{0} native2managed:{1} adjustThunk:{2}", + _managed2NativeMethodList0.Count, _native2ManagedMethodList0.Count, _adjustThunkMethodList0.Count, _structTypes0.Count); + } + + private class AnalyzeFieldInfo + { + public FieldDef field; + + public TypeInfo type; + } + + private class AnalyzeTypeInfo + { + public TypeInfo isoType; + public List<AnalyzeFieldInfo> fields; + public string signature; + public uint originalPackingSize; + public uint packingSize; + public uint classSize; + public LayoutKind layout; + public bool blittable; + } + + private readonly Dictionary<TypeInfo, AnalyzeTypeInfo> _analyzeTypeInfos = new Dictionary<TypeInfo, AnalyzeTypeInfo>(); + + private readonly Dictionary<string, TypeInfo> _signature2Type = new Dictionary<string, TypeInfo>(); + + + + private bool IsBlittable(TypeSig typeSig) + { + typeSig = typeSig.RemovePinnedAndModifiers(); + if (typeSig.IsByRef) + { + return true; + } + switch (typeSig.ElementType) + { + case ElementType.Void: return false; + case ElementType.Boolean: + case ElementType.I1: + case ElementType.U1: + case ElementType.I2: + case ElementType.Char: + case ElementType.U2: + case ElementType.I4: + case ElementType.U4: + case ElementType.I8: + case ElementType.U8: + case ElementType.R4: + case ElementType.R8: + case ElementType.I: + case ElementType.U: + case ElementType.Ptr: + case ElementType.ByRef: + case ElementType.FnPtr: + case ElementType.TypedByRef: return true; + case ElementType.String: + case ElementType.Class: + case ElementType.Array: + case ElementType.SZArray: + case ElementType.Object: + case ElementType.Module: + case ElementType.Var: + case ElementType.MVar: return false; + case ElementType.ValueType: + { + TypeDef typeDef = typeSig.ToTypeDefOrRef().ResolveTypeDef(); + if (typeDef == null) + { + throw new Exception($"type:{typeSig} definition could not be found. Please try `HybridCLR/Genergate/LinkXml`, then Build once to generate the AOT dll, and then regenerate the bridge function"); + } + if (typeDef.IsEnum) + { + return true; + } + return CalculateAnalyzeTypeInfoBasic(GetSharedTypeInfo(typeSig)).blittable; + } + case ElementType.GenericInst: + { + GenericInstSig gis = (GenericInstSig)typeSig; + if (!gis.GenericType.IsValueType) + { + return false; + } + TypeDef typeDef = gis.GenericType.ToTypeDefOrRef().ResolveTypeDef(); + if (typeDef.IsEnum) + { + return true; + } + return CalculateAnalyzeTypeInfoBasic(GetSharedTypeInfo(typeSig)).blittable; + } + default: throw new NotSupportedException($"{typeSig.ElementType}"); + } + } + + private AnalyzeTypeInfo CalculateAnalyzeTypeInfoBasic(TypeInfo typeInfo) + { + Debug.Assert(typeInfo.IsStruct); + if (_analyzeTypeInfos.TryGetValue(typeInfo, out var ati)) + { + return ati; + } + TypeSig type = typeInfo.Klass; + TypeDef typeDef = type.ToTypeDefOrRef().ResolveTypeDefThrow(); + + List<TypeSig> klassInst = type.ToGenericInstSig()?.GenericArguments?.ToList(); + GenericArgumentContext ctx = klassInst != null ? new GenericArgumentContext(klassInst, null) : null; + + var fields = new List<AnalyzeFieldInfo>(); + + bool blittable = true; + foreach (FieldDef field in typeDef.Fields) + { + if (field.IsStatic) + { + continue; + } + TypeSig fieldType = ctx != null ? MetaUtil.Inflate(field.FieldType, ctx) : field.FieldType; + blittable &= IsBlittable(fieldType); + TypeInfo sharedFieldTypeInfo = GetSharedTypeInfo(fieldType); + TypeInfo isoType = ToIsomorphicType(sharedFieldTypeInfo); + fields.Add(new AnalyzeFieldInfo { field = field, type = isoType }); + } + //analyzeTypeInfo.blittable = blittable; + //analyzeTypeInfo.packingSize = blittable ? analyzeTypeInfo.originalPackingSize : 0; + + ClassLayout sa = typeDef.ClassLayout; + uint originalPackingSize = sa?.PackingSize ?? 0; + var analyzeTypeInfo = new AnalyzeTypeInfo() + { + originalPackingSize = originalPackingSize, + packingSize = blittable && !typeDef.IsAutoLayout ? originalPackingSize : 0, + classSize = sa?.ClassSize ?? 0, + layout = typeDef.IsAutoLayout ? LayoutKind.Auto : (typeDef.IsExplicitLayout ? LayoutKind.Explicit : LayoutKind.Sequential), + fields = fields, + blittable = blittable, + }; + _analyzeTypeInfos.Add(typeInfo, analyzeTypeInfo); + analyzeTypeInfo.signature = GetOrCalculateTypeInfoSignature(typeInfo); + + if (_signature2Type.TryGetValue(analyzeTypeInfo.signature, out var sharedType)) + { + // Debug.Log($"[ToIsomorphicType] type:{type.Klass} ==> sharedType:{sharedType.Klass} signature:{signature} "); + analyzeTypeInfo.isoType = sharedType; + } + else + { + analyzeTypeInfo.isoType = typeInfo; + _signature2Type.Add(analyzeTypeInfo.signature, typeInfo); + } + + return analyzeTypeInfo; + } + + private string GetOrCalculateTypeInfoSignature(TypeInfo typeInfo) + { + if (!typeInfo.IsStruct) + { + return typeInfo.CreateSigName(); + } + + var ati = _analyzeTypeInfos[typeInfo]; + + //if (_analyzeTypeInfos.TryGetValue(typeInfo, out var ati)) + //{ + // return ati.signature; + //} + //ati = CalculateAnalyzeTypeInfoBasic(typeInfo); + //_analyzeTypeInfos.Add(typeInfo, ati); + if (ati.signature != null) + { + return ati.signature; + } + + var sigBuf = new StringBuilder(); + if (ati.packingSize != 0 || ati.classSize != 0 || ati.layout != LayoutKind.Sequential || !ati.blittable) + { + sigBuf.Append($"[{ati.classSize}|{ati.packingSize}|{ati.layout}|{(ati.blittable ? 0 : 1)}]"); + } + foreach (var field in ati.fields) + { + string fieldOffset = field.field.FieldOffset != null ? field.field.FieldOffset.ToString() + "|" : ""; + sigBuf.Append("{" + fieldOffset + GetOrCalculateTypeInfoSignature(ToIsomorphicType(field.type)) + "}"); + } + return ati.signature = sigBuf.ToString(); + } + + private TypeInfo ToIsomorphicType(TypeInfo type) + { + if (!type.IsStruct) + { + return type; + } + return CalculateAnalyzeTypeInfoBasic(type).isoType; + } + + private MethodDesc ToIsomorphicMethod(MethodDesc method) + { + var paramInfos = new List<ParamInfo>(); + foreach (var paramInfo in method.ParamInfos) + { + paramInfos.Add(new ParamInfo() { Type = ToIsomorphicType(paramInfo.Type) }); + } + var mbs = new MethodDesc() + { + MethodDef = method.MethodDef, + ReturnInfo = new ReturnInfo() { Type = ToIsomorphicType(method.ReturnInfo.Type) }, + ParamInfos = paramInfos, + }; + mbs.Init(); + return mbs; + } + + private List<MethodDesc> _managed2NativeMethodList; + private List<MethodDesc> _native2ManagedMethodList; + private List<MethodDesc> _adjustThunkMethodList; + + private List<TypeInfo> structTypes; + + private void BuildAnalyzeTypeInfos() + { + foreach (var type in _structTypes0) + { + ToIsomorphicType(type); + } + structTypes = _signature2Type.Values.ToList(); + structTypes.Sort((a, b) => a.TypeId - b.TypeId); + } + + private List<MethodDesc> ToUniqueOrderedList(List<MethodDesc> methods) + { + var methodMap = new SortedDictionary<string, MethodDesc>(); + foreach (var method in methods) + { + var sharedMethod = ToIsomorphicMethod(method); + var sig = sharedMethod.Sig; + if (!methodMap.TryGetValue(sig, out var _)) + { + methodMap.Add(sig, sharedMethod); + } + } + return methodMap.Values.ToList(); + } + + + + private static string MakeReversePInvokeSignature(MethodDesc desc, CallingConvention CallingConventionention) + { + string convStr = ((char)('A' + (int)CallingConventionention - 1)).ToString(); + return $"{convStr}{desc.Sig}"; + } + private static string MakeCalliSignature(MethodDesc desc, CallingConvention CallingConventionention) + { + string convStr = ((char)('A' + Math.Max((int)CallingConventionention - 1, 0))).ToString(); + return $"{convStr}{desc.Sig}"; + } + + private static CallingConvention GetCallingConvention(MethodDef method) + { + var monoPInvokeCallbackAttr = method.CustomAttributes.FirstOrDefault(ca => ca.AttributeType.Name == "MonoPInvokeCallbackAttribute"); + if (monoPInvokeCallbackAttr == null) + { + return CallingConvention.Winapi; + } + object delegateTypeSig = monoPInvokeCallbackAttr.ConstructorArguments[0].Value; + + TypeDef delegateTypeDef; + if (delegateTypeSig is ClassSig classSig) + { + delegateTypeDef = classSig.TypeDefOrRef.ResolveTypeDefThrow(); + } + else if (delegateTypeSig is GenericInstSig genericInstSig) + { + delegateTypeDef = genericInstSig.GenericType.TypeDefOrRef.ResolveTypeDefThrow(); + } + else + { + delegateTypeDef = null; + } + + if (delegateTypeDef == null) + { + throw new NotSupportedException($"Unsupported delegate type: {delegateTypeSig}"); + } + var attr = delegateTypeDef.CustomAttributes.FirstOrDefault(ca => ca.AttributeType.FullName == "System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute"); + if (attr == null) + { + return CallingConvention.Winapi; + } + var conv = attr.ConstructorArguments[0].Value; + return (CallingConvention)conv; + } + + private List<ABIReversePInvokeMethodInfo> BuildABIMethods(List<RawReversePInvokeMethodInfo> rawMethods) + { + var methodsBySig = new Dictionary<string, ABIReversePInvokeMethodInfo>(); + foreach (var method in rawMethods) + { + var sharedMethod = new MethodDesc + { + MethodDef = method.Method, + ReturnInfo = new ReturnInfo { Type = GetSharedTypeInfo(method.Method.ReturnType) }, + ParamInfos = method.Method.Parameters.Select(p => new ParamInfo { Type = GetSharedTypeInfo(p.Type) }).ToList(), + }; + sharedMethod.Init(); + sharedMethod = ToIsomorphicMethod(sharedMethod); + + CallingConvention callingConv = GetCallingConvention(method.Method); + string signature = MakeReversePInvokeSignature(sharedMethod, callingConv); + + if (!methodsBySig.TryGetValue(signature, out var arm)) + { + arm = new ABIReversePInvokeMethodInfo() + { + Method = sharedMethod, + Signature = signature, + Count = 0, + Callvention = callingConv, + }; + methodsBySig.Add(signature, arm); + } + int preserveCount = method.GenerationAttribute != null ? (int)method.GenerationAttribute.ConstructorArguments[0].Value : 1; + arm.Count += preserveCount; + } + var newMethods = methodsBySig.Values.ToList(); + newMethods.Sort((a, b) => string.CompareOrdinal(a.Signature, b.Signature)); + return newMethods; + } + + private List<CalliMethodInfo> BuildCalliMethods(List<RawCalliMethodSignatureInfo> rawMethods) + { + var methodsBySig = new Dictionary<string, CalliMethodInfo>(); + foreach (var method in rawMethods) + { + var sharedMethod = new MethodDesc + { + MethodDef = null, + ReturnInfo = new ReturnInfo { Type = GetSharedTypeInfo(method.MethodSig.RetType) }, + ParamInfos = method.MethodSig.Params.Select(p => new ParamInfo { Type = GetSharedTypeInfo(p) }).ToList(), + }; + sharedMethod.Init(); + sharedMethod = ToIsomorphicMethod(sharedMethod); + + CallingConvention callingConv = (CallingConvention)((int)method.MethodSig.CallingConvention + 1); + string signature = MakeCalliSignature(sharedMethod, callingConv); + + if (!methodsBySig.TryGetValue(signature, out var arm)) + { + arm = new CalliMethodInfo() + { + Method = sharedMethod, + Signature = signature, + Callvention = callingConv, + }; + methodsBySig.Add(signature, arm); + } + } + var newMethods = methodsBySig.Values.ToList(); + newMethods.Sort((a, b) => string.CompareOrdinal(a.Signature, b.Signature)); + return newMethods; + } + + private void BuildOptimizedMethods() + { + _managed2NativeMethodList = ToUniqueOrderedList(_managed2NativeMethodList0); + _native2ManagedMethodList = ToUniqueOrderedList(_native2ManagedMethodList0); + _adjustThunkMethodList = ToUniqueOrderedList(_adjustThunkMethodList0); + _reversePInvokeMethods = BuildABIMethods(_originalReversePInvokeMethods); + _callidMethods = BuildCalliMethods(_originalCalliMethodSignatures); + } + + private void OptimizationTypesAndMethods() + { + BuildAnalyzeTypeInfos(); + BuildOptimizedMethods(); + Debug.LogFormat("== after optimization struct:{3} managed2native:{0} native2managed:{1} adjustThunk:{2}", + _managed2NativeMethodList.Count, _native2ManagedMethodList.Count, _adjustThunkMethodList.Count, structTypes.Count); + } + + private void GenerateCode() + { + var frr = new FileRegionReplace(_templateCode); + + List<string> lines = new List<string>(20_0000) + { + "\n", + $"// DEVELOPMENT={(_development ? 1 : 0)}", + "\n" + }; + + var classInfos = new List<ClassInfo>(); + var classTypeSet = new Dictionary<TypeInfo, ClassInfo>(); + foreach (var type in structTypes) + { + GenerateClassInfo(type, classTypeSet, classInfos); + } + + GenerateStructDefines(classInfos, lines); + + // use structTypes0 to generate signature + GenerateStructureSignatureStub(_structTypes0, lines); + + foreach (var method in _managed2NativeMethodList) + { + GenerateManaged2NativeMethod(method, lines); + } + + GenerateManaged2NativeStub(_managed2NativeMethodList, lines); + + foreach (var method in _native2ManagedMethodList) + { + GenerateNative2ManagedMethod(method, lines); + } + + GenerateNative2ManagedStub(_native2ManagedMethodList, lines); + + foreach (var method in _adjustThunkMethodList) + { + GenerateAdjustThunkMethod(method, lines); + } + + GenerateAdjustThunkStub(_adjustThunkMethodList, lines); + + GenerateReversePInvokeWrappers(_reversePInvokeMethods, lines); + + foreach (var method in _callidMethods) + { + GenerateManaged2NativeFunctionPointerMethod(method, lines); + } + GenerateManaged2NativeFunctionPointerMethodStub(_callidMethods, lines); + + + frr.Replace("CODE", string.Join("\n", lines)); + + Directory.CreateDirectory(Path.GetDirectoryName(_outputFile)); + + frr.Commit(_outputFile); + } + + private static string GetIl2cppCallConventionName(CallingConvention conv) + { + switch (conv) + { + case 0: + case CallingConvention.Winapi: + return "DEFAULT_CALL"; + case CallingConvention.Cdecl: + return "CDECL"; + case CallingConvention.StdCall: + return "STDCALL"; + case CallingConvention.ThisCall: + return "THISCALL"; + case CallingConvention.FastCall: + return "FASTCALL"; + default: + throw new NotSupportedException($"Unsupported CallingConvention {conv}"); + } + } + + private void GenerateReversePInvokeWrappers(List<ABIReversePInvokeMethodInfo> methods, List<string> lines) + { + int methodIndex = 0; + var stubCodes = new List<string>(); + foreach (var methodInfo in methods) + { + MethodDesc method = methodInfo.Method; + string il2cppCallConventionName = GetIl2cppCallConventionName(methodInfo.Callvention); + string paramDeclaringListWithoutMethodInfoStr = string.Join(", ", method.ParamInfos.Select(p => $"{p.Type.GetTypeName()} __arg{p.Index}")); + string paramNameListWithoutMethodInfoStr = string.Join(", ", method.ParamInfos.Select(p => $"__arg{p.Index}").Concat(new string[] { "method" })); + string paramTypeListWithMethodInfoStr = string.Join(", ", method.ParamInfos.Select(p => $"{p.Type.GetTypeName()}").Concat(new string[] { "const MethodInfo*" })); + string methodTypeDef = $"typedef {method.ReturnInfo.Type.GetTypeName()} (*Callback)({paramTypeListWithMethodInfoStr})"; + for (int i = 0; i < methodInfo.Count; i++, methodIndex++) + { + lines.Add($@" +{method.ReturnInfo.Type.GetTypeName()} {il2cppCallConventionName} __ReversePInvokeMethod_{methodIndex}({paramDeclaringListWithoutMethodInfoStr}) +{{ + il2cpp::vm::ScopedThreadAttacher _vmThreadHelper; + const MethodInfo* method = InterpreterModule::GetMethodInfoByReversePInvokeWrapperIndex({methodIndex}); + {methodTypeDef}; + {(method.ReturnInfo.IsVoid ? "" : "return ")}((Callback)(method->methodPointerCallByInterp))({paramNameListWithoutMethodInfoStr}); +}} + "); + stubCodes.Add($"\t{{\"{methodInfo.Signature}\", (Il2CppMethodPointer)__ReversePInvokeMethod_{methodIndex}}},"); + } + Debug.Log($"[ReversePInvokeWrap.Generator] method:{method.MethodDef} wrapperCount:{methodInfo.Count}"); + } + + lines.Add(@" +const ReversePInvokeMethodData hybridclr::interpreter::g_reversePInvokeMethodStub[] +{ +"); + lines.AddRange(stubCodes); + + lines.Add(@" + {nullptr, nullptr}, +}; +"); + } + + public void Generate() + { + PrepareMethodBridges(); + CollectTypesAndMethods(); + OptimizationTypesAndMethods(); + GenerateCode(); + } + + private void CollectStructDefs(List<MethodDesc> methods, HashSet<TypeInfo> structTypes) + { + foreach (var method in methods) + { + foreach(var paramInfo in method.ParamInfos) + { + if (paramInfo.Type.IsStruct) + { + structTypes.Add(paramInfo.Type); + if (paramInfo.Type.Klass.ContainsGenericParameter) + { + throw new Exception($"[CollectStructDefs] method:{method.MethodDef} type:{paramInfo.Type.Klass} contains generic parameter"); + } + } + + } + if (method.ReturnInfo.Type.IsStruct) + { + structTypes.Add(method.ReturnInfo.Type); + if (method.ReturnInfo.Type.Klass.ContainsGenericParameter) + { + throw new Exception($"[CollectStructDefs] method:{method.MethodDef} type:{method.ReturnInfo.Type.Klass} contains generic parameter"); + } + } + } + + } + + class FieldInfo + { + public FieldDef field; + public TypeInfo type; + } + + class ClassInfo + { + public TypeInfo type; + public List<AnalyzeFieldInfo> fields; + public uint packingSize; + public uint classSize; + public LayoutKind layout; + public bool blittable; + } + + private void GenerateClassInfo(TypeInfo type, Dictionary<TypeInfo, ClassInfo> typeSet, List<ClassInfo> classInfos) + { + if (typeSet.ContainsKey(type)) + { + return; + } + + AnalyzeTypeInfo ati = CalculateAnalyzeTypeInfoBasic(type); + //TypeSig typeSig = type.Klass; + //var fields = new List<FieldInfo>(); + + //TypeDef typeDef = typeSig.ToTypeDefOrRef().ResolveTypeDefThrow(); + + //List<TypeSig> klassInst = typeSig.ToGenericInstSig()?.GenericArguments?.ToList(); + //GenericArgumentContext ctx = klassInst != null ? new GenericArgumentContext(klassInst, null) : null; + + //ClassLayout sa = typeDef.ClassLayout; + + //ICorLibTypes corLibTypes = typeDef.Module.CorLibTypes; + //bool blittable = true; + //foreach (FieldDef field in typeDef.Fields) + //{ + // if (field.IsStatic) + // { + // continue; + // } + // TypeSig fieldType = ctx != null ? MetaUtil.Inflate(field.FieldType, ctx) : field.FieldType; + // fieldType = MetaUtil.ToShareTypeSig(corLibTypes, fieldType); + // var fieldTypeInfo = ToIsomorphicType(GetSharedTypeInfo(fieldType)); + // if (fieldTypeInfo.IsStruct) + // { + // GenerateClassInfo(fieldTypeInfo, typeSet, classInfos); + // } + // blittable &= IsBlittable(fieldType, fieldTypeInfo, typeSet); + // fields.Add(new FieldInfo { field = field, type = fieldTypeInfo }); + //} + + foreach (var field in ati.fields) + { + if (field.type.IsStruct) + { + GenerateClassInfo(field.type, typeSet, classInfos); + } + } + var classInfo = new ClassInfo() + { + type = type, + fields = ati.fields, + packingSize = ati.packingSize, + classSize = ati.classSize, + layout = ati.layout, + blittable = ati.blittable, + }; + typeSet.Add(type, classInfo); + classInfos.Add(classInfo); + } + + private void GenerateStructDefines(List<ClassInfo> classInfos, List<string> lines) + { + foreach (var ci in classInfos) + { + lines.Add($"// {ci.type.Klass}"); + uint packingSize = ci.packingSize; + uint classSize = ci.classSize; + + if (ci.layout == LayoutKind.Explicit) + { + lines.Add($"struct {ci.type.GetTypeName()} {{"); + lines.Add("\tunion {"); + if (classSize > 0) + { + lines.Add($"\tstruct {{ char __fieldSize_offsetPadding[{classSize}];}};"); + } + int index = 0; + foreach (var field in ci.fields) + { + uint offset = field.field.FieldOffset.Value; + string fieldName = $"__{index}"; + string commentFieldName = $"{field.field.Name}"; + lines.Add("\t#pragma pack(push, 1)"); + lines.Add($"\tstruct {{ {(offset > 0 ? $"char {fieldName}_offsetPadding[{offset}]; " : "")}{field.type.GetTypeName()} {fieldName};}}; // {commentFieldName}"); + lines.Add($"\t#pragma pack(pop)"); + if (packingSize > 0) + { + lines.Add($"\t#pragma pack(push, {packingSize})"); + } + lines.Add($"\tstruct {{ {(offset > 0 ? $"char {fieldName}_offsetPadding_forAlignmentOnly[{offset}]; " : "")}{field.type.GetTypeName()} {fieldName}_forAlignmentOnly;}}; // {commentFieldName}"); + if (packingSize > 0) + { + lines.Add($"\t#pragma pack(pop)"); + } + ++index; + } + lines.Add("\t};"); + lines.Add("};"); + } + else + { + if (packingSize != 0) + { + lines.Add($"#pragma pack(push, {packingSize})"); + } + lines.Add($"{(classSize > 0 ? "union" : "struct")} {ci.type.GetTypeName()} {{"); + if (classSize > 0) + { + lines.Add($"\tstruct {{ char __fieldSize_offsetPadding[{classSize}];}};"); + lines.Add("\tstruct {"); + } + int index = 0; + foreach (var field in ci.fields) + { + string fieldName = $"__{index}"; + string commentFieldName = $"{field.field.Name}"; + lines.Add($"\t{field.type.GetTypeName()} {fieldName}; // {commentFieldName}"); + ++index; + } + if (classSize > 0) + { + lines.Add("\t};"); + } + lines.Add("};"); + if (packingSize != 0) + { + lines.Add($"#pragma pack(pop)"); + } + } + } + } + + private const string SigOfObj = "u"; + + private static string ToFullName(TypeSig type) + { + type = type.RemovePinnedAndModifiers(); + switch (type.ElementType) + { + case ElementType.Void: return "v"; + case ElementType.Boolean: return "u1"; + case ElementType.I1: return "i1"; + case ElementType.U1: return "u1"; + case ElementType.I2: return "i2"; + case ElementType.Char: + case ElementType.U2: return "u2"; + case ElementType.I4: return "i4"; + case ElementType.U4: return "u4"; + case ElementType.I8: return "i8"; + case ElementType.U8: return "u8"; + case ElementType.R4: return "r4"; + case ElementType.R8: return "r8"; + case ElementType.I: return "i"; + case ElementType.U: + case ElementType.String: + case ElementType.Ptr: + case ElementType.ByRef: + case ElementType.Class: + case ElementType.Array: + case ElementType.SZArray: + case ElementType.FnPtr: + case ElementType.Object: + return SigOfObj; + case ElementType.Module: + case ElementType.Var: + case ElementType.MVar: + throw new NotSupportedException($"ToFullName type:{type}"); + case ElementType.TypedByRef: return TypeInfo.strTypedByRef; + case ElementType.ValueType: + { + TypeDef typeDef = type.ToTypeDefOrRef().ResolveTypeDef(); + if (typeDef == null) + { + throw new Exception($"type:{type} definition could not be found. Please try `HybridCLR/Genergate/LinkXml`, then Build once to generate the AOT dll, and then regenerate the bridge function"); + } + if (typeDef.IsEnum) + { + return ToFullName(typeDef.GetEnumUnderlyingType()); + } + return ToValueTypeFullName((ClassOrValueTypeSig)type); + } + case ElementType.GenericInst: + { + GenericInstSig gis = (GenericInstSig)type; + if (!gis.GenericType.IsValueType) + { + return SigOfObj; + } + TypeDef typeDef = gis.GenericType.ToTypeDefOrRef().ResolveTypeDef(); + if (typeDef.IsEnum) + { + return ToFullName(typeDef.GetEnumUnderlyingType()); + } + return $"{ToValueTypeFullName(gis.GenericType)}<{string.Join(",", gis.GenericArguments.Select(a => ToFullName(a)))}>"; + } + default: throw new NotSupportedException($"{type.ElementType}"); + } + } + + private static bool IsSystemOrUnityAssembly(ModuleDef module) + { + if (module.IsCoreLibraryModule == true) + { + return true; + } + string assName = module.Assembly.Name.String; + return assName.StartsWith("System.") || assName.StartsWith("UnityEngine."); + } + + private static string ToValueTypeFullName(ClassOrValueTypeSig type) + { + TypeDef typeDef = type.ToTypeDefOrRef().ResolveTypeDef(); + if (typeDef == null) + { + throw new Exception($"type:{type} resolve fail"); + } + + if (typeDef.DeclaringType != null) + { + return $"{ToValueTypeFullName((ClassOrValueTypeSig)typeDef.DeclaringType.ToTypeSig())}/{typeDef.Name}"; + } + + if (IsSystemOrUnityAssembly(typeDef.Module)) + { + return type.FullName; + } + return $"{Path.GetFileNameWithoutExtension(typeDef.Module.Name)}:{typeDef.FullName}"; + } + + private void GenerateStructureSignatureStub(List<TypeInfo> types, List<string> lines) + { + lines.Add("const FullName2Signature hybridclr::interpreter::g_fullName2SignatureStub[] = {"); + foreach (var type in types) + { + TypeInfo isoType = ToIsomorphicType(type); + lines.Add($"\t{{\"{ToFullName(type.Klass)}\", \"{isoType.CreateSigName()}\"}},"); + } + lines.Add("\t{ nullptr, nullptr},"); + lines.Add("};"); + } + + private void GenerateManaged2NativeStub(List<MethodDesc> methods, List<string> lines) + { + lines.Add($@" +const Managed2NativeMethodInfo hybridclr::interpreter::g_managed2nativeStub[] = +{{ +"); + + foreach (var method in methods) + { + lines.Add($"\t{{\"{method.CreateInvokeSigName()}\", __M2N_{method.CreateInvokeSigName()}}},"); + } + + lines.Add($"\t{{nullptr, nullptr}},"); + lines.Add("};"); + } + + private void GenerateNative2ManagedStub(List<MethodDesc> methods, List<string> lines) + { + lines.Add($@" +const Native2ManagedMethodInfo hybridclr::interpreter::g_native2managedStub[] = +{{ +"); + + foreach (var method in methods) + { + lines.Add($"\t{{\"{method.CreateInvokeSigName()}\", (Il2CppMethodPointer)__N2M_{method.CreateInvokeSigName()}}},"); + } + + lines.Add($"\t{{nullptr, nullptr}},"); + lines.Add("};"); + } + + private void GenerateAdjustThunkStub(List<MethodDesc> methods, List<string> lines) + { + lines.Add($@" +const NativeAdjustThunkMethodInfo hybridclr::interpreter::g_adjustThunkStub[] = +{{ +"); + + foreach (var method in methods) + { + lines.Add($"\t{{\"{method.CreateInvokeSigName()}\", (Il2CppMethodPointer)__N2M_AdjustorThunk_{method.CreateCallSigName()}}},"); + } + + lines.Add($"\t{{nullptr, nullptr}},"); + lines.Add("};"); + } + + private string GetManaged2NativePassParam(TypeInfo type, string varName) + { + return $"M2NFromValueOrAddress<{type.GetTypeName()}>({varName})"; + } + + private string GetNative2ManagedPassParam(TypeInfo type, string varName) + { + return type.NeedExpandValue() ? $"(uint64_t)({varName})" : $"N2MAsUint64ValueOrAddress<{type.GetTypeName()}>({varName})"; + } + + private void GenerateManaged2NativeMethod(MethodDesc method, List<string> lines) + { + string paramListStr = string.Join(", ", method.ParamInfos.Select(p => $"{p.Type.GetTypeName()} __arg{p.Index}").Concat(new string[] { "const MethodInfo* method" })); + string paramNameListStr = string.Join(", ", method.ParamInfos.Select(p => GetManaged2NativePassParam(p.Type, $"localVarBase+argVarIndexs[{p.Index}]")).Concat(new string[] { "method" })); + + lines.Add($@" +static void __M2N_{method.CreateCallSigName()}(const MethodInfo* method, uint16_t* argVarIndexs, StackObject* localVarBase, void* ret) +{{ + typedef {method.ReturnInfo.Type.GetTypeName()} (*NativeMethod)({paramListStr}); + {(!method.ReturnInfo.IsVoid ? $"*({method.ReturnInfo.Type.GetTypeName()}*)ret = " : "")}((NativeMethod)(method->methodPointerCallByInterp))({paramNameListStr}); +}} +"); + } + + private string GenerateArgumentSizeAndOffset(List<ParamInfo> paramInfos) + { + StringBuilder s = new StringBuilder(); + int index = 0; + foreach (var param in paramInfos) + { + s.AppendLine($"\tconstexpr int __ARG_OFFSET_{index}__ = {(index > 0 ? $"__ARG_OFFSET_{index - 1}__ + __ARG_SIZE_{index-1}__" : "0")};"); + s.AppendLine($"\tconstexpr int __ARG_SIZE_{index}__ = (sizeof(__arg{index}) + 7)/8;"); + index++; + } + s.AppendLine($"\tconstexpr int __TOTAL_ARG_SIZE__ = {(paramInfos.Count > 0 ? $"__ARG_OFFSET_{index-1}__ + __ARG_SIZE_{index-1}__" : "1")};"); + return s.ToString(); + } + + private string GenerateCopyArgumentToInterpreterStack(List<ParamInfo> paramInfos) + { + StringBuilder s = new StringBuilder(); + int index = 0; + foreach (var param in paramInfos) + { + if (param.Type.IsPrimitiveType) + { + if (param.Type.NeedExpandValue()) + { + s.AppendLine($"\targs[__ARG_OFFSET_{index}__].u64 = __arg{index};"); + } + else + { + s.AppendLine($"\t*({param.Type.GetTypeName()}*)(args + __ARG_OFFSET_{index}__) = __arg{index};"); + } + } + else + { + s.AppendLine($"\t*({param.Type.GetTypeName()}*)(args + __ARG_OFFSET_{index}__) = __arg{index};"); + } + index++; + } + return s.ToString(); + } + + private void GenerateNative2ManagedMethod0(MethodDesc method, bool adjustorThunk, List<string> lines) + { + string paramListStr = string.Join(", ", method.ParamInfos.Select(p => $"{p.Type.GetTypeName()} __arg{p.Index}").Concat(new string[] { "const MethodInfo* method" })); + lines.Add($@" +static {method.ReturnInfo.Type.GetTypeName()} __N2M_{(adjustorThunk ? "AdjustorThunk_" : "")}{method.CreateCallSigName()}({paramListStr}) +{{ + {(adjustorThunk ? "__arg0 += sizeof(Il2CppObject);" : "")} +{GenerateArgumentSizeAndOffset(method.ParamInfos)} + StackObject args[__TOTAL_ARG_SIZE__]; +{GenerateCopyArgumentToInterpreterStack(method.ParamInfos)} + {(method.ReturnInfo.IsVoid ? "Interpreter::Execute(method, args, nullptr);" : $"{method.ReturnInfo.Type.GetTypeName()} ret; Interpreter::Execute(method, args, &ret); return ret;")} +}} +"); + } + + private void GenerateNative2ManagedMethod(MethodDesc method, List<string> lines) + { + GenerateNative2ManagedMethod0(method, false, lines); + } + + private void GenerateAdjustThunkMethod(MethodDesc method, List<string> lines) + { + GenerateNative2ManagedMethod0(method, true, lines); + } + + private void GenerateManaged2NativeFunctionPointerMethod(CalliMethodInfo methodInfo, List<string> lines) + { + MethodDesc method = methodInfo.Method; + string paramListStr = string.Join(", ", method.ParamInfos.Select(p => $"{p.Type.GetTypeName()} __arg{p.Index}")); + string paramNameListStr = string.Join(", ", method.ParamInfos.Select(p => GetManaged2NativePassParam(p.Type, $"localVarBase+argVarIndexs[{p.Index}]"))); + string il2cppCallConventionName = GetIl2cppCallConventionName(methodInfo.Callvention); + lines.Add($@" +static void __M2NF_{methodInfo.Signature}(const void* methodPointer, uint16_t* argVarIndexs, StackObject* localVarBase, void* ret) +{{ + typedef {method.ReturnInfo.Type.GetTypeName()} ({il2cppCallConventionName} *NativeMethod)({paramListStr}); + {(!method.ReturnInfo.IsVoid ? $"*({method.ReturnInfo.Type.GetTypeName()}*)ret = " : "")}((NativeMethod)(methodPointer))({paramNameListStr}); +}} +"); + } + + private void GenerateManaged2NativeFunctionPointerMethodStub(List<CalliMethodInfo> calliMethodSignatures, List<string> lines) + { + lines.Add(@" +const Managed2NativeFunctionPointerCallData hybridclr::interpreter::g_managed2NativeFunctionPointerCallStub[] +{ +"); + foreach (var method in calliMethodSignatures) + { + lines.Add($"\t{{\"{method.Signature}\", __M2NF_{method.Signature}}},"); + } + + lines.Add(@" + {nullptr, nullptr}, +}; +"); + } + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/MethodBridge/Generator.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/MethodBridge/Generator.cs.meta new file mode 100644 index 0000000..914508e --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/MethodBridge/Generator.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e42a0f3bcbc5ddf438a85ae16c1b3116 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ReversePInvokeWrap.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ReversePInvokeWrap.meta new file mode 100644 index 0000000..234a1bc --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ReversePInvokeWrap.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 259c1cb7fe681f74eb435ab8f268890d +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ReversePInvokeWrap/Analyzer.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ReversePInvokeWrap/Analyzer.cs new file mode 100644 index 0000000..0004d18 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ReversePInvokeWrap/Analyzer.cs @@ -0,0 +1,74 @@ +锘縰sing dnlib.DotNet; +using HybridCLR.Editor.ABI; +using HybridCLR.Editor.Meta; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using CallingConvention = System.Runtime.InteropServices.CallingConvention; +using UnityEngine; + +namespace HybridCLR.Editor.ReversePInvokeWrap +{ + public class RawReversePInvokeMethodInfo + { + public MethodDef Method { get; set; } + + public CustomAttribute GenerationAttribute { get; set; } + } + + public class Analyzer + { + + private readonly List<ModuleDefMD> _rootModules = new List<ModuleDefMD>(); + + private readonly List<RawReversePInvokeMethodInfo> _reversePInvokeMethods = new List<RawReversePInvokeMethodInfo>(); + + public List<RawReversePInvokeMethodInfo> ReversePInvokeMethods => _reversePInvokeMethods; + + public Analyzer(AssemblyCache cache, List<string> assemblyNames) + { + foreach (var assemblyName in assemblyNames) + { + _rootModules.Add(cache.LoadModule(assemblyName)); + } + } + + private void CollectReversePInvokeMethods() + { + foreach (var mod in _rootModules) + { + Debug.Log($"ass:{mod.FullName} methodcount:{mod.Metadata.TablesStream.MethodTable.Rows}"); + for (uint rid = 1, n = mod.Metadata.TablesStream.MethodTable.Rows; rid <= n; rid++) + { + var method = mod.ResolveMethod(rid); + //Debug.Log($"method:{method}"); + if (!method.IsStatic || !method.HasCustomAttributes) + { + continue; + } + CustomAttribute wa = method.CustomAttributes.FirstOrDefault(ca => ca.AttributeType.Name == "MonoPInvokeCallbackAttribute"); + if (wa == null) + { + continue; + } + //foreach (var ca in method.CustomAttributes) + //{ + // Debug.Log($"{ca.AttributeType.FullName} {ca.TypeFullName}"); + //} + _reversePInvokeMethods.Add(new RawReversePInvokeMethodInfo() + { + Method = method, + GenerationAttribute = method.CustomAttributes.FirstOrDefault(ca => ca.AttributeType.FullName == "HybridCLR.ReversePInvokeWrapperGenerationAttribute"), + }); + } + } + } + + public void Run() + { + CollectReversePInvokeMethods(); + } + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ReversePInvokeWrap/Analyzer.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ReversePInvokeWrap/Analyzer.cs.meta new file mode 100644 index 0000000..792b5b5 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/ReversePInvokeWrap/Analyzer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c172068b408c0e349b2ceee4c4635085 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Settings.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Settings.meta new file mode 100644 index 0000000..f73ef75 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Settings.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3708ee1d4035cb14abaa4d64a8ec8148 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Settings/EditorStatusWatcher.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Settings/EditorStatusWatcher.cs new file mode 100644 index 0000000..986f026 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Settings/EditorStatusWatcher.cs @@ -0,0 +1,29 @@ +锘縰sing HybridCLR.Editor; +using System; +using UnityEditor; +using UnityEditorInternal; + +namespace HybridCLR.Editor.Settings +{ + + [InitializeOnLoad] + public static class EditorStatusWatcher + { + public static Action OnEditorFocused; + static bool isFocused; + static EditorStatusWatcher() => EditorApplication.update += Update; + static void Update() + { + if (isFocused != InternalEditorUtility.isApplicationActive) + { + isFocused = InternalEditorUtility.isApplicationActive; + if (isFocused) + { + HybridCLRSettings.LoadOrCreate(); + OnEditorFocused?.Invoke(); + } + } + } + } + +} \ No newline at end of file diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Settings/EditorStatusWatcher.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Settings/EditorStatusWatcher.cs.meta new file mode 100644 index 0000000..317bfd7 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Settings/EditorStatusWatcher.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 093a9e6c1e7399244bbcd8983fdbfdee +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Settings/HybridCLRSettingProvider.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Settings/HybridCLRSettingProvider.cs new file mode 100644 index 0000000..7695484 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Settings/HybridCLRSettingProvider.cs @@ -0,0 +1,178 @@ +using System; +using System.Reflection; +using UnityEditor; +using UnityEditor.Presets; +using UnityEngine; +using UnityEngine.UIElements; + +namespace HybridCLR.Editor.Settings +{ + public class HybridCLRSettingsProvider : SettingsProvider + { + private SerializedObject _serializedObject; + private SerializedProperty _enable; + private SerializedProperty _useGlobalIl2cpp; + private SerializedProperty _hybridclrRepoURL; + private SerializedProperty _il2cppPlusRepoURL; + private SerializedProperty _hotUpdateAssemblyDefinitions; + private SerializedProperty _hotUpdateAssemblies; + private SerializedProperty _preserveHotUpdateAssemblies; + private SerializedProperty _hotUpdateDllCompileOutputRootDir; + private SerializedProperty _externalHotUpdateAssembliyDirs; + private SerializedProperty _strippedAOTDllOutputRootDir; + private SerializedProperty _patchAOTAssemblies; + private SerializedProperty _outputLinkFile; + private SerializedProperty _outputAOTGenericReferenceFile; + private SerializedProperty _maxGenericReferenceIteration; + private SerializedProperty _maxMethodBridgeGenericIteration; + + private GUIStyle buttonStyle; + public HybridCLRSettingsProvider() : base("Project/HybridCLR Settings", SettingsScope.Project) { } + public override void OnActivate(string searchContext, VisualElement rootElement) + { + EditorStatusWatcher.OnEditorFocused += OnEditorFocused; + InitGUI(); + } + private void InitGUI() + { + var setting = HybridCLRSettings.LoadOrCreate(); + _serializedObject?.Dispose(); + _serializedObject = new SerializedObject(setting); + _enable = _serializedObject.FindProperty("enable"); + _useGlobalIl2cpp = _serializedObject.FindProperty("useGlobalIl2cpp"); + _hybridclrRepoURL = _serializedObject.FindProperty("hybridclrRepoURL"); + _il2cppPlusRepoURL = _serializedObject.FindProperty("il2cppPlusRepoURL"); + _hotUpdateAssemblyDefinitions = _serializedObject.FindProperty("hotUpdateAssemblyDefinitions"); + _hotUpdateAssemblies = _serializedObject.FindProperty("hotUpdateAssemblies"); + _preserveHotUpdateAssemblies = _serializedObject.FindProperty("preserveHotUpdateAssemblies"); + _hotUpdateDllCompileOutputRootDir = _serializedObject.FindProperty("hotUpdateDllCompileOutputRootDir"); + _externalHotUpdateAssembliyDirs = _serializedObject.FindProperty("externalHotUpdateAssembliyDirs"); + _strippedAOTDllOutputRootDir = _serializedObject.FindProperty("strippedAOTDllOutputRootDir"); + _patchAOTAssemblies = _serializedObject.FindProperty("patchAOTAssemblies"); + _outputLinkFile = _serializedObject.FindProperty("outputLinkFile"); + _outputAOTGenericReferenceFile = _serializedObject.FindProperty("outputAOTGenericReferenceFile"); + _maxGenericReferenceIteration = _serializedObject.FindProperty("maxGenericReferenceIteration"); + _maxMethodBridgeGenericIteration = _serializedObject.FindProperty("maxMethodBridgeGenericIteration"); + } + private void OnEditorFocused() + { + InitGUI(); + Repaint(); + } + public override void OnTitleBarGUI() + { + base.OnTitleBarGUI(); + var rect = GUILayoutUtility.GetLastRect(); + buttonStyle = buttonStyle ?? GUI.skin.GetStyle("IconButton"); + + #region 缁樺埗瀹樻柟缃戠珯璺宠浆鎸夐挳 + var w = rect.x + rect.width; + rect.x = w - 57; + rect.y += 6; + rect.width = rect.height = 18; + var content = EditorGUIUtility.IconContent("_Help"); + content.tooltip = "鐐瑰嚮璁块棶 HybridCLR 瀹樻柟鏂囨。"; + if (GUI.Button(rect, content, buttonStyle)) + { + Application.OpenURL("https://hybridclr.doc.code-philosophy.com/"); + } + #endregion + #region 缁樺埗 Preset + rect.x += 19; + content = EditorGUIUtility.IconContent("Preset.Context"); + content.tooltip = "鐐瑰嚮瀛樺偍鎴栧姞杞� Preset ."; + if (GUI.Button(rect, content, buttonStyle)) + { + var target = HybridCLRSettings.Instance; + var receiver = ScriptableObject.CreateInstance<SettingsPresetReceiver>(); + receiver.Init(target, this); + PresetSelector.ShowSelector(target, null, true, receiver); + } + #endregion + #region 缁樺埗 Reset + rect.x += 19; + content = EditorGUIUtility.IconContent( +#if UNITY_2021_3_OR_NEWER + "pane options" +#else + "_Popup" +#endif + ); + content.tooltip = "Reset"; + if (GUI.Button(rect, content, buttonStyle)) + { + GenericMenu menu = new GenericMenu(); + menu.AddItem(new GUIContent("Reset"), false, () => + { + Undo.RecordObject(HybridCLRSettings.Instance, "Capture Value for Reset"); + var dv = ScriptableObject.CreateInstance<HybridCLRSettings>(); + var json = EditorJsonUtility.ToJson(dv); + UnityEngine.Object.DestroyImmediate(dv); + EditorJsonUtility.FromJsonOverwrite(json, HybridCLRSettings.Instance); + HybridCLRSettings.Save(); + }); + menu.ShowAsContext(); + } + #endregion + } + public override void OnGUI(string searchContext) + { + using (CreateSettingsWindowGUIScope()) + { + if (_serializedObject == null||!_serializedObject.targetObject) + { + InitGUI(); + } + _serializedObject.Update(); + EditorGUI.BeginChangeCheck(); + EditorGUILayout.PropertyField(_enable); + EditorGUILayout.PropertyField(_hybridclrRepoURL); + EditorGUILayout.PropertyField(_il2cppPlusRepoURL); + EditorGUILayout.PropertyField(_useGlobalIl2cpp); + EditorGUILayout.PropertyField(_hotUpdateAssemblyDefinitions); + EditorGUILayout.PropertyField(_hotUpdateAssemblies); + EditorGUILayout.PropertyField(_preserveHotUpdateAssemblies); + EditorGUILayout.PropertyField(_hotUpdateDllCompileOutputRootDir); + EditorGUILayout.PropertyField(_externalHotUpdateAssembliyDirs); + EditorGUILayout.PropertyField(_strippedAOTDllOutputRootDir); + EditorGUILayout.PropertyField(_patchAOTAssemblies); + EditorGUILayout.PropertyField(_outputLinkFile); + EditorGUILayout.PropertyField(_outputAOTGenericReferenceFile); + EditorGUILayout.PropertyField(_maxGenericReferenceIteration); + EditorGUILayout.PropertyField(_maxMethodBridgeGenericIteration); + if (EditorGUI.EndChangeCheck()) + { + _serializedObject.ApplyModifiedProperties(); + HybridCLRSettings.Save(); + } + } + } + private IDisposable CreateSettingsWindowGUIScope() + { + var unityEditorAssembly = Assembly.GetAssembly(typeof(EditorWindow)); + var type = unityEditorAssembly.GetType("UnityEditor.SettingsWindow+GUIScope"); + return Activator.CreateInstance(type) as IDisposable; + } + public override void OnDeactivate() + { + base.OnDeactivate(); + EditorStatusWatcher.OnEditorFocused -= OnEditorFocused; + HybridCLRSettings.Save(); + } + + static HybridCLRSettingsProvider provider; + [SettingsProvider] + public static SettingsProvider CreateMyCustomSettingsProvider() + { + if (HybridCLRSettings.Instance && provider == null) + { + provider = new HybridCLRSettingsProvider(); + using (var so = new SerializedObject(HybridCLRSettings.Instance)) + { + provider.keywords = GetSearchKeywordsFromSerializedObject(so); + } + } + return provider; + } + } +} \ No newline at end of file diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Settings/HybridCLRSettingProvider.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Settings/HybridCLRSettingProvider.cs.meta new file mode 100644 index 0000000..0a21f37 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Settings/HybridCLRSettingProvider.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d2bd1694fedc8b54c88bb9f6c67907d3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Settings/HybridCLRSettings.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Settings/HybridCLRSettings.cs new file mode 100644 index 0000000..b6ce977 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Settings/HybridCLRSettings.cs @@ -0,0 +1,54 @@ +using UnityEditorInternal; +using UnityEngine; + +namespace HybridCLR.Editor.Settings +{ + [FilePath("ProjectSettings/HybridCLRSettings.asset")] + public class HybridCLRSettings : ScriptableSingleton<HybridCLRSettings> + { + [Tooltip("enable HybridCLR")] + public bool enable = true; + + [Tooltip("use il2cpp in unity editor installation location")] + public bool useGlobalIl2cpp; + + [Tooltip("hybridclr repo URL")] + public string hybridclrRepoURL = "https://gitee.com/focus-creative-games/hybridclr"; + + [Tooltip("il2cpp_plus repo URL")] + public string il2cppPlusRepoURL = "https://gitee.com/focus-creative-games/il2cpp_plus"; + + [Tooltip("hot update assembly definitions(asd)")] + public AssemblyDefinitionAsset[] hotUpdateAssemblyDefinitions; + + [Tooltip("hot update assembly names(without .dll suffix)")] + public string[] hotUpdateAssemblies; + + [Tooltip("preserved hot update assembly names(without .dll suffix)")] + public string[] preserveHotUpdateAssemblies; + + [Tooltip("output directory of compiling hot update assemblies")] + public string hotUpdateDllCompileOutputRootDir = "HybridCLRData/HotUpdateDlls"; + + [Tooltip("searching paths of external hot update assemblies")] + public string[] externalHotUpdateAssembliyDirs; + + [Tooltip("output directory of stripped AOT assemblies")] + public string strippedAOTDllOutputRootDir = "HybridCLRData/AssembliesPostIl2CppStrip"; + + [Tooltip("supplementary metadata assembly names(without .dll suffix)")] + public string[] patchAOTAssemblies; + + [Tooltip("output file of automatic generated link.xml by scanning hot update assemblies")] + public string outputLinkFile = "HybridCLRGenerate/link.xml"; + + [Tooltip("output file of automatic generated AOTGenericReferences.cs")] + public string outputAOTGenericReferenceFile = "HybridCLRGenerate/AOTGenericReferences.cs"; + + [Tooltip("max iteration count of searching generic methods in hot update assemblies")] + public int maxGenericReferenceIteration = 10; + + [Tooltip("max iteration count of searching method bridge generic methods in AOT assemblies")] + public int maxMethodBridgeGenericIteration = 10; + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Settings/HybridCLRSettings.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Settings/HybridCLRSettings.cs.meta new file mode 100644 index 0000000..570bc8f --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Settings/HybridCLRSettings.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e189374413a3f00468e49d51d8b27a09 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Settings/MenuProvider.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Settings/MenuProvider.cs new file mode 100644 index 0000000..c21c46d --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Settings/MenuProvider.cs @@ -0,0 +1,39 @@ +using HybridCLR.Editor.Installer; +using UnityEditor; +using UnityEngine; + +namespace HybridCLR.Editor.Settings +{ + public static class MenuProvider + { + + [MenuItem("HybridCLR/About", priority = 0)] + public static void OpenAbout() => Application.OpenURL("https://hybridclr.doc.code-philosophy.com/docs/intro"); + + [MenuItem("HybridCLR/Installer...", priority = 60)] + private static void Open() + { + InstallerWindow window = EditorWindow.GetWindow<InstallerWindow>("HybridCLR Installer", true); + window.minSize = new Vector2(800f, 500f); + } + + [MenuItem("HybridCLR/Settings...", priority = 61)] + public static void OpenSettings() => SettingsService.OpenProjectSettings("Project/HybridCLR Settings"); + + [MenuItem("HybridCLR/Documents/Quick Start")] + public static void OpenQuickStart() => Application.OpenURL("https://hybridclr.doc.code-philosophy.com/docs/beginner/quickstart"); + + [MenuItem("HybridCLR/Documents/Performance")] + public static void OpenPerformance() => Application.OpenURL("https://hybridclr.doc.code-philosophy.com/docs/basic/performance"); + + [MenuItem("HybridCLR/Documents/FAQ")] + public static void OpenFAQ() => Application.OpenURL("https://hybridclr.doc.code-philosophy.com/docs/help/faq"); + + [MenuItem("HybridCLR/Documents/Common Errors")] + public static void OpenCommonErrors() => Application.OpenURL("https://hybridclr.doc.code-philosophy.com/docs/help/commonerrors"); + + [MenuItem("HybridCLR/Documents/Bug Report")] + public static void OpenBugReport() => Application.OpenURL("https://hybridclr.doc.code-philosophy.com/docs/help/issue"); + } + +} \ No newline at end of file diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Settings/MenuProvider.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Settings/MenuProvider.cs.meta new file mode 100644 index 0000000..a4474b2 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Settings/MenuProvider.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a475a5f281298b84da32373694704c68 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Settings/ScriptableSignleton.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Settings/ScriptableSignleton.cs new file mode 100644 index 0000000..903f802 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Settings/ScriptableSignleton.cs @@ -0,0 +1,89 @@ +using System; +using System.IO; +using System.Linq; +using UnityEditor; +using UnityEditorInternal; +using UnityEngine; + +namespace HybridCLR.Editor.Settings +{ + public class ScriptableSingleton<T> : ScriptableObject where T : ScriptableObject + { + private static T s_Instance; + public static T Instance + { + get + { + if (!s_Instance) + { + LoadOrCreate(); + } + return s_Instance; + } + } + public static T LoadOrCreate() + { + string filePath = GetFilePath(); + if (!string.IsNullOrEmpty(filePath)) + { + var arr = InternalEditorUtility.LoadSerializedFileAndForget(filePath); + s_Instance = arr.Length > 0 ? arr[0] as T : s_Instance??CreateInstance<T>(); + } + else + { + Debug.LogError($"save location of {nameof(ScriptableSingleton<T>)} is invalid"); + } + return s_Instance; + } + + public static void Save(bool saveAsText = true) + { + if (!s_Instance) + { + Debug.LogError("Cannot save ScriptableSingleton: no instance!"); + return; + } + + string filePath = GetFilePath(); + if (!string.IsNullOrEmpty(filePath)) + { + string directoryName = Path.GetDirectoryName(filePath); + if (!Directory.Exists(directoryName)) + { + Directory.CreateDirectory(directoryName); + } + UnityEngine.Object[] obj = new T[1] { s_Instance }; + InternalEditorUtility.SaveToSerializedFileAndForget(obj, filePath, saveAsText); + } + } + protected static string GetFilePath() + { + return typeof(T).GetCustomAttributes(inherit: true) + .Where(v => v is FilePathAttribute) + .Cast<FilePathAttribute>() + .FirstOrDefault() + ?.filepath; + } + } + [AttributeUsage(AttributeTargets.Class)] + public class FilePathAttribute : Attribute + { + internal string filepath; + /// <summary> + /// 鍗曚緥瀛樻斁璺緞 + /// </summary> + /// <param name="path">鐩稿 Project 璺緞</param> + public FilePathAttribute(string path) + { + if (string.IsNullOrEmpty(path)) + { + throw new ArgumentException("Invalid relative path (it is empty)"); + } + if (path[0] == '/') + { + path = path.Substring(1); + } + filepath = path; + } + } +} \ No newline at end of file diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Settings/ScriptableSignleton.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Settings/ScriptableSignleton.cs.meta new file mode 100644 index 0000000..fa1923b --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Settings/ScriptableSignleton.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 851c44a8da67a9742a7ea68815383f27 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Settings/SettingsPresetReceiver.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Settings/SettingsPresetReceiver.cs new file mode 100644 index 0000000..e60f3aa --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Settings/SettingsPresetReceiver.cs @@ -0,0 +1,39 @@ +using UnityEditor; +using UnityEditor.Presets; +using UnityEngine; + +namespace HybridCLR.Editor.Settings +{ + public class SettingsPresetReceiver : PresetSelectorReceiver + { + private Object m_Target; + private Preset m_InitialValue; + private SettingsProvider m_Provider; + + internal void Init(Object target, SettingsProvider provider) + { + m_Target = target; + m_InitialValue = new Preset(target); + m_Provider = provider; + } + public override void OnSelectionChanged(Preset selection) + { + if (selection != null) + { + Undo.RecordObject(m_Target, "Apply Preset " + selection.name); + selection.ApplyTo(m_Target); + } + else + { + Undo.RecordObject(m_Target, "Cancel Preset"); + m_InitialValue.ApplyTo(m_Target); + } + m_Provider.Repaint(); + } + public override void OnSelectionClosed(Preset selection) + { + OnSelectionChanged(selection); + Object.DestroyImmediate(this); + } + } +} \ No newline at end of file diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Settings/SettingsPresetReceiver.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Settings/SettingsPresetReceiver.cs.meta new file mode 100644 index 0000000..5047283 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Settings/SettingsPresetReceiver.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d8373e0cb30c4894db7cd4d0b77a7a48 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/SettingsUtil.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/SettingsUtil.cs new file mode 100644 index 0000000..0aaa269 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/SettingsUtil.cs @@ -0,0 +1,116 @@ +锘縰sing System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using UnityEditor; +using UnityEditorInternal; +using UnityEngine; +using HybridCLR.Editor.Settings; + + +namespace HybridCLR.Editor +{ + public static class SettingsUtil + { + public static bool Enable + { + get => HybridCLRSettings.Instance.enable; + set + { + HybridCLRSettings.Instance.enable = value; + HybridCLRSettings.Save(); + } + } + + public static string PackageName { get; } = "com.code-philosophy.hybridclr"; + + public static string HybridCLRDataPathInPackage => $"Packages/{PackageName}/Data~"; + + public static string TemplatePathInPackage => $"{HybridCLRDataPathInPackage}/Templates"; + + public static string ProjectDir { get; } = Directory.GetParent(Application.dataPath).ToString(); + + public static string ScriptingAssembliesJsonFile { get; } = "ScriptingAssemblies.json"; + + public static string HotUpdateDllsRootOutputDir => HybridCLRSettings.Instance.hotUpdateDllCompileOutputRootDir; + + public static string AssembliesPostIl2CppStripDir => HybridCLRSettings.Instance.strippedAOTDllOutputRootDir; + + public static string HybridCLRDataDir => $"{ProjectDir}/HybridCLRData"; + + public static string LocalUnityDataDir => $"{HybridCLRDataDir}/LocalIl2CppData-{Application.platform}"; + + public static string LocalIl2CppDir => $"{LocalUnityDataDir}/il2cpp"; + + public static string GeneratedCppDir => $"{LocalIl2CppDir}/libil2cpp/hybridclr/generated"; + + public static string Il2CppBuildCacheDir { get; } = $"{ProjectDir}/Library/Il2cppBuildCache"; + + public static string GlobalgamemanagersBinFile { get; } = "globalgamemanagers"; + + public static string Dataunity3dBinFile { get; } = "data.unity3d"; + + public static string GetHotUpdateDllsOutputDirByTarget(BuildTarget target) + { + return $"{HotUpdateDllsRootOutputDir}/{target}"; + } + + public static string GetAssembliesPostIl2CppStripDir(BuildTarget target) + { + return $"{AssembliesPostIl2CppStripDir}/{target}"; + } + + class AssemblyDefinitionData + { + public string name; + } + + public static List<string> HotUpdateAssemblyNamesExcludePreserved + { + get + { + var gs = HybridCLRSettings.Instance; + var hotfixAssNames = (gs.hotUpdateAssemblyDefinitions ?? Array.Empty<AssemblyDefinitionAsset>()).Select(ad => JsonUtility.FromJson<AssemblyDefinitionData>(ad.text)); + + var hotfixAssembles = new List<string>(); + foreach (var assName in hotfixAssNames) + { + hotfixAssembles.Add(assName.name); + } + hotfixAssembles.AddRange(gs.hotUpdateAssemblies ?? Array.Empty<string>()); + return hotfixAssembles.ToList(); + } + } + + public static List<string> HotUpdateAssemblyFilesExcludePreserved => HotUpdateAssemblyNamesExcludePreserved.Select(dll => dll + ".dll").ToList(); + + + public static List<string> HotUpdateAssemblyNamesIncludePreserved + { + get + { + List<string> allAsses = HotUpdateAssemblyNamesExcludePreserved; + string[] preserveAssemblyNames = HybridCLRSettings.Instance.preserveHotUpdateAssemblies; + if (preserveAssemblyNames != null && preserveAssemblyNames.Length > 0) + { + foreach (var assemblyName in preserveAssemblyNames) + { + if (allAsses.Contains(assemblyName)) + { + throw new Exception($"[HotUpdateAssemblyNamesIncludePreserved] assembly:'{assemblyName}' is duplicated"); + } + allAsses.Add(assemblyName); + } + } + + return allAsses; + } + } + + public static List<string> HotUpdateAssemblyFilesIncludePreserved => HotUpdateAssemblyNamesIncludePreserved.Select(ass => ass + ".dll").ToList(); + + public static List<string> AOTAssemblyNames => HybridCLRSettings.Instance.patchAOTAssemblies.ToList(); + + public static HybridCLRSettings HybridCLRSettings => HybridCLRSettings.Instance; + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/SettingsUtil.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/SettingsUtil.cs.meta new file mode 100644 index 0000000..323dcf6 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/SettingsUtil.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 381c08faeafbc004f97504eeba87380d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Template.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Template.meta new file mode 100644 index 0000000..f2430d5 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Template.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9af6345cc5ab1ae4a81262ab4b537911 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Template/FileRegionReplace.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Template/FileRegionReplace.cs new file mode 100644 index 0000000..797477b --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Template/FileRegionReplace.cs @@ -0,0 +1,74 @@ +锘縰sing System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace HybridCLR.Editor.Template +{ + public class FileRegionReplace + { + private readonly string _tplCode; + + private readonly Dictionary<string, string> _regionReplaceContents = new Dictionary<string, string>(); + + public FileRegionReplace(string tplCode) + { + _tplCode = tplCode; + } + + public void Replace(string regionName, string regionContent) + { + _regionReplaceContents.Add(regionName, regionContent); + } + + public string GenFinalString() + { + string originContent = _tplCode; + + string resultContent = originContent; + + foreach (var c in _regionReplaceContents) + { + resultContent = ReplaceRegion(resultContent, c.Key, c.Value); + } + return resultContent; + } + + public void Commit(string outputFile) + { + string dir = Path.GetDirectoryName(outputFile); + Directory.CreateDirectory(dir); + string resultContent = GenFinalString(); + var utf8WithoutBOM = new System.Text.UTF8Encoding(false); + File.WriteAllText(outputFile, resultContent, utf8WithoutBOM); + } + + public static string ReplaceRegion(string resultText, string region, string replaceContent) + { + int startIndex = resultText.IndexOf("//!!!{{" + region); + if (startIndex == -1) + { + throw new Exception($"region:{region} start not find"); + } + int endIndex = resultText.IndexOf("//!!!}}" + region); + if (endIndex == -1) + { + throw new Exception($"region:{region} end not find"); + } + int replaceStart = resultText.IndexOf('\n', startIndex); + int replaceEnd = resultText.LastIndexOf('\n', endIndex); + if (replaceStart == -1 || replaceEnd == -1) + { + throw new Exception($"region:{region} not find"); + } + if (resultText.Substring(replaceStart, replaceEnd - replaceStart) == replaceContent) + { + return resultText; + } + resultText = resultText.Substring(0, replaceStart) + "\n" + replaceContent + "\n" + resultText.Substring(replaceEnd); + return resultText; + } + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Template/FileRegionReplace.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Template/FileRegionReplace.cs.meta new file mode 100644 index 0000000..14a642a --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Editor/Template/FileRegionReplace.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 15d4563ad83546c42bc65c99be9bd54a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/LICENSE b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/LICENSE new file mode 100644 index 0000000..dcad5cf --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 Code Philosophy Technology Ltd. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/LICENSE.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/LICENSE.meta new file mode 100644 index 0000000..d5478d5 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/LICENSE.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: f09e582706a5776448316f6c584e63a6 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Plugins.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Plugins.meta new file mode 100644 index 0000000..ccdd127 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Plugins.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a26873724919287449e2c9eec68ef1da +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Plugins/LZ4.dll b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Plugins/LZ4.dll new file mode 100644 index 0000000..f1aeba3 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Plugins/LZ4.dll Binary files differ diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Plugins/LZ4.dll.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Plugins/LZ4.dll.meta new file mode 100644 index 0000000..527366c --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Plugins/LZ4.dll.meta @@ -0,0 +1,87 @@ +fileFormatVersion: 2 +guid: ca69cf4ffd628394a9dd1ef1c56f7f20 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 1 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + : Any + second: + enabled: 0 + settings: + Exclude Android: 1 + Exclude Editor: 0 + Exclude Linux64: 1 + Exclude OSXUniversal: 1 + Exclude WebGL: 1 + Exclude Win: 1 + Exclude Win64: 1 + Exclude iOS: 1 + - first: + Android: Android + second: + enabled: 0 + settings: + CPU: ARMv7 + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 1 + settings: + CPU: AnyCPU + DefaultValueInitialized: true + OS: AnyOS + - first: + Standalone: Linux64 + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: OSXUniversal + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: Win + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: Win64 + second: + enabled: 0 + settings: + CPU: None + - first: + Windows Store Apps: WindowsStoreApps + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + iPhone: iOS + second: + enabled: 0 + settings: + AddToEmbeddedBinaries: false + CPU: AnyCPU + CompileFlags: + FrameworkDependencies: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Plugins/dnlib.dll b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Plugins/dnlib.dll new file mode 100644 index 0000000..ba1f36d --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Plugins/dnlib.dll Binary files differ diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Plugins/dnlib.dll.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Plugins/dnlib.dll.meta new file mode 100644 index 0000000..bdb7a88 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Plugins/dnlib.dll.meta @@ -0,0 +1,87 @@ +fileFormatVersion: 2 +guid: b93c6604eb031674b80de14cd4458dc0 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + : Any + second: + enabled: 0 + settings: + Exclude Android: 1 + Exclude Editor: 0 + Exclude Linux64: 1 + Exclude OSXUniversal: 1 + Exclude WebGL: 1 + Exclude Win: 1 + Exclude Win64: 1 + Exclude iOS: 1 + - first: + Android: Android + second: + enabled: 0 + settings: + CPU: ARMv7 + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 1 + settings: + CPU: AnyCPU + DefaultValueInitialized: true + OS: AnyOS + - first: + Standalone: Linux64 + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: OSXUniversal + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: Win + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: Win64 + second: + enabled: 0 + settings: + CPU: None + - first: + Windows Store Apps: WindowsStoreApps + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + iPhone: iOS + second: + enabled: 0 + settings: + AddToEmbeddedBinaries: false + CPU: AnyCPU + CompileFlags: + FrameworkDependencies: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/README.md b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/README.md new file mode 100644 index 0000000..d759670 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/README.md @@ -0,0 +1,88 @@ +- [README 涓枃](./README.md) +- [README English](./README_EN.md) + +# HybridCLR + +[](https://github.com/focus-creative-games/hybridclr/blob/main/LICENSE) + + + +<br/> +<br/> + +HybridCLR鏄竴涓�**鐗规�у畬鏁淬�侀浂鎴愭湰銆侀珮鎬ц兘銆佷綆鍐呭瓨**鐨�**杩戜箮瀹岀編**鐨刄nity鍏ㄥ钩鍙板師鐢焎#鐑洿鏂拌В鍐虫柟妗堛�� + +HybridCLR鎵╁厖浜唅l2cpp杩愯鏃朵唬鐮侊紝浣垮畠鐢辩函[AOT](https://en.wikipedia.org/wiki/Ahead-of-time_compilation) runtime鍙樻垚AOT+Interpreter 娣峰悎runtime锛岃繘鑰屽師鐢熸敮鎸佸姩鎬佸姞杞絘ssembly锛屼粠搴曞眰褰诲簳鏀寔浜嗙儹鏇存柊銆備娇鐢℉ybridCLR鎶�鏈殑娓告垙涓嶄粎鑳藉湪Android骞冲彴锛屼篃鑳藉湪IOS銆丆onsoles銆乄ebGL绛夋墍鏈塱l2cpp鏀寔鐨勫钩鍙颁笂楂樻晥杩愯銆� + +鐢变簬HybridCLR瀵笶CMA-335瑙勮寖 鐨勮壇濂芥敮鎸佷互鍙婂Unity寮�鍙戝伐浣滄祦鐨勯珮搴﹀吋瀹癸紝Unity椤圭洰鍦ㄦ帴鍏ybridCLR鍚庯紝鍙互鍑犱箮鏃犵紳鍦拌幏寰桟#浠g爜鐑洿鏂扮殑鑳藉姏锛屽紑鍙戣�呬笉闇�瑕佹敼鍙樻棩甯稿紑鍙戜範鎯拰瑕佹眰銆侶ybridCLR棣栨瀹炵幇浜嗗皢Unity骞冲彴鐨勫叏骞冲彴浠g爜鐑洿鏂版柟妗堢殑宸ョ▼闅惧害闄嶅埌鍑犱箮涓洪浂鐨勬按骞炽�� + +娆㈣繋鎷ユ姳鐜颁唬鍘熺敓C#鐑洿鏂版妧鏈� 锛侊紒锛� + +## 鏂囨。 + +- [瀹樻柟鏂囨。](https://hybridclr.doc.code-philosophy.com/docs/intro) +- [蹇�熶笂鎵媇(https://hybridclr.doc.code-philosophy.com/docs/beginner/quickstart) +- [鍟嗕笟椤圭洰妗堜緥](https://hybridclr.doc.code-philosophy.com/docs/other/businesscase) + + +## 鐗规�� + +- 杩戜箮瀹屾暣瀹炵幇浜哰ECMA-335瑙勮寖](https://www.ecma-international.org/publications-and-standards/standards/ecma-335/)锛屽彧鏈夋瀬灏戦噺鐨刐涓嶆敮鎸佺殑鐗规�(https://hybridclr.doc.code-philosophy.com/docs/basic/notsupportedfeatures)銆� +- 闆跺涔犲拰浣跨敤鎴愭湰銆傚缁濆ぇ澶氭暟寮�鍙戣�呮潵璇村啓浠g爜杩戜箮娌℃湁闄愬埗銆� 鐑洿鏂颁唬鐮佷笌AOT浠g爜鏃犵紳宸ヤ綔锛屽彲浠ラ殢鎰忓啓缁ф壙銆�**娉涘瀷**銆�**鍙嶅皠**涔嬬被鐨勪唬鐮併�備笉闇�瑕侀澶栧啓浠讳綍鐗规畩浠g爜銆佹病鏈変唬鐮佺敓鎴� +- 瀹屽叏鏀寔澶氱嚎绋嬶紝鍖呭惈浣嗕笉闄愪簬 volatile銆乀hreadStatic銆乤sync Task绛夌浉鍏冲姛鑳藉拰鐗规�с�傝繖鏄叾浠栨墍鏈夌儹鏇存柊鏂规閮戒笉鏀寔鐨� +- 鍑犱箮瀹屽叏鍏煎Unity鐨勫伐浣滄祦銆傚寘鎷笖涓嶉檺浜庢敮鎸佺儹鏇存柊**MonoBehaviour**銆丼criptableObject銆�**DOTS**鎶�鏈紝璧勬簮涓婃寕杞界殑鐑洿鏂拌剼鏈彲浠ユ纭疄渚嬪寲锛岃繖鏄叾浠栨墍鏈夌儹鏇存柊鏂规閮戒笉鏀寔鐨� +- 鎵ц楂樻晥銆傚疄鐜颁簡涓�涓瀬鍏堕珮鏁堢殑瀵勫瓨鍣ㄨВ閲婂櫒锛屾墍鏈夋寚鏍囬兘澶у箙浼樹簬鍏朵粬鐑洿鏂版柟妗堛�俒鎬ц兘娴嬭瘯鎶ュ憡](https://hybridclr.doc.code-philosophy.com/docs/basic/performance) +- 鍐呭瓨楂樻晥銆� 鐑洿鏂拌剼鏈腑瀹氫箟鐨勭被璺熸櫘閫歝#绫诲崰鐢ㄤ竴鏍风殑鍐呭瓨绌洪棿锛岃繙浼樹簬鍏朵粬鐑洿鏂版柟妗堛�俒鍐呭瓨鍗犵敤鎶ュ憡](https://hybridclr.doc.code-philosophy.com/docs/basic/memory) +- 鏀寔MonoPInvokeCallback锛屽彲浠ヤ笌native浠g爜鎴栬�呭叾浠栬瑷�濡俵ua銆乯avascript銆乸ython鑹ソ浜や簰 +- 鏀寔涓�浜沬l2cpp涓嶆敮鎸佺殑鐗规�э紝濡俖_makeref銆� __reftype銆乢_refvalue鎸囦护 +- 鏀寔鐙垱鐨� **Differential Hybrid Execution(DHE)** 宸垎娣峰悎鎵ц鎶�鏈紝鍗冲彲浠ュAOT dll浠绘剰澧炲垹鏀癸紝浼氭櫤鑳藉湴璁╂湭鏀瑰姩鐨勫嚱鏁颁互AOT鏂瑰紡杩愯锛屽彉鍖栨垨鑰呮柊澧炵殑鍑芥暟浠nterpreter妯″紡杩愯锛岃鐑洿鏂扮殑娓告垙閫昏緫鐨勮繍琛屾�ц兘鍩烘湰杈惧埌鍘熺敓AOT鐨勬按骞� +- 鏀寔 **鐑噸杞�** 鎶�鏈紝鍙互100%鍗歌浇绋嬪簭闆� +- 鏀寔鐜颁唬鐨刣ll鍔犲瘑鎶�鏈紝鏈夋晥淇濋殰浠g爜瀹夊叏 + +## 鏀寔鐨勭増鏈笌骞冲彴 + +- 鏀寔2019.4.x銆�2020.3.x銆�2021.3.x銆�2022.3.x銆�2023.2.x銆�6000.0.x鍏ㄧ郴鍒桳TS鐗堟湰 +- 鏀寔鎵�鏈塱l2cpp鏀寔鐨勫钩鍙� +- 鏀寔鍥㈢粨寮曟搸鍜岄缚钂欏钩鍙� + +## 宸ヤ綔鍘熺悊 + +HybridCLR浠巑ono鐨� [mixed mode execution](https://www.mono-project.com/news/2017/11/13/mono-interpreter/) 鎶�鏈腑寰楀埌鍚彂锛屼负unity鐨刬l2cpp涔嬬被鐨凙OT runtime棰濆鎻愪緵浜唅nterpreter妯″潡锛屽皢瀹冧滑鐢辩函AOT杩愯鏃舵敼閫犱负"AOT + Interpreter"娣峰悎杩愯鏂瑰紡銆� + + + +鏇村叿浣撳湴璇达紝HybridCLR鍋氫簡浠ヤ笅鍑犵偣宸ヤ綔锛� + +- 瀹炵幇浜嗕竴涓珮鏁堢殑鍏冩暟鎹�(dll)瑙f瀽搴� +- 鏀归�犱簡鍏冩暟鎹鐞嗘ā鍧楋紝瀹炵幇浜嗗厓鏁版嵁鐨勫姩鎬佹敞鍐� +- 瀹炵幇浜嗕竴涓狪L鎸囦护闆嗗埌鑷畾涔夌殑瀵勫瓨鍣ㄦ寚浠ら泦鐨刢ompiler +- 瀹炵幇浜嗕竴涓珮鏁堢殑瀵勫瓨鍣ㄨВ閲婂櫒 +- 棰濆鎻愪緵澶ч噺鐨刬nstinct鍑芥暟锛屾彁鍗囪В閲婂櫒鎬ц兘 + +## 绋冲畾鎬х姸鍐� + +HybridCLR宸茬粡琚箍娉涢獙璇佹槸闈炲父楂樻晥銆佺ǔ瀹氱殑Unity鐑洿鏂拌В鍐虫柟妗堬紝鑹ソ婊¤冻澶т腑鍨嬪晢涓氶」鐩殑绋冲畾鍜屾�ц兘瑕佹眰銆� + +鐩墠宸茬粡鏈夋暟鍗冧釜鍟嗕笟娓告垙椤圭洰鎺ュ叆浜咹ybridCLR锛屽叾涓湁瓒呰繃鍗冧釜宸茬粡鍦ˋpp Store鍜孏oogle Player涓婄嚎锛屼粎浠卛OS鍏嶈垂姒滃墠500鍚嶄腑灏辨湁杩戠櫨娆句娇鐢ㄤ簡HybridCLR銆備笂绾跨殑椤圭洰涓寘鎷琈MORPG銆侀噸搴﹀崱鐗屻�侀噸搴﹀闃蹭箣绫荤殑娓告垙銆傚浗鍐呯粷澶у鏁�**Top娓告垙鍏徃**閮藉凡缁忓湪浣跨敤HybridCLR銆� + +鍙煡鐪嬫垜浠凡鐭ョ殑澶撮儴鍏徃涓娇鐢℉ybridCLR骞朵笖宸茬粡涓婄嚎鐨刐椤圭洰鍒楄〃](https://hybridclr.doc.code-philosophy.com/docs/other/businesscase)銆� + +## 鏀寔涓庤仈绯� + +- 瀹樻柟1缇わ紙3000浜猴級锛�651188171锛堟弧锛� +- 鏂版墜1缇わ紙3000浜猴級锛�428404198锛堟弧锛� +- 鏂版墜2缇わ紙2000浜猴級锛�680274677锛堟弧锛� +- 鏂版墜3缇わ紙2000浜猴級锛�**920714552锛堟帹鑽愶級** +- discord棰戦亾 https://discord.gg/BATfNfJnm2 +- 鍟嗕笟鍚堜綔閭: business#code-philosophy.com +- [鍟嗕笟鍖栨敮鎸乚(https://hybridclr.doc.code-philosophy.com/docs/business/intro) + +## 鍏充簬浣滆�� + +**walon** 锛�**Code Philosophy锛堜唬鐮佸摬瀛︼級** 鍒涘浜� + +姣曚笟浜庢竻鍗庡ぇ瀛︾墿鐞嗙郴锛�2006骞碈MO閲戠墝锛屽ゥ鏁板浗瀹堕泦璁槦鎴愬憳锛屼繚閫佹竻鍗庡熀绉戠彮銆備笓娉ㄤ簬娓告垙鎶�鏈紝鎿呴暱寮�鍙戞灦鏋勫拰鍩虹鎶�鏈鏂姐�� + +## license + +HybridCLR is licensed under the [MIT](https://github.com/focus-creative-games/hybridclr/blob/main/LICENSE) license diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/README.md.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/README.md.meta new file mode 100644 index 0000000..b674416 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/README.md.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: b4b6051e2483d664facc72a5102dcffc +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/README_EN.md b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/README_EN.md new file mode 100644 index 0000000..16cd417 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/README_EN.md @@ -0,0 +1,87 @@ + +- [README Chinese](./README.md) +- [README English](./README_EN.md) + +# HybridCLR + +[](https://github.com/focus-creative-games/hybridclr/blob/main/LICENSE) + + + +<br/> +<br/> + +HybridCLR is a **feature-complete, zero-cost, high-performance, low-memory** **near-perfect** Unity cross-platform native C# hot update solution. + +HybridCLR extends the il2cpp runtime code, transforming it from a pure [AOT](https://en.wikipedia.org/wiki/Ahead-of-time_compilation) runtime to an AOT+Interpreter hybrid runtime, thereby natively supporting the dynamic loading of assemblies and fundamentally supporting hot updates from the bottom layer. Games using HybridCLR technology can not only run efficiently on the Android platform but also on all platforms supported by il2cpp, including iOS, Consoles, WebGL, etc. + +Thanks to HybridCLR's good support for the ECMA-335 specification and its high compatibility with the Unity development workflow, Unity projects can almost seamlessly gain the ability to hot update C# code after integrating HybridCLR. Developers do not need to change their daily development habits and requirements. HybridCLR is the first to achieve the engineering difficulty of a full-platform code hot update solution for the Unity platform to almost zero. + +Welcome to embrace modern native C# hot update technology! + +## Documentation + +- [Official Documentation](https://hybridclr.doc.code-philosophy.com/en/docs/intro) +- [Quick Start](https://hybridclr.doc.code-philosophy.com/en/docs/beginner/quickstart) +- [Business Project Cases](https://hybridclr.doc.code-philosophy.com/en/docs/other/businesscase) + +## Features + +- Nearly complete implementation of the [ECMA-335 specification](https://www.ecma-international.org/publications-and-standards/standards/ecma-335/), with only a very small number of [unsupported features](https://hybridclr.doc.code-philosophy.com/en/docs/basic/notsupportedfeatures). +- Zero learning and usage costs. For most developers, writing code is almost unrestricted. Hot update code works seamlessly with AOT code, allowing for inheritance, **generics**, **reflection**, and other code without additional special code or code generation. +- Full support for multithreading, including but not limited to volatile, ThreadStatic, async Task, and related features and characteristics. This is not supported by any other hot update solution. +- Almost complete compatibility with Unity's workflow. This includes support for hot updating **MonoBehaviour**, ScriptableObject, **DOTS** technology, and correctly instantiating hot update scripts mounted on resources, which is not supported by any other hot update solution. +- Efficient execution. A highly efficient register interpreter has been implemented, with all indicators significantly better than other hot update solutions. [Performance Test Report](https://hybridclr.doc.code-philosophy.com/en/docs/basic/performance) +- Efficient memory usage. Classes defined in hot update scripts occupy the same memory space as ordinary C# classes, far superior to other hot update solutions. [Memory Usage Report](https://hybridclr.doc.code-philosophy.com/en/docs/basic/memory) +- Supports MonoPInvokeCallback, enabling good interaction with native code or other languages such as Lua, JavaScript, Python. +- Supports some features not supported by il2cpp, such as __makeref, __reftype, __refvalue instructions. +- Supports the unique **Differential Hybrid Execution (DHE)** technology, which allows for arbitrary additions, deletions, and modifications to AOT DLLs. It intelligently runs unchanged functions in AOT mode and changed or newly added functions in interpreter mode, bringing the performance of hot-updated game logic close to that of native AOT. +- Supports **hot reload** technology, allowing 100% unloading of assemblies. +- Supports modern DLL encryption technology to effectively protect code security. + +## Supported Versions and Platforms + +- Supports all LTS versions including 2019.4.x, 2020.3.x, 2021.3.x, 2022.3.x, 2023.2.x, 6000.0.x. +- Supports all platforms supported by il2cpp. +- Supports Tuanjie(China) Engine and HarmonyOS platform. + +## Working Principle + +HybridCLR draws inspiration from Mono's [mixed mode execution](https://www.mono-project.com/news/2017/11/13/mono-interpreter/) technology, providing an interpreter module for AOT runtimes like Unity's il2cpp, transforming them from pure AOT runtimes to "AOT + Interpreter" hybrid operation modes. + + + +More specifically, HybridCLR has done the following: + +- Implemented an efficient metadata (dll) parsing library. +- Modified the metadata management module to achieve dynamic registration of metadata. +- Implemented a compiler that converts IL instructions to a custom register instruction set. +- Implemented an efficient register interpreter. +- Provided a large number of instinct functions to enhance interpreter performance. + +## Stability Status + +HybridCLR has been widely verified as an efficient and stable Unity hot update solution, meeting the stability and performance requirements of medium and large commercial projects. + +Currently, thousands of commercial game projects have integrated HybridCLR, with over a thousand already launched on the App Store and Google Play. Nearly a hundred of the top 500 free iOS games use HybridCLR, including MMORPGs, heavy card games, and heavy tower defense games. Most of the **Top Game Companies** in China are already using HybridCLR. + +You can view the [list of known top companies using HybridCLR and their launched projects](https://hybridclr.doc.code-philosophy.com/en/docs/other/businesscase). + +## Support and Contact + +- Official Group 1: 651188171 (Full) +- Beginner Group 1: 428404198 (Full) +- Beginner Group 2: **680274677 (Recommended)** +- Discord channel https://discord.gg/BATfNfJnm2 +- Business cooperation email: business#code-philosophy.com +- [Commercial Support](https://hybridclr.doc.code-philosophy.com/en/docs/business/intro) + +## About the Author + +**walon**: Founder of **Code Philosophy (浠g爜鍝插)** + +Graduated from the Department of Physics at Tsinghua University, gold medalist of the 2006 CMO, member of the National Mathematical Olympiad Training Team, and sent to the Basic Science Class of Tsinghua. Focused on game technology, proficient in development architecture and basic technical infrastructure. + +## License + +HybridCLR is licensed under the [MIT](https://github.com/focus-creative-games/hybridclr/blob/main/LICENSE) license. diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/README_EN.md.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/README_EN.md.meta new file mode 100644 index 0000000..2da64ec --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/README_EN.md.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: c9e34f237251ef44193538977db6b15f +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/RELEASELOG.md b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/RELEASELOG.md new file mode 100644 index 0000000..0cd36f4 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/RELEASELOG.md @@ -0,0 +1,899 @@ +# ReleaseLog + +## 7.9.0 + +Release Date: 2025-03-31. + +### Runtime + +- [merge] merge il2cpp changes from 6000.0.30f1 to 6000.0.44f1 + +## 7.8.1 + +Release Date: 2025-03-24. + +### Runtime + +- [fix] fix bug of CreateInitLocals when size <= 16 +- [change] remove unnecessary `frame->ip = (byte*)ip;` assignment in LOAD_PREV_FRAME() + +## 7.8.0 + +Release Date: 2025-03-24. + +### Runtime + +- [opt] fixed a **critical** bug where taking the address of the ip variable severely impacted compiler optimizations, leading to significant performance degradation. +- [opt] add HiOpCodeEnum::None case to interpreter loop. avoid decrement *ip when compute jump table, boosts about 5% performance. +- [opt] opt InitLocals and InitInlineLocals in small size cases +- [opt] reorder MethodInfo fields to reduce memory size + +### Editor + +- [fix] fixed the bug where BashUtil.RemoveDir failed to run under certain circumstances on macOS systems. + +## 7.7.0 + +Release Date: 2025-03-12. + +### Runtime + +- [change] fixed the issue that HYBRIDCLR_ENABLE_PROFILER was disabled in release build +- [fix] fix a crash in PDBImage::SetMethodDebugInfo when GetMethodDataFromCache returns nullptr +- [fix] fix assert bug of InterpreterDelegateInvoke when method->parameters_count - curMethod->parameters_count == 1 +- [fix] fix compiler error of initialize constructor code `{a, b}` for `std::tuple<void*,void*>` in PS5 +- [opt] removed unnecessary pdb lock in PDBImage +- [change] fix some compiler warnings +- [change] HYBRIDCLR_ENABLE_STRACKTRACE was enabled in both DEBUG and RELEASE build without considering HYBRIDCLR_ENABLE_STRACE_TRACE_IN_WEBGL_RELEASE_BUILD flag. + +### Editor + +- [fix] fixed hook failed in version below MacOS 11 +- [change] CompileDllActiveBuildTarget and GenerateAll use EditorUserBuildSettings.development to compile hot update dll. +- [remove] remove option HybridCLRSettings.enableProfilerInReleaseBuild +- [remove] remove option HybridCLRSettings.enableStraceTraceInWebGLReleaseBuild + +## 7.6.0 + +Release Date: 2025-03-01. + +### Runtime + +- [fix] fixed the bug in ClassFieldLayoutCalculator where it incorrectly handles [StructLayout] and blittable attribute when calculating the layout for structs. +- [fix] fix bug of computing explicit struct layout caused by commit "199b1b1a789d760828bd33e7e1438261cd1f8d15" +- [fix] fix the code `TokenGenericContextType key = { token, genericContext }` has compiler error in PS5 +- [merge] merge il2cpp changes from 2021.3.44f1 to 2021.3.49f1 + +### Editor + +- [fix] fixed the bug in the MethodBridge generator where it incorrectly handles [StructLayout] and blittable attribute when generating code for struct classes. +- [new] add AssemblySorter to sort assemblies by reference order + +## 7.5.0 + +Release Date: 2025-02-05. + +### Editor + +- [revert] Revert 'support preserve UnityEngine core types when GenerateLinkXml'. + +## 7.4.1 + +Release Date: 2025-01-19. + +### Editor + +[fix] fixe the bug that preserving UnityEngine.PerformanceReportingModule when generating link.xml would cause the Android app built with Unity 2019 to crash on startup. + +## 7.4.0 + +Release Date: 2025-01-17. + +### Runtime + +- [new] calli supports call both native function pointer and managed method + +### Editor + +- [new] add Managed2NativeFunctionPointer MethodBridge functions +- [new] support preserve UnityEngine core types when GenerateLinkXml +- [fix] fixed the bug in AOTAssemblyMetadataStripper::Strip where ModuleWriterOptions MetadataFlags.PreserveRids was not used. +- [fix] fixed the bug where StripAOTDllCommand did not set BuildPlayerOptions.subtarget in Unity 2021+ versions, causing failure when publishing dedicated buildTarget. +- [change] add UnityVersion.h.tpl and AssemblyManifest.cpp.tpl, Il2CppDefGenerator doesn't generates and override code file from same one +- [change] add MethodBridge.cpp.tpl. MethodBridgeGeneratorCommand doesn't generate and override from same file + +## 7.3.0 + +Release Date: 2024-12-31. + +### Runtime + +- [fix] fix bug that Image::ReadRuntimeHandleFromMemberRef didn't inflate parent type when read field of GenericType +- [fix] fix an issue occurred in InterpreterImage::GenerateCustomAttributesCacheInternal where HYBRIDCLR_METADATA_MALLOC was incorrectly used to allocate the cache. When occasional contention occurs, releasing memory using HYBRIDCLR_FREE causes a crash. +- [fix] fixed a potential deadlock issue in Unity 2019 and 2020 versions within InterpreterImage::GenerateCustomAttributesCacheInternal, where il2cpp::vm::g_MetadataLock was held before running ConstructCustomAttribute. +- [fix] fixed a bug in Unity 2019 and 2020 within InterpreterImage::GenerateCustomAttributesCacheInternal, where cache memory leaks occurred under multithreading contention. +- [fix] fix the bug that InterpreterImage::ConstructCustomAttribute doesn't set write barrier for field +- [fix] fix the bug that `InterpreterImage::InitTypeDefs_2` runs after `InitClassLayouts`, causing the `packingSize` field to be incorrectly initialized. +- [fix] fix the bug in ClassFieldLayoutCalculator::LayoutFields where the alignment calculation incorrectly considers naturalAlignment, resulting in field offsets that are inconsistent with the actual field offsets in AOT. This bug originates from IL2CPP itself and only occurs in Unity 2021 and earlier versions. + +### Editor + +- [fix] fix the issue in Unity 6000 where the modification of the trimmed AOT DLL output directory for the visionOS build target caused CopyStrippedAOTAssemblies::GetStripAssembliesDir2021 to fail in copying AOT DLLs. +- [fix] fix the bug where MissingMetadataChecker can't detect references to newly added AOT assemblies. + +## 7.2.0 + +Release Date: 2024-12-9. + +### Runtime + +- [fix] fix a critical bug in Image::ReadArrayType, where it incorrectly uses alloca to allocate Il2CppArray's sizes and lobounds data. +- [merge] merge il2cpp changes from 2022.3.51f1 to 2022.3.54f1 +- [merge] merge il2cpp changes from 6000.0.21 to 6000.0.30 + +## 7.1.0 + +Release Date: 2024-12-4. + +### Runtime + +- [new] support prejit interpreter class and method +- [new] add RuntimeOptionId::MaxInlineableMethodBodySize +- [merge] merge il2cpp changes from tuanjie v1.3.1 to v1.3.4 +- [fix] fix memory leak of TransformContext::irbbs and ir2offsetMap +- [opt] does not insert CheckThrowIfNull check when inlining constructors +- [opt] remove unnecessary typeSize calculation from the NewValueTypeInterpVar instruction. +- [change] change default maxInlineableMethodBodySize from 16 to 32 +- [change] remove the unnecessary Inflate operation on arg.type when initializing ArgVarInfo in TransformContext::TransformBodyImpl. +- [change] remove unnecessary fields genericContext, klassContainer, methodContainer from the TransformContext + +### Editor + +- [new] support prejit interpreter class and method +- [new] add RuntimeOptionId::MaxInlineableMethodBodySize +- [fix] fix the bug that CopyStrippedAOTAssemblies didn't work on UWP platform of 6000.0.x +- [fix] fix the issue that CopyStrippedAOTAssemblies didn't support HMIAndroid in tuanjie engine +- [change] change the attributes on fields of HybridCLRSettings from `[Header]` to `[ToolTip]` +- [refactor] refactor code comments and translate them to English + +## 7.0.0 + +Release Date: 2024-11-15. + +### Runtime + +- [new] support method inlining +- [refactor] refactor Transform codes + +### Editor + +- [new] add option RuntimeOptionId::MaxMethodBodyCacheSize and RuntimeOptionId::MaxMethodInlineDepth +- [fix] fix the bug in GenericReferenceWriter where _systemTypePattern did not properly escape the '.' in type names. This caused issues when compiler-generated anonymous types and functions contained string sequences like 'System-Int', incorrectly matching them to 'System.Int', resulting in runtime exceptions. +- [fix] fix the bug in `MissingMetadataChecker` where it did not check for missing fields. + +## 6.11.0 + +Release Date: 2024-10-31. + +### Runtime + +- [merge] Merges changes from Tuanjie versions 1.3.0 to 1.3.1 +- [merge] Merges il2cpp code changes from version 2022.3.48f1 to 2022.3.51f1 + +## 6.10.1 + +Release Date: 2024-10-24. + +### Editor + +- [fix] Fixs HookUtils compile errors in Unity 2019 and 2020 +- [change] remove README_zh.md.meta, add README_EN.md.meta + +## 6.10.0 + +Release Date: 2024-10-23. + +### Runtime + +- [new] Officially supports 6000.0.23f LTS version +- [merge] Merges changes from Tuanjie versions 1.2.6 to 1.3.0 +- [fix] Fixed an issue in MonoHook where processorType was not handled correctly on some CPUs when the processorType was returned in all uppercase (e.g., some machines return 'INTEL' instead of 'Intel'). + +## 6.9.0 + +Release Date: 2024-9-30. + +### Runtime + +- [fix] Fixes the bug where thrown exceptions did not call `il2cpp::vm::Exception::PrepareExceptionForThrow`, resulting in an empty stack trace. +- [merge] Merges changes from versions 2021.3.42f1 to 2021.3.44f1, fixing compilation errors introduced by il2cpp changes in version 2021.3.44. +- [merge] Merges changes from versions 2022.3.41f1 to 2022.3.48f1, fixing compilation errors introduced by il2cpp changes in version 2022.3.48. +- [merge] Merges code from 6000.0.19f1 to 6000.0.21f1, fixing compilation errors introduced by il2cpp changes in version 6000.0.20. +- [merge] Merges changes from Tuanjie versions 1.1.0 to 1.2.6 + +## 6.8.0 + +Release Date: 2024-9-14. + +### Runtime + +- [fix] Fixes the bug where exception stacks did not include line numbers. +- [fix] Fixes the bug where `Il2CppGenericContextCompare` simply compared class_inst and method_inst pointers for equality, which is not the case for all GenericInst (e.g., `s_Il2CppMetadataRegistration->genericInsts`) that do not come from GenericInstPool, hence identical GenericInst are not pointer equal. +- [merge] Merges il2cpp code changes from version 6000.0.10 to 6000.0.19 + +## 6.7.1 + +Release Date: 2024-8-26. + +### Runtime + +- [fix] Fixes the bug where there were compilation errors when publishing to the iOS platform with Unity 2019. + +## 6.7.0 + +Release Date: 2024-8-26. + +### Runtime + +- [opt] No longer enables PROFILER in Release compilation mode, this optimization reduces the overhead of function calls by 10-15%, and overall performance is improved by approximately 2-4%. +- [opt] When publishing for WebGL targets, StackTrace is no longer maintained in Release compilation mode, which improves performance by about 1-2%. +- [fix] Fixes the bug where `Transform Enum::GetHashCode` did not change the variable type from `uintptr_t` to `int32_t` on the stack, leading to incorrect calculations when participating in subsequent numerical computations due to the parameter type being extended to 64 bits. +- [fix] Fixes the bug where a stack overflow was triggered by calling delegates extensively within interpreter functions. + +### Editor + +- [new] HybridCLRSettings adds two new options: `enableProfilerInReleaseBuild` and `enableStackTraceInWebGLReleaseBuild`. +- [change] Fixes the issue where an assertion failure occurred when switching from the WebGL platform to other platforms (no substantial impact). + +## 6.6.0 + +Release Date: 2024-8-12. + +### Runtime + +- [fix] Fixes the bug where `CustomAttribute` construction or namedArg includes a `typeof(T[])` parameter, causing a crash. +- [fix] Fixes the bug where `T[index].CallMethod()` throws an `ArrayTypeMismatchException` when `CallMethod` is an interface function of generic type T, and the array element is a subclass of T. +- [fix] Fixes the bug where `MethodBase.GetCurrentMethod` does not return the correct result. A new instinct instruction `MethodBaseGetCurrentMethod` is added. +- [fix] Fixes the bug where loading pdb on platforms like WebGL still does not display stack code line numbers. +- [fix] Fixes the bug where, after calling a sub-interpreter function and returning, logging prints the code line number of the called function due to `frame->ip` not being reset to `&ip`. +- [fix] Fixes the bug where calling a sub-interpreter function displays the line number of the next statement in the parent function's code line number due to `frame->ip` pointing to the next instruction. +- [merge] Merges il2cpp code from 2021.3.42f1 and 2022.3.41f1, fixing compilation errors caused by the new `il2cpp_codegen_memcpy_with_write_barrier` function in versions 2021.3.42f1 and 2022.3.40f1. + +## 6.5.0 + +Release Date: 2024-8-5. + +### Runtime + +- [new] Hot update function stacks for versions 2019-2020 can now correctly display code files and line numbers. +- [merge] Merges il2cpp changes from Unity versions 6000.0.1 to 6000.0.10 + +## 6.4.0 + +Release Date: 2024-7-25. + +### Runtime + +- [new] Supports loading dll and pdb symbol files with `Assembly.Load(byte[] assData, byte[] pdbData)`, displaying the correct code files and line numbers in function stacks when printing on versions 2021+. +- [fix] Fixes the bug where `InterpreterImage::GetEventInfo` and `GetPropertyInfo` might not initialize `method`, resulting in empty getter functions. +- [opt] Optimizes the order of function stacks printed by `StackTrace` and `UnityEngine.Debug`, displaying interpreter functions at the correct stack positions in most cases. +- [opt] Optimizes metadata memory. + +### Editor + +- [fix] Fixes the bug where `GenerateMethodBridge` did not consider `ClassLayout`, `Layout`, and `FieldOffset` factors when calculating equivalent classes. +- [fix] Fixes the bug where `PatchScriptingAssembliesJsonHook` throws an寮傚父 when the `Library/PlayerDataCache` directory does not exist. + +## 6.3.0 + +Release Date: 2024-7-15. + +### Runtime + +- [opt] Significantly optimizes metadata memory, reducing memory usage by 15-40% compared to version 6.2.0. +- [fix] Fixes the bug where memory was not released for `insts` in `IRBasicBlock` during transformation, causing a memory leak approximately 0.7-1.6 times the size of the dll. +- [fix] Fixes the bug where `ClassFieldLayoutCalculator` caused a memory leak. +- [fix] Fixes the bug where `MetadataAllocT` incorrectly used `HYBRIDCLR_MALLOC` instead of `HYBRIDCLR_METADATA_MALLOC`. +- [opt] Optimizes the native stack size occupied by `Interpreter::Execute` to avoid stack overflow errors when nesting is too deep. + +### Editor + +- [fix] Fixes the bug where exporting an xcode project for Unity 2022 includes multiple ShellScript fragments, incorrectly deleting non-repeated fragments. +- [fix] Fixes the bug where the temporary directory name is `WinxinMiniGame{xxx}` when `TextureCompression` is not the default value on the WeChat Mini Games platform, causing the `scriptingassemblies.json` file to not be successfully modified. +- [fix] Fixes the bug where the WeChat Mini Games platform on the Unity Engine, due to the definition of both `UNITY_WEIXINMINIGAME` and `UNITY_WEBGL` macros, fails to find the `scriptingassemblies.json` file from the wrong path, resulting in a script missing bug at runtime. + +## 6.2.0 + +Release Date: 2024-7-1. + +### Runtime + +- [merge] Merges changes from versions 2021.3.27f1 to 2021.3.40f1. +- [opt] Optimizes metadata memory, reducing memory usage by 20-25%. +- [opt] Optimizes the implementation of `GetHashCode` for enum types, no longer generating GC. + +## 6.1.0 + +Release Date: 2024-6-17. + +### Runtime + +- [merge] Merges changes from versions 2022.3.23f1 to 2022.3.33f1, fixing incompatibility issues with version 2022.3.33. +- [new] Supports the new function return value Attribute added in version 2022.3.33. +- [fix] Fixes the bug where `FieldInfo` calling `GetFieldMarshaledSizeForField` crashes. + +### Editor + +- [fix] Upgrades the dnlib version, fixing the serious bug where `ModuleMD` saves dlls without setting the assembly-qualified `mscorlib` assembly types to the current assembly. +- [fix] Fixes the issue where `Generate/LinkXml` generates a `link.xml` that preserves all `UnityEngine.Debug`, causing compilation errors on iOS and visionOS platforms with Unity 2023 and higher versions. This bug is caused by Unity, and we temporarily solve this problem by ignoring the `UnityEngine.Debug` class when generating `link.xml`. + +## 6.0.0 + +Release Date: 2024-6-11. + +### Runtime + +- [new] Supports Unity 6000.x.y and Unity 2023.2.x versions. +- [refactor] Merges `ReversePInvokeMethodStub` into `MethodBridge`, and moves ReversePInvoke-related code from `MetadataModule` to `InterpreterModule`. +- [new] Supports MonoPInvokeCallback functions with parameters or return types as struct types. + +### Editor + +- [new] Supports Unity 6000.x.y and Unity 2023.2.x versions. +- [new] Supports MonoPInvokeCallback functions with parameters or return types as struct types. +- [new] Adds `GeneratedAOTGenericReferenceExcludeExistsAOTClassAndMethods`, which calculates hot update references to AOT generic types and functions, excluding those already existing in AOT, ultimately generating a more accurate list of supplementary metadata assembly programs. +- [fix] Fixes the bug where `CopyStrippedAOTAssemblies` class has compilation errors on some Unity versions that do not support visionOS. +- [fix] Fixes the bug where calculating the `CallingConvention` of `MonoPInvokeCallback` is incorrectly treated as Winapi if the delegate is defined in another assembly, resulting in an incorrect wrapper signature calculation. +- [fix] PatchScriptingAssemblyList.cs has compilation errors on Unity 2023+ WebGL platforms. +- [fix] Fixes the bug where calculating Native2Manager bridge functions does not consider MonoPInvokeCallback functions, leading to `UnsupportedNative2ManagedMethod` when calling C# hot update functions from Lua or other languages. +- [refactor] Merges `ReversePInvokeMethodStub` into `MethodBridge`, and moves ReversePInvoke-related code from `MetadataModule` to `InterpreterModule`. +- [opt] Checks if the development option during packaging is consistent with the current development option. Switching the development option after `Generate/All` and then packaging will cause serious crashes. +- [opt] `Generate/All` checks if HybridCLR is installed before generating. + +## 5.4.1 + +Release Date: 2024-5-30. + +### Editor + +- [new] Supports the visionOS platform. +- [fix]**[Serious]** Fixes the bug where calculating `MonoPInvokeCallback`'s `CallingConvention` incorrectly treats it as Winapi if the delegate is defined in another assembly, resulting in an incorrect wrapper signature calculation. +- [fix] Fixes the bug where the wrong Unity-iPhone.xcodeproj path is used on tvOS platforms, causing the project.pbxproj to not be found. + +## 5.4.0 + +Release Date: 2024-5-20. + +### Runtime + +- [new] ReversePInvoke supports CallingConvention. +- [fix] Fixes the bug where `calli`'s `argBasePtr=argIdx[0]` when the number of arguments is 0, due to `argIdxs` not being assigned, causing the function stack frame to point to the wrong location. +- [fix] Fixes the bug where `MetadataModule::GetReversePInvokeWrappe`'s `ComputeSignature` might deadlock. +- [fix] Fixes the bug where AOT base class virtual functions implementing hot update interface functions use `CallInterpVirtual`, causing runtime exceptions. +- [fix] Fixes the issue where some sub-instructions of the `PREFIX1` prefix instruction are missing and not sorted by instruction number in the Transform. +- [fix] Fixes the bug where the `no.{x}` prefix instruction is 3 bytes long but incorrectly treated as 2 bytes in the Transform. +- [fix] Fixes the bug where the `unaligned.{x}` prefix instruction is 3 bytes long but incorrectly treated as 2 bytes in the Transform. +- [opt] Removes unnecessary `INIT_CLASS` operations in `Interpreter_Execute`, as `PREPARE_NEW_FRAME_FROM_NATIVE` will always check. +- [opt] No longer caches MethodBody of non-generic functions, optimizing memory. +- [opt] **Optimizes supplementary metadata memory**, saving approximately 2.8 times the size of metadata dll memory. +- [refactor] Changes the type of the `_rawImage` field in `Image` from `RawImage` to `RawImage*`. + +### Editor + +- [new] ReversePInvoke supports CallingConvention. +- [fix] Fixes the bug where calculating the equivalence of structs by flattening and expanding them does not apply on some platforms. For example, struct A { uint8_t x; A2 y; } struct A2 { uint8_t x; int32_t y;}; and struct B { uint8_t x; uint8_t y; int32_t z; } are not equivalent under the x86_64 ABI. +- [fix] Fixes the bug where appending to an existing xcode project causes the 'Run Script' command to be duplicated the first time and subsequently fails to find --external-lib-il2-cpp, printing an error log. + +## 5.3.0 + +Release Date: 2024-4-22. + +### Runtime + +- [fix] Fixes the bug where MachineState::CollectFramesWithoutDuplicates incorrectly uses `hybridclr::metadata::IsInterpreterMethod` to remove hot update functions, leading to an increasingly long StackFrames list and an infinite loop when printing the stack. The implementation is adjusted to uniformly use `il2cpp::vm::StackTrace::PushFrame` and `PopFrame` for perfect interpreter stack printing. The downside is the increased overhead of maintaining the stack when calling interpreter functions. +- [fix] Fixes the serious bug where `StringUtils::Utf16ToUtf8` does not correctly handle `maxinumSize==0`, causing a significant overflow when converting strings of length 0 in `InterpreterImage::ConvertConstValue`. +- [fix] Fixes the bug where `_ReversePInvokeMethod_XXX` functions do not set `Il2CppThreadContext`, causing a crash when obtaining thread variables from native threads. +- [merge] Merges il2cpp changes from versions 2021.3.34 to 2021.3.37f1. +- [merge] Merges il2cpp changes from versions 2022.3.19 to 2022.3.23f1. + +### Editor + +- [fix] Fixes the bug where exporting a tvOS project does not modify xcode project settings, causing packaging to fail. +- [fix] Fixes the bug where building for tvOS targets does not copy the pruned AOT dll, causing bridge function generation to fail. +- [fix] Solves the issue where the locationPathName generated by `StripAOTDllCommand` is not standardized, causing incompatibility with some plugins like the Embedded Browser. +- [fix] Fixes the bug where deleting the `TUANJIE_2022` macro in Unity Engine 1.1.0 does not copy the pruned AOT assembly. +- [fix] Fixes the bug where `_ReversePInvokeMethod_XXX` functions do not set `Il2CppThreadContext`, causing a crash when obtaining thread variables from native threads. +- [fix] Fixes the bug where iOS platform mono-related header files are not found when the development build option is enabled. + +## 5.2.1 + +Release Date: 2024-4-7. + +### Runtime + +- [fix] Fixes the bug where stack logs are not printed on the WebGL platform. +- [fix] Fixes the bug where `RuntimeConfig::GetRuntimeOption` incorrectly returns `s_threadFrameStackSize` for `InterpreterThreadExceptionFlowSize`. + +### Editor + +- [opt] Sets `mod.EnableTypeDefFindCache = true` in `LoadModule`, reducing the time to calculate bridge functions to one-third of the original. +- [fix] Fixes the bug where renaming the xcode project file to `Tuanjie-iPhone.xcodeproj` when exporting for the Unity Engine platform causes xcode project construction to fail. + +## 5.2.0 + +Release Date: 2024-3-25. + +### Runtime + +- [new] Supports the Unity Engine. +- [new] Supports function pointers, supporting IL2CPP_TYPE_FNPTR type. +- [fix] Fixes the bug where the `SetMdArrElementVarVar_ref` instruction does not SetWriteBarrier. +- [fix] Fixes the bug where `InvokeSingleDelegate` crashes when calling a generic function without supplementary metadata. +- [fix] Fixes the bug where `InterpreterDelegateInvoke` crashes when calling a delegate pointing to a generic function without supplementary metadata. +- [fix] Fixes the bug where `RawImage::GetBlobFromRawIndex` fails when the BlobStream is empty. +- [change] Refactorizes the metadata index design, allowing up to 3 64M dlls, 16 16M dlls, 64 4M dlls, and 255 1M dlls to be allocated. + +### Editor + +- [new] Supports the Unity Engine. +- [fix] Fixes the bug where `GenericArgumentContext` does not support `ElementType.FnPtr`. +- [change] Adds the `[Preserve]` attribute to RuntimeApi to prevent it from being pruned. + +## 5.1.0 + +Release Date: 2024-2-26. + +### Runtime + +- [fix] Fixes the runtime error caused by not implementing `System.ByReference`1's .ctor and get_Value functions in 2021, where il2cpp runs normally through special instinct functions. +- [opt] Optimizes metadata loading by delaying the loading of some metadata, reducing the execution time of `Assembly::Load` by approximately 30%. +- [change] Changes `tempRet` from a local variable in `Interpreter::Execute` to a local variable in `CallDelegateInvoke_xxx`, reducing the possibility of stack overflow when nesting is too deep. + +## 5.0.0 + +Release Date: 2024-1-26. + +### Runtime + +- [new] Restores support for 2019. +- [fix] Fixes the bug where dlls are not loaded in dependency order, and since the assembly list at the time of image creation is cached, if dependent assemblies are loaded after this assembly, delayed access may result in `TypeLoadedException` due to not being in the cached assembly list. + +### Editor + +- [new] Restores support for 2019. +- [new] Supports building 2019 on the iOS platform in source form. +- [new] Adds AOTAssemblyMetadataStripper to remove non-generic function metadata from AOT dlls. +- [new] Adds MissingMetadataChecker to check for missing types or function metadata. +- [opt] Optimizes AOTReference calculations; if all generic parameters of a generic are class-constrained, they are not added to the set of metadata that needs to be supplemented. +- [change] Makes some adjustments to support the Unity Engine (note that the il2cpp_plus branch supporting the Unity Engine has not been made public). + +## 4.0.15 + +Release Date: 2024-1-2. + +### Runtime + +- [fix] Fixes the serious bug where the size of the instance of a not fully instantiated generic class is calculated as `sizeof(void*)`, resulting in an invalid and excessively large instance. This causes an error when using the generic base class instance to overwrite the instance type value set during `LayoutFieldsLocked` in `UpdateInstanceSizeForGenericClass`. +- [change] Supports printing hot update stacks, although the order is not quite correct. +- [change] Replaces IL2CPP_MALLOC with HYBRIDCLR_MALLOC and similar allocation functions. +- [refactor] Refactorizes the Config interface to缁熶竴ly retrieve and set options through `GetRuntimeOption` and `SetRuntimeOption`. +- [opt] Removes unnecessary memset operations on structures for `NewValueTypeVar` and `NewValueTypeInterpVar` instructions. + +### Editor + +- [fix] Fixes the bug where entering `-nullable:enable` in Additional Compiler Arguments throws an `InvalidCastException` in the Editor. Reported at https://github.com/focus-creative-games/hybridclr/issues/116 +- [fix] Fixes the error: `BuildFailedException: Build path contains a project previously built without the "Create Visual Studio Solution"` +- [opt] Optimizes bridge function generation by mapping isomorphic structs to the same structure, reducing the number of bridge functions by 30-35%. +- [change] `StripAOTDllCommand` no longer sets the `BuildScriptsOnly` option when exporting. +- [change] Adjusts the display content of the Installer window. +- [refactor] Centralizes the functionality of setting hybridclr parameters in RuntimeApi through `GetRuntimeOption` and `SetRuntimeOption` functions. + +## 4.0.14 + +Release Date: 2023-12-11. + +### Runtime + +- [fix] Fixes the bug where optimizing the `box; brtrue|brfalse` sequence unconditionally converts to an unconditional branch statement when the type is a class or nullable type. +- [fix] Fixes the bug where `ClassFieldLayoutCalculator` does not release value objects in each key-value pair of `_classMap`, causing a memory leak. +- [fix] Fixes the bug where calculating the native_size of a struct with `ExplicitLayout` is incorrect. +- [fix] Fixes the bug where when there are virtual functions with identical signatures and virtual generic functions, the override calculation does not consider the generic signature, incorrectly returning a non-matching function, resulting in an incorrect vtable. +- [fix][2021] Fixes the bug where when the faster (smaller) build option is enabled, some fully generic shared AOT functions do not use supplementary metadata to set function pointers, causing errors when called. + +## 4.0.13 + +Release Date: 2023-11-27. + +### Runtime + +- [fix] Fixes the bug where `ConvertInvokeArgs` might pass non-aligned args, causing `CopyStackObject` to crash on platforms like armv7 that require memory alignment. +- [fix] Fixes the serious bug where calculating `ClassFieldLayout` when the size is specified by `StructLayout`. +- [fix] Fixes the bug where instructions like `bgt` do not double-negate the judgment, causing incorrect branch execution when comparing floating-point numbers with NaN due to涓嶅绉版��. +- [fix] Fixes the serious bug where `Class::FromGenericParameter` incorrectly sets `thread_static_fields_size=-1`, causing ThreadStatic memory allocation for it. +- [opt] Allocates `Il2CppGenericInst`缁熶竴ly using `MetadataCache::GetGenericInst` to allocate unique pool objects, optimizing memory allocation. +- [opt] Since some Il2CppGenericInst in the Interpreter uses `MetadataCache::GetGenericInst` uniformly, compare `Il2CppGenericContext` by directly comparing class_inst and method_inst pointers. + +### Editor + +- [fix] Fixes the bug where pruning aot dll results in an exception when generating bridge functions if netstandard is referenced. +- [fix] Fixes the bug where unusual field names result in compilation errors in the generated bridge function code files. +- [change] Removes the unnecessaryDatas~/Templates directory, using the original files as templates directly. +- [refactor] Refactorizes `AssemblyCache` and `AssemblyReferenceDeepCollector` to eliminate redundant code. + +## 4.0.12 + +Release Date: 2023-11-02. + +### Editor + +- [fix] Fixes the bug in `BashUtil.RemoveDir` causing Installer installation to fail. + +## 4.0.11 + +Release Date: 2023-11-02. + +### Runtime + +- [fix] Fixes the bug where when full generic sharing is enabled, for some `MethodInfo`, since `methodPointer` and `virtualMethodPointer` use the interpreter function with supplementary metadata, while `invoker_method` remains in the call form supporting full generic sharing, causing `invoker_method` to mismatch with `methodPointer` and `virtualMethodPointer`. +- [fix] Fixes the bug where `Il2CppGenericContextCompare` only compares inst pointers, causing a large number of duplicate generic functions in the hot update module. +- [fix] Fixes the bug where `MethodInfo` is not correctly set when full generic sharing is enabled. + +### Editor + +- [new] Checks if the currently installed libil2cpp version matches the package version to avoid issues when upgrading the package without reinstalling. +- [new] `Generate` supports netstandard. +- [fix] Fixes the bug where `ReversePInvokeWrap` generates unnecessarily, parsing referenced dlls, causing parsing errors if aot dll references netstandard. +- [fix] Fixes the bug where `BashUtil.RemoveDir` occasionally fails to delete directories. Adds multiple retries. +- [fix] Fixes the bug where bridge function calculation does not reduce function parameter types, resulting in multiple functions with the same signature. + +## 4.0.10 + +Release Date: 2023-10-12. + +### Runtime + +- [merge][il2cpp] Merges il2cpp changes from versions 2022.3.10 to 2022.3.11f1, fixing incompatibility issues with version 2022.3.11. + +## 4.0.9 + +Release Date: 2023-10-11. + +### Runtime + +- [merge][il2cpp][fix] Merges il2cpp changes from versions 2021.3.29 to 2021.3.31f1, fixing incompatibility issues with version 2021.3.31. +- [merge][il2cpp] Merges il2cpp changes from versions 2022.3.7 to 2022.3.10f1. + +### Editor + +- [fix] Fixes the compilation error with `AddLil2cppSourceCodeToXcodeproj2022OrNewer` on the iOS platform for Unity 2022 versions. + +## 4.0.8 + +Release Date: 2023-10-10. + +### Runtime + +- [fix] Fixes the bug where calculating the bridge function signature for value type generic bridge functions incorrectly replaces the value type generic parameter type with the signature, resulting in an inconsistent signature with the Editor calculation. +- [fix][refactor] Changes RuntimeApi related functions from PInvoke to InternalCall, solving the issue of reloading libil2cpp.a when calling RuntimeApi on Android platforms. + +### Editor + +- [refactor] Changes RuntimeApi related functions from PInvoke to InternalCall . +- [refactor] Adjusts some non-standard namespace names in the HybridCLR.Editor module. + +## 4.0.7 + +Release Date: 2023-10-09. + +### Runtime + +- [fix] Fixes the bug where `initobj` calls `CopyN`, but `CopyN` does not consider object memory alignment, which may cause unaligned access exceptions on platforms like 32-bit. +- [fix] Fixes the bug where calculating the bridge function signature for not fully instantiated generic functions crashes. +- [fix] Fixes the bug where `GenericMethod::CreateMethodLocked` has issues when the Il2cpp code generation option is faster (smaller) for versions 2021 and 2022. +- [remove] Removes all array-related instructions with int64_t indices to simplify the code. +- [remove] Removes the `ldfld_xxx_ref` series of instructions. + +### Editor + +- [fix] Fixes the bug where generating bridge functions does not generate bridge functions for an aot assembly if the hot update assembly does not directly reference any code, resulting in a `NotSupportNative2Managed` exception. +- [fix] Fixes the bug where copying files fails on Mac due to excessively long paths. +- [fix] Fixes the bug where publishing for PS5 targets does not process `ScriptingAssemblies.json`. +- [change] Clears the pruned aot dll directory when packaging. + +## 4.0.6 + +Release Date: 2023-09-26. + +### Runtime + +- [fix] Fixes the bug with versions 2021 and 2022 when full generic sharing is enabled. +- [fix] Fixes the bug where loading a PlaceHolder Assembly does not increase `assemblyVersion`, causing `Assembly::GetAssemblies()` to incorrectly obtain an old assembly list. + +## 4.0.5 + +Release Date: 2023-09-25. + +### Runtime + +- [fix] Fixes the bug where `Transform` does not destruct `pendingFlows`, causing a memory leak. +- [fix] Fixes the bug where `SetMdArrElement` does not distinguish between structures with and without ref. +- [fix] Fixes the bug where `CpobjVarVAr_WriteBarrier_n_4` does not set the size. +- [fix] Fixes the bug where calculating interface member function slots does not consider static and similar functions. +- [fix] Fixes the bug where `ExplicitLayout` is not set for layout.alignment in version 2022, resulting in a size of 0. +- [fix] Fixes the bug where `InterpreterInvoke` in full generic sharing may have inconsistent `methodPointer` and `virtualMethodPointer` for class types, causing an error in incrementing the this pointer by 1. +- [fix] Fixes the bug where `ldobj` does not expand data into an int when T is a type like byte with a size less than 4. +- [fix] Fixes the bug where `CopySize` does not consider memory alignment issues. +- [opt] Optimizes `stelem` when the element is a larger struct, unifying it as a structure containing ref. +- [opt] Adjusts the default memory block size of `TemporaryMemoryArena` from 1M to 8K. +- [opt] Changes `Assembly::GetAllAssemblies()` in `Image::Image` to `Assembly::GetAllAssemblies(AssemblyVector&)`, avoiding the creation of an assembly snapshot and preventing unnecessary memory leaks. + +### Editor + +- [fix] Fixes the bug where `DllImport` for the StandaloneLinux platform has incorrect dllName and pruned dll path errors. +- [change] For Unity versions with minor incompatibility, installation is no longer prohibited, but a warning is displayed instead. +- [fix] Fixes the bug where `MetaUtil.ToShareTypeSig` calculates `Ptr` and `ByRef` as `IntPtr` in bridge function calculations, which should correctly be `UIntPtr`. + +## 4.0.4 + +Release Date: 2023-09-11. + +### Runtime + +- [new][platform] Fully supports all platforms, including UWP and PS5. +- [fix][serious] Fixes the bug where calculating the bridge function signature for interpreter parts of enum types is incorrect. +- [fix] Fixes compilation errors on some platforms. +- [fix] Fixes the bug where converting STOBJ instructions does not correctly handle incremental GC. +- [fix] Fixes the bug where the `StindVarVar_ref` instruction does not correctly set WriteBarrier. +- [fix] Fixes the thread safety issue where `GenericMethod::CreateMethodLocked` calls `vm::MetadataAllocGenericMethod()` without holding the `s_GenericMethodMutex` lock in version 2020. + +### Editor + +- [fix] Fixes the bug where `AddLil2cppSourceCodeToXcodeproj2021OrOlder` includes two ThreadPool.cpp files in different directories, causing compilation errors in Unity 2020. +- [fix] Fixes the bug where obtaining `BuildGroupTarget` from `EditorUserBuildSettings.selectedBuildTargetGroup` is incorrect. +- [fix] `StripAOTDllCommand` generates AOT dlls with the current Player settings to avoid serious mismatches between supplementary metadata and bridge function generation when packaging with development enabled. +- [change] To better support all platforms, adjusts the implementation of dllName in RuntimeApi.cs to default to `__Internal`. +- [change] To better support all platforms, all AOT dll pruning since 2021 is done through MonoHook copying. + +## 4.0.3 + +Release Date: 2023-08-31. + +### Editor + +- [fix] Fixes the bug in bridge function calculation. + +## 4.0.2 + +Release Date: 2023-08-29. + +### Runtime + +- [fix][serious] Fixes the bug in `LdobjVarVar_ref` instruction. This bug was introduced by incremental GC code. +- [fix] Fixes the bug where `ResolveField` obtaining a Field as nullptr is not handled, causing a crash. +- [fix] Fixes the bug where AOT and interpreter interface explicitly implement parent interface functions are not correctly handled. + +## 4.0.1 + +Release Date: 2023-08-28. + +### Runtime + +- [fix] Fixes the compilation error when incremental GC is enabled in version 2020. + +## 4.0.0 + +Release Date: 2023-08-28. + +### Runtime + +- [new] Supports incremental GC. +- [refactor] Refactorizes bridge functions to fully support all platforms supported by il2cpp. +- [opt] Significantly optimizes Native2Managed direction parameter passing. + +### Editor + +- [change] Removes incremental GC option checks. +- [refactor] Refactorizes bridge function generation. + +## 3.4.2 + +Release Date: 2023-08-14. + +### Runtime + +- [fix] Fixes the bug in `RawImage::LoadTables` reading `_4byteGUIDIndex`. +- [version] Supports version 2022.3.7. +- [version] Supports version 2021.3.29. + +### Editor + +- [fix] Fixes the bug where calculating AOTGenericReference does not consider generic calls on generics, resulting in fewer calculated generics and supplementary metadata. + +## 3.4.1 + +Release Date: 2023-07-31. + +### Runtime + +- [fix] Fixes the memory visibility issue in `InitializeRuntimeMetadata`. +- [fix] Fixes the bug where `CustomAttribute` does not correctly handle parent NamedArg, causing a crash. +- [opt] Optimizes the code for Transform Instinct instructions, quickly looking up in the HashMap instead of matching one by one. + +### Editor + +- [fix] Fixes the bug where `FilterHotFixAssemblies` only compares the tail of the assembly name, causing an assembly to be unexpectedly filtered if it matches the tail of an AOT assembly. +- [change] Checks that the assembly name in the hot update assembly list configuration in Settings is not empty. + +## 3.4.0 + +Release Date: 2023-07-17. + +### Runtime + +- [version] Supports versions 2021.3.28 and 2022.3.4. +- [opt] Removes unnecessary memset after allocating `_StackBase` in `MachineState::InitEvalStack`. +- [fix] Fixes the exception mechanism bug. +- [fix] Fixes the bug where `CustomAttribute` does not support Type[] type parameters. +- [fix] Fixes the issue where the new string(xxx) syntax is not supported. +- [refactor] Refactorizes VTableSetup implementation. +- [fix] Fixes the bug where functions explicitly implementing parent interfaces in subinterfaces are not calculated. +- [opt] Lazily initializes `CustomAttributeData` instead of initializing all at load time, significantly reducing `Assembly.Load` time. +- [fix] Fixes the bug where new byte[]{a,b,c...} initialization of longer byte[] data returns incorrect data in version 2022. + +### Editor + +- [fix] Fixes the bug where calculating bridge functions does not consider Native2Managed calls that may be included in generic class member functions. +- [change] The default output paths for link.xml and AOTGenericReferences.cs are changed to HybridCLRGenerate to avoid confusion with the top-level HybridCLRData. +- [fix] Fixes the bug where the include path in the lump file generated on Windows uses \ as the directory separator, causing path not found errors when synchronized to Mac. +- [refactor] Refactorizes the Installer. + +## 3.3.0 + +Release Date: 2023-07-03. + +### Runtime + +- [fix] Fixes the bug where memory allocated by localloc is not released. +- [change] `MachineState` uses RegisterRoot to register the execution stack, avoiding GC scanning of the entire stack. +- [opt] Optimizes the performance of Managed2NativeCallByReflectionInvoke by calculating the parameter passing method in advance. +- [refactor] Refactorizes ConvertInvokeArgs. + +### Editor + +- [fix] Fixes the bug where compiling libil2cpp.a for 2020-2021 does not include brotli-related code files, resulting in compilation errors. +- [fix] Fixes the bug where exporting an xcode project includes absolute paths, causing path not found errors when compiled on other machines. +- [fix] Solves the instability issues in generating LinkXml, MethodBridge, AOTGenericReference, and ReversePInvokeWrap. +- [fix] Fixes the exception when opening the Installer with an incompatible version. +- [change] When hybridclr is disabled, packaging iOS no longer modifies the exported xcode project. + +## 3.2.1 + +### Runtime + +- [fix] Fixes the bug where il2cpp TypeNameParser does not remove escape characters '\' from type names, causing nested child types to not be found. + +### Editor + +- [new] The Installer interface adds display of package version. +- [new] CompileDll adds MacOS, Linux, and WebGL targets. +- [fix] Fixes the help documentation link errors after refactoring the documentation site. +- [change] Adds using qualifiers to Analyzer to resolve compilation conflicts with project types that have the same name. + +## 3.2.0 + +### Runtime + +- [fix] Fixes the bug where if an Assembly is not in the PlaceHolder, and there is no interpreter stack, `Class::resolve_parse_info_internal` cannot find the type due to not being in the Assembly list. + +### Editor + +- [new] Supports packaging iOS directly from source code, no longer needing to compile libil2cpp.a separately. +- [opt] Optimizes error prompts for incompatible versions, no longer throwing exceptions, but displaying "incompatible with the current version". + +## 3.1.1 + +### Runtime + +- [fix] Fixes the bug where InterpreterModule::Managed2NativeCallByReflectionInvoke calls value type member functions in 2021 and higher versions, with an extra this=this-1 operation. +- [fix] Fixes the bug where parsing CustomAttribute Enum[] type fields. +- [fix] Fixes the bug where invoking the Invoke function of a closed Delegate via reflection in 2021 and higher versions does not repair the target pointer. + +### Editor + +- [fix] Fixes compilation errors for Win32, Android32, and WebGL platforms. +- [fix] Fixes the bug where calculating bridge functions does not consider supplementary metadata generic instantiation, which may access some non-public functions, resulting in fewer necessary bridge functions being generated. +- [opt] When generating AOTGenericReferences, the supplementary metadata assembly list is changed from comments to List<string> lists for easy direct use in code. +- [change] CheckSettings no longer automatically sets Api Compatible Level. + +## 3.1.0 + +### Runtime + +- [rollback] Reverts support for Unity 2020.3.x. +- [fix] Fixes the WebGL platform ABI bug. + +### Editor + +- [rollback] Reverts support for Unity 2020.3.x. + +## 3.0.3 + +### Runtime + +- [fix] Fixes the bug where Enum::GetValues returns incorrect values. + +## 3.0.2 + +### Runtime + +- [fix] Fixes the bug where creating a memory snapshot in Memory Profiler crashes. + +### Editor + +- [remove] Removes the `HybridCLR/CreateAOTDllSnapshot` menu. + +## 3.0.1 + +### Runtime + +- [new] Supports version 2022.3.0. + +## 3.0.0 + +### Runtime + +- [fix] Fixes the bug where accessing CustomData fields and values is not supported. +- [remove] Removes support for 2019 and 2020 versions. + +### Editor + +- Changes the package name to com.code-philosophy.hybridclr. +- Removes the UnityFS plugin. +- Removes the Zip plugin. +- Adjusts the HybridCLR menu location. + +## 2.4.2 + +### Runtime + +- [version] Supports 2020.3.48, the last 2020 LTS version. +- [version] Supports 2021.3.25. + +## 2.4.1 + +### Runtime + +### Editor + +- [fix] Fixes the閬楁紡 RELEASELOG.md.meta file issue. + +## 2.4.0 + +### Runtime + +### Editor + +- [new] CheckSettings checks ScriptingBackend and ApiCompatibleLevel, switching to the correct values. +- [new] Adds MsvcStdextWorkaround.cs to solve stdext compilation errors in 2020 vs. +- [fix] Fixes the bug where calculating bridge function signatures for structs containing only one float or double field is incorrect on arm64. + +## 2.3.1 + +### Runtime + +### Editor + +- [fix] Fixes the bug where copying libil2cpp locally still downloads and installs from the repository. + +## 2.3.0 + +### Runtime + +### Editor + +- [new] The Installer supports copying modified libil2cpp from a local directory. +- [fix] Fixes the bug where the MonoBleedingEdge subdirectory in version 2019 includes files with excessively long paths, causing the Installer to fail when copying files. + + + + diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/RELEASELOG.md.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/RELEASELOG.md.meta new file mode 100644 index 0000000..47abd21 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/RELEASELOG.md.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 8e53ce54bd8e88c4785c625555308dba +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Runtime.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Runtime.meta new file mode 100644 index 0000000..d5e99d3 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Runtime.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a6d5e365e1b7d9742bee023ea54b31f2 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Runtime/HomologousImageMode.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Runtime/HomologousImageMode.cs new file mode 100644 index 0000000..f244856 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Runtime/HomologousImageMode.cs @@ -0,0 +1,10 @@ +锘� +namespace HybridCLR +{ + public enum HomologousImageMode + { + Consistent, + SuperSet, + } +} + diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Runtime/HomologousImageMode.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Runtime/HomologousImageMode.cs.meta new file mode 100644 index 0000000..dde78bf --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Runtime/HomologousImageMode.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0f0351553ad90e74aa586746b5965ded +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Runtime/HybridCLR.Runtime.asmdef b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Runtime/HybridCLR.Runtime.asmdef new file mode 100644 index 0000000..98f5d3e --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Runtime/HybridCLR.Runtime.asmdef @@ -0,0 +1,14 @@ +{ + "name": "HybridCLR.Runtime", + "rootNamespace": "", + "references": [], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": true, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +} \ No newline at end of file diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Runtime/HybridCLR.Runtime.asmdef.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Runtime/HybridCLR.Runtime.asmdef.meta new file mode 100644 index 0000000..c73a6d4 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Runtime/HybridCLR.Runtime.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 13ba8ce62aa80c74598530029cb2d649 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Runtime/LoadImageErrorCode.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Runtime/LoadImageErrorCode.cs new file mode 100644 index 0000000..93d4b38 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Runtime/LoadImageErrorCode.cs @@ -0,0 +1,16 @@ +锘� +namespace HybridCLR +{ + public enum LoadImageErrorCode + { + OK = 0, + BAD_IMAGE, // invalid dll file + NOT_IMPLEMENT, // not implement feature + AOT_ASSEMBLY_NOT_FIND, // AOT assembly not found + HOMOLOGOUS_ONLY_SUPPORT_AOT_ASSEMBLY, // can not load supplementary metadata assembly for non-AOT assembly + HOMOLOGOUS_ASSEMBLY_HAS_LOADED, // can not load supplementary metadata assembly for the same assembly + INVALID_HOMOLOGOUS_MODE, // invalid homologous image mode + PDB_BAD_FILE, // invalid pdb file + }; +} + diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Runtime/LoadImageErrorCode.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Runtime/LoadImageErrorCode.cs.meta new file mode 100644 index 0000000..4f77029 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Runtime/LoadImageErrorCode.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2c7d5b71981fba643b4c21ed01bcb675 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Runtime/ReversePInvokeWrapperGenerationAttribute.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Runtime/ReversePInvokeWrapperGenerationAttribute.cs new file mode 100644 index 0000000..3308313 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Runtime/ReversePInvokeWrapperGenerationAttribute.cs @@ -0,0 +1,19 @@ +锘縰sing System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace HybridCLR +{ + [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] + public class ReversePInvokeWrapperGenerationAttribute : Attribute + { + public int ReserveWrapperCount { get; } + + public ReversePInvokeWrapperGenerationAttribute(int reserveWrapperCount) + { + ReserveWrapperCount = reserveWrapperCount; + } + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Runtime/ReversePInvokeWrapperGenerationAttribute.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Runtime/ReversePInvokeWrapperGenerationAttribute.cs.meta new file mode 100644 index 0000000..a46bd5a --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Runtime/ReversePInvokeWrapperGenerationAttribute.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f99dd22d9d81b2540b4663b3bcdf0a79 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Runtime/RuntimeApi.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Runtime/RuntimeApi.cs new file mode 100644 index 0000000..1ee67bb --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Runtime/RuntimeApi.cs @@ -0,0 +1,139 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; +using UnityEditor; +using UnityEngine.Scripting; + +namespace HybridCLR +{ + [Preserve] + public static class RuntimeApi + { + /// <summary> + /// load supplementary metadata assembly + /// </summary> + /// <param name="dllBytes"></param> + /// <returns></returns> + /// <exception cref="NotSupportedException"></exception> +#if UNITY_EDITOR + public static unsafe LoadImageErrorCode LoadMetadataForAOTAssembly(byte[] dllBytes, HomologousImageMode mode) + { + return LoadImageErrorCode.OK; + } +#else + [MethodImpl(MethodImplOptions.InternalCall)] + public static extern LoadImageErrorCode LoadMetadataForAOTAssembly(byte[] dllBytes, HomologousImageMode mode); +#endif + + /// <summary> + /// prejit method to avoid the jit cost of first time running + /// </summary> + /// <param name="method"></param> + /// <returns>return true if method is jited, return false if method can't be jited </returns> + /// +#if UNITY_EDITOR + public static bool PreJitMethod(MethodInfo method) + { + return false; + } +#else + [MethodImpl(MethodImplOptions.InternalCall)] + public static extern bool PreJitMethod(MethodInfo method); +#endif + + /// <summary> + /// prejit all methods of class to avoid the jit cost of first time running + /// </summary> + /// <param name="type"></param> + /// <returns>return true if class is jited, return false if class can't be jited </returns> +#if UNITY_EDITOR + public static bool PreJitClass(Type type) + { + return false; + } +#else + [MethodImpl(MethodImplOptions.InternalCall)] + public static extern bool PreJitClass(Type type); +#endif + + /// <summary> + /// get the maximum number of StackObjects in the interpreter thread stack (size*8 represents the final memory size occupied + /// </summary> + /// <returns></returns> + public static int GetInterpreterThreadObjectStackSize() + { + return GetRuntimeOption(RuntimeOptionId.InterpreterThreadObjectStackSize); + } + + /// <summary> + /// set the maximum number of StackObjects for the interpreter thread stack (size*8 represents the final memory size occupied) + /// </summary> + /// <param name="size"></param> + public static void SetInterpreterThreadObjectStackSize(int size) + { + SetRuntimeOption(RuntimeOptionId.InterpreterThreadObjectStackSize, size); + } + + + /// <summary> + /// get the number of interpreter thread function frames (sizeof(InterpreterFrame)*size represents the final memory size occupied) + /// </summary> + /// <returns></returns> + public static int GetInterpreterThreadFrameStackSize() + { + return GetRuntimeOption(RuntimeOptionId.InterpreterThreadFrameStackSize); + } + + /// <summary> + /// set the number of interpreter thread function frames (sizeof(InterpreterFrame)*size represents the final memory size occupied) + /// </summary> + /// <param name="size"></param> + public static void SetInterpreterThreadFrameStackSize(int size) + { + SetRuntimeOption(RuntimeOptionId.InterpreterThreadFrameStackSize, size); + } + + +#if UNITY_EDITOR + + private static readonly Dictionary<RuntimeOptionId, int> s_runtimeOptions = new Dictionary<RuntimeOptionId, int>(); + + /// <summary> + /// set runtime option value + /// </summary> + /// <param name="optionId"></param> + /// <param name="value"></param> + public static void SetRuntimeOption(RuntimeOptionId optionId, int value) + { + s_runtimeOptions[optionId] = value; + } +#else + [MethodImpl(MethodImplOptions.InternalCall)] + public static extern void SetRuntimeOption(RuntimeOptionId optionId, int value); +#endif + + /// <summary> + /// get runtime option value + /// </summary> + /// <param name="optionId"></param> + /// <returns></returns> +#if UNITY_EDITOR + public static int GetRuntimeOption(RuntimeOptionId optionId) + { + if (s_runtimeOptions.TryGetValue(optionId, out var value)) + { + return value; + } + return 0; + } +#else + [MethodImpl(MethodImplOptions.InternalCall)] + public static extern int GetRuntimeOption(RuntimeOptionId optionId); +#endif + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Runtime/RuntimeApi.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Runtime/RuntimeApi.cs.meta new file mode 100644 index 0000000..6ed5cdc --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Runtime/RuntimeApi.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0d58bdc22b6d6b54ab6791baf16a0a3d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Runtime/RuntimeOptionId.cs b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Runtime/RuntimeOptionId.cs new file mode 100644 index 0000000..25c3417 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Runtime/RuntimeOptionId.cs @@ -0,0 +1,12 @@ +锘縩amespace HybridCLR +{ + public enum RuntimeOptionId + { + InterpreterThreadObjectStackSize = 1, + InterpreterThreadFrameStackSize = 2, + ThreadExceptionFlowSize = 3, + MaxMethodBodyCacheSize = 4, + MaxMethodInlineDepth = 5, + MaxInlineableMethodBodySize = 6, + } +} diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Runtime/RuntimeOptionId.cs.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Runtime/RuntimeOptionId.cs.meta new file mode 100644 index 0000000..9c7181e --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/Runtime/RuntimeOptionId.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 64be598b47302644a96013c74d945653 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/package.json b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/package.json new file mode 100644 index 0000000..4e39f57 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/package.json @@ -0,0 +1,22 @@ +{ + "name": "com.code-philosophy.hybridclr", + "version": "7.9.0", + "displayName": "HybridCLR", + "description": "HybridCLR is a fully featured, zero-cost, high-performance, low-memory solution for Unity's all-platform native c# hotupdate.", + "category": "Runtime", + "documentationUrl": "https://hybridclr.doc.code-philosophy.com/#/", + "changelogUrl": "https://hybridclr.doc.code-philosophy.com/#/other/changelog", + "licensesUrl": "https://github.com/focus-creative-games/hybridclr_unity/blob/main/LICENSE", + "keywords": [ + "HybridCLR", + "hotupdate", + "hotfix", + "focus-creative-games", + "code-philosophy" + ], + "author": { + "name": "Code Philosophy", + "email": "hybridclr@code-philosophy.com", + "url": "https://code-philosophy.com" + } +} \ No newline at end of file diff --git a/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/package.json.meta b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/package.json.meta new file mode 100644 index 0000000..65ee986 --- /dev/null +++ b/Library/PackageCache/com.code-philosophy.hybridclr@903cf9faa2/package.json.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 8ea8eca3a387d9d4988a2fca1036f2e7 +PackageManifestImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: -- Gitblit v1.8.0