124 lines
4.0 KiB
C++
124 lines
4.0 KiB
C++
#pragma once
|
|
|
|
#include <string>
|
|
#include <vector>
|
|
#include <map>
|
|
#include <cstdint>
|
|
|
|
#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<std::string, uintptr_t>& GetIl2cppAddressMap() {
|
|
static std::map<std::string, uintptr_t> 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 <typename Return, typename... Args>
|
|
auto InvokeAddress(uintptr_t address, Args... args) -> Return {
|
|
return reinterpret_cast<Return(*)(Args...)>(address)(args...);
|
|
}
|
|
|
|
template <typename Return, typename... Args>
|
|
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<Return>(GetUnityBaseAddress() + it->second, args...);
|
|
}
|
|
// GakumasLocal::Log::InfoFmt("InvokeIl2cpp failed: %s", name.c_str());
|
|
|
|
// return nullptr;
|
|
if constexpr (!std::is_void_v<Return>)
|
|
{
|
|
return Return{};
|
|
}
|
|
}
|
|
|
|
struct Method {
|
|
std::string name;
|
|
std::vector<std::string> paramTypes;
|
|
int paramCount = 0;
|
|
uintptr_t address = 0;
|
|
|
|
template <typename Return, typename... Args>
|
|
auto Invoke(Args... args) -> Return {
|
|
return reinterpret_cast<Return(*)(Args...)>(address)(args...);
|
|
}
|
|
};
|
|
|
|
struct Class {
|
|
std::string assemblyName;
|
|
std::string namespaceName;
|
|
std::string className;
|
|
// methodName -> overloaded methods
|
|
std::map<std::string, std::vector<Method>> methods;
|
|
|
|
Method* GetMethod(const std::string& methodName,
|
|
const std::vector<std::string>& args = {});
|
|
|
|
// template <typename T>
|
|
static void* New(void* address) {
|
|
return InvokeIl2cpp<void*>("il2cpp_object_new", address);
|
|
}
|
|
};
|
|
|
|
// assembly -> namespace -> className -> Class
|
|
using ClassMap = std::map<std::string, std::map<std::string, std::map<std::string, Class>>>;
|
|
|
|
/// 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<std::string>& args = {});
|
|
|
|
} // namespace Il2cppJson
|