add lazy initializing

This commit is contained in:
chinosk 2024-07-05 20:34:46 +08:00
parent c810a27ba2
commit 77fc61d9da
Signed by: chinosk
GPG Key ID: 00610B08C1BF7BE9
10 changed files with 89 additions and 12 deletions

View File

@ -39,7 +39,8 @@ std::unordered_set<void*> hookedStubs{};
GakumasLocal::Log::InfoFmt("ADD_HOOK: %s at %p", #name, addr); \ GakumasLocal::Log::InfoFmt("ADD_HOOK: %s at %p", #name, addr); \
} \ } \
} \ } \
else GakumasLocal::Log::ErrorFmt("Hook failed: %s is NULL", #name, addr) else GakumasLocal::Log::ErrorFmt("Hook failed: %s is NULL", #name, addr); \
if (Config::lazyInit) UnityResolveProgress::classProgress.current++
void UnHookAll() { void UnHookAll() {
for (const auto i: hookedStubs) { for (const auto i: hookedStubs) {
@ -827,7 +828,8 @@ namespace GakumasLocal::HookMain {
void StartInjectFunctions() { void StartInjectFunctions() {
const auto hookInstaller = Plugin::GetInstance().GetHookInstaller(); const auto hookInstaller = Plugin::GetInstance().GetHookInstaller();
UnityResolve::Init(xdl_open(hookInstaller->m_il2cppLibraryPath.c_str(), RTLD_NOW), UnityResolve::Mode::Il2Cpp); UnityResolve::Init(xdl_open(hookInstaller->m_il2cppLibraryPath.c_str(), RTLD_NOW),
UnityResolve::Mode::Il2Cpp, Config::lazyInit);
ADD_HOOK(AssetBundle_LoadAssetAsync, Il2cppUtils::il2cpp_resolve_icall( ADD_HOOK(AssetBundle_LoadAssetAsync, Il2cppUtils::il2cpp_resolve_icall(
"UnityEngine.AssetBundle::LoadAssetAsync_Internal(System.String,System.Type)")); "UnityEngine.AssetBundle::LoadAssetAsync_Internal(System.String,System.Type)"));
@ -959,10 +961,30 @@ namespace GakumasLocal::HookMain {
Log::Info("Start init plugin..."); Log::Info("Start init plugin...");
if (Config::lazyInit) {
UnityResolveProgress::startInit = true;
UnityResolveProgress::assembliesProgress.total = 2;
UnityResolveProgress::assembliesProgress.current = 1;
UnityResolveProgress::classProgress.total = 36;
UnityResolveProgress::classProgress.current = 0;
}
StartInjectFunctions(); StartInjectFunctions();
GKCamera::initCameraSettings(); GKCamera::initCameraSettings();
if (Config::lazyInit) {
UnityResolveProgress::assembliesProgress.current = 2;
UnityResolveProgress::classProgress.total = 1;
UnityResolveProgress::classProgress.current = 0;
}
Local::LoadData(); Local::LoadData();
if (Config::lazyInit) {
UnityResolveProgress::classProgress.current = 1;
UnityResolveProgress::startInit = false;
}
Log::Info("Plugin init finished."); Log::Info("Plugin init finished.");
return ret; return ret;
} }

View File

@ -7,6 +7,7 @@ namespace GakumasLocal::Config {
bool dbgMode = false; bool dbgMode = false;
bool enabled = true; bool enabled = true;
bool lazyInit = true;
bool replaceFont = true; bool replaceFont = true;
bool forceExportResource = true; bool forceExportResource = true;
bool textTest = false; bool textTest = false;
@ -55,6 +56,7 @@ namespace GakumasLocal::Config {
GetConfigItem(dbgMode); GetConfigItem(dbgMode);
GetConfigItem(enabled); GetConfigItem(enabled);
GetConfigItem(lazyInit);
GetConfigItem(replaceFont); GetConfigItem(replaceFont);
GetConfigItem(forceExportResource); GetConfigItem(forceExportResource);
GetConfigItem(gameOrientation); GetConfigItem(gameOrientation);

View File

@ -5,6 +5,7 @@ namespace GakumasLocal::Config {
extern bool dbgMode; extern bool dbgMode;
extern bool enabled; extern bool enabled;
extern bool lazyInit;
extern bool replaceFont; extern bool replaceFont;
extern bool forceExportResource; extern bool forceExportResource;
extern int gameOrientation; extern int gameOrientation;

View File

@ -81,7 +81,15 @@ public:
[[nodiscard]] auto Get(const std::string& strClass, const std::string& strNamespace = "*", const std::string& strParent = "*") const -> Class* { [[nodiscard]] auto Get(const std::string& strClass, const std::string& strNamespace = "*", const std::string& strParent = "*") const -> Class* {
if (!this) return nullptr; if (!this) return nullptr;
/*
if (lazyInit_ && classes.empty()) {
const auto image = Invoke<void*>("il2cpp_assembly_get_image", address);
ForeachClass(const_cast<Assembly *>(this), image);
}*/
for (const auto pClass : classes) if (strClass == pClass->name && (strNamespace == "*" || pClass->namespaze == strNamespace) && (strParent == "*" || pClass->parent == strParent)) return pClass; for (const auto pClass : classes) if (strClass == pClass->name && (strNamespace == "*" || pClass->namespaze == strNamespace) && (strParent == "*" || pClass->parent == strParent)) return pClass;
if (lazyInit_) {
return FillClass_Il2ccpp(const_cast<Assembly *>(this), strNamespace.c_str(), strClass.c_str());
}
return nullptr; return nullptr;
} }
}; };
@ -291,16 +299,17 @@ public:
} }
} }
static auto Init(void* hmodule, const Mode mode = Mode::Mono) -> void { static auto Init(void* hmodule, const Mode mode = Mode::Mono, const bool lazyInit = false) -> void {
mode_ = mode; mode_ = mode;
hmodule_ = hmodule; hmodule_ = hmodule;
lazyInit_ = lazyInit;
if (mode_ == Mode::Il2Cpp) { if (mode_ == Mode::Il2Cpp) {
UnityResolveProgress::startInit = true; if (!lazyInit) UnityResolveProgress::startInit = true;
pDomain = Invoke<void*>("il2cpp_domain_get"); pDomain = Invoke<void*>("il2cpp_domain_get");
Invoke<void*>("il2cpp_thread_attach", pDomain); Invoke<void*>("il2cpp_thread_attach", pDomain);
ForeachAssembly(); ForeachAssembly();
UnityResolveProgress::startInit = false; if (!lazyInit) UnityResolveProgress::startInit = false;
} }
else { else {
pDomain = Invoke<void*>("mono_get_root_domain"); pDomain = Invoke<void*>("mono_get_root_domain");
@ -576,10 +585,10 @@ private:
size_t nrofassemblies = 0; size_t nrofassemblies = 0;
const auto assemblies = Invoke<void**>("il2cpp_domain_get_assemblies", pDomain, &nrofassemblies); const auto assemblies = Invoke<void**>("il2cpp_domain_get_assemblies", pDomain, &nrofassemblies);
UnityResolveProgress::assembliesProgress.total = nrofassemblies; if (!lazyInit_) UnityResolveProgress::assembliesProgress.total = nrofassemblies;
for (auto i = 0; i < nrofassemblies; i++) { for (auto i = 0; i < nrofassemblies; i++) {
UnityResolveProgress::assembliesProgress.current = i + 1; if (!lazyInit_) UnityResolveProgress::assembliesProgress.current = i + 1;
const auto ptr = assemblies[i]; const auto ptr = assemblies[i];
if (ptr == nullptr) continue; if (ptr == nullptr) continue;
auto assembly = new Assembly{ .address = ptr }; auto assembly = new Assembly{ .address = ptr };
@ -587,9 +596,11 @@ private:
assembly->file = Invoke<const char*>("il2cpp_image_get_filename", image); assembly->file = Invoke<const char*>("il2cpp_image_get_filename", image);
assembly->name = Invoke<const char*>("il2cpp_image_get_name", image); assembly->name = Invoke<const char*>("il2cpp_image_get_name", image);
UnityResolve::assembly.push_back(assembly); UnityResolve::assembly.push_back(assembly);
if (!lazyInit_) {
ForeachClass(assembly, image); ForeachClass(assembly, image);
} }
} }
}
else { else {
Invoke<void*, void(*)(void* ptr, std::vector<Assembly*>&), std::vector<Assembly*>&>("mono_assembly_foreach", Invoke<void*, void(*)(void* ptr, std::vector<Assembly*>&), std::vector<Assembly*>&>("mono_assembly_foreach",
[](void* ptr, std::vector<Assembly*>& v) { [](void* ptr, std::vector<Assembly*>& v) {
@ -608,13 +619,39 @@ private:
} }
} }
static auto FillClass_Il2ccpp(Assembly* assembly, const char* namespaze, const char* klassName) -> Class* {
auto image = Invoke<void*>("il2cpp_assembly_get_image", assembly->address);
const auto pClass = Invoke<void*>("il2cpp_class_from_name", image, namespaze, klassName);
if (pClass == nullptr) return nullptr;
const auto pAClass = new Class();
pAClass->address = pClass;
pAClass->name = Invoke<const char*>("il2cpp_class_get_name", pClass);
if (const auto pPClass = Invoke<void*>("il2cpp_class_get_parent", pClass)) pAClass->parent = Invoke<const char*>("il2cpp_class_get_name", pPClass);
// pAClass->namespaze = Invoke<const char*>("il2cpp_class_get_namespace", pClass);
pAClass->namespaze = namespaze;
assembly->classes.push_back(pAClass);
ForeachFields(pAClass, pClass);
ForeachMethod(pAClass, pClass);
void* i_class{};
void* iter{};
do {
if ((i_class = Invoke<void*>("il2cpp_class_get_interfaces", pClass, &iter))) {
ForeachFields(pAClass, i_class);
ForeachMethod(pAClass, i_class);
}
} while (i_class);
return pAClass;
}
static auto ForeachClass(Assembly* assembly, void* image) -> void { static auto ForeachClass(Assembly* assembly, void* image) -> void {
// 遍历类 // 遍历类
if (mode_ == Mode::Il2Cpp) { if (mode_ == Mode::Il2Cpp) {
const auto count = Invoke<int>("il2cpp_image_get_class_count", image); const auto count = Invoke<int>("il2cpp_image_get_class_count", image);
UnityResolveProgress::classProgress.total = count; if (!lazyInit_) UnityResolveProgress::classProgress.total = count;
for (auto i = 0; i < count; i++) { for (auto i = 0; i < count; i++) {
UnityResolveProgress::classProgress.current = i + 1; if (!lazyInit_) UnityResolveProgress::classProgress.current = i + 1;
const auto pClass = Invoke<void*>("il2cpp_image_get_class", image, i); const auto pClass = Invoke<void*>("il2cpp_image_get_class", image, i);
if (pClass == nullptr) continue; if (pClass == nullptr) continue;
const auto pAClass = new Class(); const auto pAClass = new Class();
@ -2606,6 +2643,7 @@ public:
private: private:
inline static Mode mode_{}; inline static Mode mode_{};
inline static void* hmodule_; inline static void* hmodule_;
inline static bool lazyInit_;
inline static std::unordered_map<std::string, void*> address_{}; inline static std::unordered_map<std::string, void*> address_{};
inline static void* pDomain{}; inline static void* pDomain{};
}; };

View File

@ -17,6 +17,7 @@ interface ConfigListener {
fun onForceExportResourceChanged(value: Boolean) fun onForceExportResourceChanged(value: Boolean)
fun onTextTestChanged(value: Boolean) fun onTextTestChanged(value: Boolean)
fun onReplaceFontChanged(value: Boolean) fun onReplaceFontChanged(value: Boolean)
fun onLazyInitChanged(value: Boolean)
fun onEnableFreeCameraChanged(value: Boolean) fun onEnableFreeCameraChanged(value: Boolean)
fun onTargetFpsChanged(s: CharSequence, start: Int, before: Int, count: Int) fun onTargetFpsChanged(s: CharSequence, start: Int, before: Int, count: Int)
fun onUnlockAllLiveChanged(value: Boolean) fun onUnlockAllLiveChanged(value: Boolean)
@ -111,6 +112,11 @@ interface ConfigUpdateListener: ConfigListener, IHasConfigItems {
pushKeyEvent(KeyEvent(1145, 30)) pushKeyEvent(KeyEvent(1145, 30))
} }
override fun onLazyInitChanged(value: Boolean) {
config.lazyInit = value
saveConfig()
}
override fun onTextTestChanged(value: Boolean) { override fun onTextTestChanged(value: Boolean) {
config.textTest = value config.textTest = value
saveConfig() saveConfig()

View File

@ -6,6 +6,7 @@ import kotlinx.serialization.Serializable
data class GakumasConfig ( data class GakumasConfig (
var dbgMode: Boolean = false, var dbgMode: Boolean = false,
var enabled: Boolean = true, var enabled: Boolean = true,
var lazyInit: Boolean = true,
var replaceFont: Boolean = true, var replaceFont: Boolean = true,
var textTest: Boolean = false, var textTest: Boolean = false,
var dumpText: Boolean = false, var dumpText: Boolean = false,

View File

@ -96,7 +96,7 @@ class InitProgressUI {
gravity = Gravity.CENTER_HORIZONTAL gravity = Gravity.CENTER_HORIZONTAL
} }
setTextColor(Color.BLACK) setTextColor(Color.BLACK)
text = "Initializing Plugins" text = "Initializing"
textSize = 20f textSize = 20f
setTypeface(typeface, Typeface.BOLD) setTypeface(typeface, Typeface.BOLD)
} }

View File

@ -141,9 +141,14 @@ fun HomePage(modifier: Modifier = Modifier,
v -> context?.onEnabledChanged(v) v -> context?.onEnabledChanged(v)
} }
GakuSwitch(modifier, stringResource(R.string.lazy_init), checked = config.value.lazyInit) {
v -> context?.onLazyInitChanged(v)
}
GakuSwitch(modifier, stringResource(R.string.replace_font), checked = config.value.replaceFont) { GakuSwitch(modifier, stringResource(R.string.replace_font), checked = config.value.replaceFont) {
v -> context?.onReplaceFontChanged(v) v -> context?.onReplaceFontChanged(v)
} }
} }
} }
Spacer(Modifier.height(6.dp)) Spacer(Modifier.height(6.dp))

View File

@ -3,6 +3,7 @@
<string name="gakumas_localify">Gakumas Localify</string> <string name="gakumas_localify">Gakumas Localify</string>
<string name="enable_plugin">启用插件 (不可热重载)</string> <string name="enable_plugin">启用插件 (不可热重载)</string>
<string name="replace_font">替换字体</string> <string name="replace_font">替换字体</string>
<string name="lazy_init">快速初始化(懒加载配置)</string>
<string name="enable_free_camera">启用自由视角(可热重载; 需使用实体键盘)</string> <string name="enable_free_camera">启用自由视角(可热重载; 需使用实体键盘)</string>
<string name="start_game">以上述配置启动游戏/重载配置</string> <string name="start_game">以上述配置启动游戏/重载配置</string>
<string name="setFpsTitle">最大 FPS (0 为保持游戏原设置)</string> <string name="setFpsTitle">最大 FPS (0 为保持游戏原设置)</string>

View File

@ -3,6 +3,7 @@
<string name="gakumas_localify">Gakumas Localify</string> <string name="gakumas_localify">Gakumas Localify</string>
<string name="enable_plugin">Enable Plugin (Not Hot Reloadable)</string> <string name="enable_plugin">Enable Plugin (Not Hot Reloadable)</string>
<string name="replace_font">Replace Font</string> <string name="replace_font">Replace Font</string>
<string name="lazy_init">Fast Initialization (Lazy loading)</string>
<string name="enable_free_camera">Enable Free Camera</string> <string name="enable_free_camera">Enable Free Camera</string>
<string name="start_game">Start Game / Hot Reload Config</string> <string name="start_game">Start Game / Hot Reload Config</string>
<string name="setFpsTitle">Max FPS (0 is Use Original Settings)</string> <string name="setFpsTitle">Max FPS (0 is Use Original Settings)</string>