#pragma once #include #include #include #include #include "GakumasLocalify/GakumasLocalify/Local.h" #include "GakumasLocalify/GakumasLocalify/Log.h" namespace Il2cppJson { // inline static uintptr_t s_baseAddress = 0; inline uintptr_t& GetUnityBaseAddress() { static uintptr_t s_baseAddress = 0; return s_baseAddress; } inline std::map& GetIl2cppAddressMap() { static std::map il2cppAddress { { "il2cpp_object_new", 0x9D710C4 }, // 2.10.1、 2.10.2 { "il2cpp_class_get_method_from_name", 0x9DCC534 }, { "il2cpp_string_new", 0x9D7110C }, { "il2cpp_class_get_field_from_name", 0x9DCC2B0 }, { "il2cpp_class_from_type", 0x9D70E30}, { "il2cpp_class_get_fields", 0x9DCC1DC }, { "il2cpp_field_static_get_value_0+1", 0x9DC8D00 }, { "il2cpp_class_from_system_type", 0x9DCC028 }, { "il2cpp_init", 0x9D70D90 }, { "il2cpp_class_from_name", 0x9DCE4A4 }, { "il2cpp_assembly_get_image", 0x7C11B50 }, { "il2cpp_domain_get", 0x9DB81AC }, { "il2cpp_domain_assembly_open", 0x9D70EE4 }, { "il2cpp_domain_assembly_open+1", 0x9DA374C }, { "il2cpp_resolve_icall", 0x9D71304 }, // il2cpp_class_get_parent // il2cpp_resolve_icall // il2cpp_class_get_nested_types // il2cpp_type_get_object // il2cpp_class_get_type // il2cpp_field_static_set_value // il2cpp_runtime_invoke // il2cpp_thread_attach // il2cpp_domain_get_assemblies // il2cpp_image_get_filename // il2cpp_image_get_name // il2cpp_image_get_class_count // il2cpp_image_get_class // ... }; return il2cppAddress; } template auto InvokeAddress(uintptr_t address, Args... args) -> Return { return reinterpret_cast(address)(args...); } template auto InvokeIl2cpp(const std::string& name, Args... args) -> Return { if (auto it = GetIl2cppAddressMap().find(name); it != GetIl2cppAddressMap().end()) { // GakumasLocal::Log::InfoFmt("InvokeIl2cpp: %s", name.c_str()); return InvokeAddress(GetUnityBaseAddress() + it->second, args...); } // GakumasLocal::Log::InfoFmt("InvokeIl2cpp failed: %s", name.c_str()); // return nullptr; if constexpr (!std::is_void_v) { return Return{}; } } struct Method { std::string name; std::vector paramTypes; int paramCount = 0; uintptr_t address = 0; template auto Invoke(Args... args) -> Return { return reinterpret_cast(address)(args...); } }; struct Class { std::string assemblyName; std::string namespaceName; std::string className; // methodName -> overloaded methods std::map> methods; Method* GetMethod(const std::string& methodName, const std::vector& args = {}); // template static void* New(void* address) { return InvokeIl2cpp("il2cpp_object_new", address); } }; // assembly -> namespace -> className -> Class using ClassMap = std::map>>; /// Initialize the parser. Must be called before any GetClass/GetMethod calls. /// @param baseAddress Runtime base address of the UnityFramework image. /// {HOME}/Documents/gakumas-localify/il2cpp.json bool Init(uintptr_t baseAddress); Class* GetClass(const std::string& assemblyName, const std::string& nameSpaceName, const std::string& className); Method* GetMethod(const std::string& assemblyName, const std::string& nameSpaceName, const std::string& className, const std::string& methodName, const std::vector& args = {}); } // namespace Il2cppJson