diff --git a/src/VERSIONINFO.rc b/src/VERSIONINFO.rc index 789728e..d66d50b 100644 --- a/src/VERSIONINFO.rc +++ b/src/VERSIONINFO.rc @@ -7,8 +7,8 @@ // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,27,0,0 - PRODUCTVERSION 1,27,0,0 + FILEVERSION 1,28,0,0 + PRODUCTVERSION 1,28,0,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -25,19 +25,19 @@ BEGIN BEGIN VALUE "LegalCopyright", "Copyright © Ji O Kim\0" VALUE "FileDescription", "우마무스메 현지화 패치\0" - VALUE "FileVersion", "1.27.0.0\0" + VALUE "FileVersion", "1.28.0.0\0" VALUE "InternalName", "umamusume-localify\0" VALUE "ProductName", "Umamusume Localify\0" - VALUE "ProductVersion", "1.27.0\0" + VALUE "ProductVersion", "1.28.0\0" END BLOCK "000004b0" BEGIN VALUE "LegalCopyright", "Copyright © Ji O Kim\0" VALUE "FileDescription", "Localization patch for Umamusume\0" - VALUE "FileVersion", "1.27.0.0\0" + VALUE "FileVersion", "1.28.0.0\0" VALUE "InternalName", "umamusume-localify\0" VALUE "ProductName", "Umamusume Localify\0" - VALUE "ProductVersion", "1.27.0\0" + VALUE "ProductVersion", "1.28.0\0" END END BLOCK "VarFileInfo" diff --git a/src/hook.cpp b/src/hook.cpp index c88824f..a049e25 100644 --- a/src/hook.cpp +++ b/src/hook.cpp @@ -4,6 +4,8 @@ #include #include +#include + #include #include @@ -19,6 +21,8 @@ #include "discord/core.h" #include "discord/activity_manager.h" +#include "libcef.h" + using namespace std; namespace @@ -79,6 +83,22 @@ namespace void Application_Quit_hook(int exitCode) { + auto StackTrace = il2cpp_symbols::get_class("mscorlib.dll", "System.Diagnostics", "StackFrame"); + auto trace = il2cpp_object_new(StackTrace); + il2cpp_class_get_method_from_name_type(trace->klass, ".ctor", 2)->methodPointer(trace, 0, false); + + auto methodRef = il2cpp_class_get_method_from_name_type(trace->klass, "GetMethod", 0)->methodPointer(trace); + + auto method = il2cpp_method_get_from_reflection(methodRef); + + if (string(method->klass->name).find("Uncheater") != string::npos || + string(method->klass->name).find("Boot") != string::npos || + string(method->name).find("Uncheater") != string::npos) + { + return; + } + + reinterpret_cast(Application_Quit_orig)(exitCode); } extern "C" NTSTATUS NtProtectVirtualMemory( @@ -130,6 +150,8 @@ namespace if (Game::CurrentGameRegion == Game::Region::KOR) { + KillProcessByName("ucldr_Umamusume_KR_loader_x64.exe"); + auto Application_Quit = il2cpp_resolve_icall("UnityEngine.Application::Quit(System.Int32)"); MH_CreateHook(Application_Quit, Application_Quit_hook, &Application_Quit_orig); MH_EnableHook(Application_Quit); @@ -147,9 +169,9 @@ namespace } void* umaFindService_orig = nullptr; - int __stdcall umaFindService_hook() + BOOL __stdcall umaFindService_hook() { - return 1; + return TRUE; } set currentPlayerHandles; @@ -172,6 +194,22 @@ namespace template Il2CppDelegate* CreateDelegateWithClass(Il2CppClass* klass, Il2CppObject* target, void (*fn)(Il2CppObject*, T...)); + void SetNotificationDisplayTime(float time) + { + if (!notification) + { + return; + } + + if (!uobject_IsNativeObjectAlive(notification)) + { + return; + } + + auto _displayTimeField = il2cpp_class_get_field_from_name_wrap(notification->klass, "_displayTime"); + il2cpp_field_set_value(notification, _displayTimeField, &time); + } + void ShowNotification(Il2CppString* text) { if (!notification) @@ -286,6 +324,7 @@ namespace } auto u8Text = local::wide_u8(text->start_char); + replaceAll(u8Text, "\n\n", " "); replaceAll(u8Text, "\n", " "); if (notification && wstring(cueSheet->start_char).find(L"_home_") == string::npos && wstring(cueSheet->start_char).find(L"_tc_") == string::npos && @@ -296,7 +335,7 @@ namespace (characterId < 9000 || voiceId == 95006 || voiceId == 70000)) { - if (wstring(cueSheet->start_char).find(L"_training_") != string::npos && cueId < 29) + if (wstring(cueSheet->start_char).find(L"_training_") != string::npos && (cueId < 29 || cueId == 39)) { if (voiceId < 93000 && !(cueId == 8 || cueId == 9 || cueId == 12 || cueId == 13)) { @@ -308,14 +347,13 @@ namespace il2cpp_symbols::get_method_pointer("umamusume.dll", "Gallop", "GallopUtil", "LineHeadWrap", 2); - auto timeField = il2cpp_class_get_field_from_name_wrap(notification->klass, "_displayTime"); - float length = il2cpp_class_get_method_from_name_type(audioManager->klass, "GetCueLength", 2)->methodPointer(audioManager, cueSheet, cueId); - il2cpp_field_set_value(notification, timeField, &length); - ShowNotification(LineHeadWrap(il2cpp_string_new(u8Text.data()), 32)); + SetNotificationDisplayTime(length); + + ShowNotification(LineHeadWrap(il2cpp_string_new(u8Text.data()), g_character_system_text_caption_line_char_count)); } } @@ -353,8 +391,7 @@ namespace { return result; } - - const regex r(R"((\d{4})(?:\d{2})*_(\d{4})*_*(\d{2})*(?:\d{2})*$)"); + const regex r(R"(_(?:9)*(\d{4})(?:\d{2})*_(\d{4})*_*(\d{2})*(?:\d{2})*$)"); smatch stringMatch; const auto cueSheet = string(info->name); const auto cueSheet16 = local::u8_wide(cueSheet); @@ -571,21 +608,126 @@ namespace } } + void* delete_cookies_orig = nullptr; + int delete_cookies_hook( + struct _cef_cookie_manager_t* self, + const cef_string_t* url, + const cef_string_t* cookie_name, + struct _cef_delete_cookies_callback_t* callback) + { + // return reinterpret_cast(delete_cookies_orig)(self, url, cookie_name, callback); + return TRUE; + } + + void* cef_cookie_manager_get_global_manager_orig = nullptr; + cef_cookie_manager_t* cef_cookie_manager_get_global_manager_hook( + struct _cef_completion_callback_t* callback) + { + auto manager = reinterpret_cast(cef_cookie_manager_get_global_manager_orig)(callback); + + if (manager) + { + auto addr = manager->delete_cookies; + + MH_CreateHook(addr, delete_cookies_hook, &delete_cookies_orig); + MH_EnableHook(addr); + } + + return manager; + } + + void* cef_initialize_orig = nullptr; + int cef_initialize_hook(const cef_main_args_t* args, + /*const*/ struct _cef_settings_t* settings, + struct _cef_app_t* application, + void* windows_sandbox_info) + { + return reinterpret_cast(cef_initialize_orig)(args, settings, application, windows_sandbox_info); + } + + void* cef_browser_host_create_browser_orig = nullptr; + int cef_browser_host_create_browser_hook( + const cef_window_info_t* windowInfo, + struct _cef_client_t* client, + const cef_string_t* url, + const struct _cef_browser_settings_t* settings, + struct _cef_dictionary_value_t* extra_info, + struct _cef_request_context_t* request_context) + { + return reinterpret_cast(cef_browser_host_create_browser_orig)(windowInfo, client, url, settings, extra_info, request_context); + } + + void* load_library_ex_w_orig = nullptr; + HMODULE + WINAPI + load_library_ex_w_hook( + _In_ LPCWSTR lpLibFileName, + _Reserved_ HANDLE hFile, + _In_ DWORD dwFlags + ) + { + if (wstring(lpLibFileName).find(L"KakaoGame.dll") != wstring::npos) + { + auto KakaoGame = reinterpret_cast(load_library_ex_w_orig)(lpLibFileName, hFile, dwFlags); + + auto cef = GetModuleHandleW(L"libcef.dll"); + + cef_initialize = reinterpret_cast(GetProcAddress(cef, "cef_initialize")); + + cef_string_wide_set = reinterpret_cast(GetProcAddress(cef, "cef_string_wide_set")); + + cef_string_utf8_set = reinterpret_cast(GetProcAddress(cef, "cef_string_utf8_set")); + + cef_string_utf16_set = reinterpret_cast(GetProcAddress(cef, "cef_string_utf16_set")); + + cef_browser_host_create_browser = reinterpret_cast(GetProcAddress(cef, "cef_browser_host_create_browser")); + + cef_string_list_alloc = reinterpret_cast(GetProcAddress(cef, "cef_string_list_alloc")); + + cef_string_list_size = reinterpret_cast(GetProcAddress(cef, "cef_string_list_size")); + + cef_string_list_value = reinterpret_cast(GetProcAddress(cef, "cef_string_list_value")); + + cef_string_list_append = reinterpret_cast(GetProcAddress(cef, "cef_string_list_append")); + + cef_string_list_clear = reinterpret_cast(GetProcAddress(cef, "cef_string_list_clear")); + + cef_string_list_free = reinterpret_cast(GetProcAddress(cef, "cef_string_list_free")); + + cef_string_list_copy = reinterpret_cast(GetProcAddress(cef, "cef_string_list_copy")); + + cef_cookie_manager_get_global_manager = reinterpret_cast(GetProcAddress(cef, "cef_cookie_manager_get_global_manager")); + + MH_CreateHook(cef_initialize, cef_initialize_hook, &cef_initialize_orig); + MH_EnableHook(cef_initialize); + + MH_CreateHook(cef_browser_host_create_browser, cef_browser_host_create_browser_hook, &cef_browser_host_create_browser_orig); + MH_EnableHook(cef_browser_host_create_browser); + + MH_CreateHook(cef_cookie_manager_get_global_manager, cef_cookie_manager_get_global_manager_hook, &cef_cookie_manager_get_global_manager_orig); + MH_EnableHook(cef_cookie_manager_get_global_manager); + + return KakaoGame; + } + + return reinterpret_cast(load_library_ex_w_orig)(lpLibFileName, hFile, dwFlags); + } + void* load_library_w_orig = nullptr; - HMODULE __stdcall load_library_w_hook(const wchar_t* path) + HMODULE WINAPI load_library_w_hook(LPCWSTR lpLibFileName) { - if (path == L"UmamusumeKr.dll"s) + if (lpLibFileName == L"UmamusumeKr.dll"s) { - const auto UmamusumeKr = reinterpret_cast(load_library_w_orig)(path); + const auto UmamusumeKr = reinterpret_cast(load_library_w_orig)(lpLibFileName); const auto umaFindService_addr = GetProcAddress(UmamusumeKr, "umaFindService"); MH_CreateHook(umaFindService_addr, umaFindService_hook, &umaFindService_orig); MH_EnableHook(umaFindService_addr); return UmamusumeKr; } - /*if (path == L"GameAssembly.dll"s) + /*if (lpLibFileName == L"GameAssembly.dll"s) { - const auto il2cpp = reinterpret_cast(load_library_w_orig)(path); + const auto il2cpp = reinterpret_cast(load_library_w_orig)(lpLibFileName); const auto il2cpp_init_addr = GetProcAddress(il2cpp, "il2cpp_init"); MH_CreateHook(il2cpp_init_addr, il2cpp_init_hook, &il2cpp_init_orig); MH_EnableHook(il2cpp_init_addr); @@ -593,7 +735,7 @@ namespace }*/ // GameAssembly.dll code must be loaded and decrypted while loading criware library - if (path == L"cri_ware_unity.dll"s) + if (lpLibFileName == L"cri_ware_unity.dll"s) { patch_after_criware(); @@ -614,7 +756,7 @@ namespace } // use original function beacuse we have unhooked that - auto criware = LoadLibraryW(path); + auto criware = LoadLibraryW(lpLibFileName); if (g_character_system_text_caption) { @@ -662,7 +804,7 @@ namespace return criware; } - return reinterpret_cast(load_library_w_orig)(path); + return reinterpret_cast(load_library_w_orig)(lpLibFileName); } FieldInfo* il2cpp_class_get_field_from_name_wrap(Il2CppClass* klass, const char* name) @@ -756,6 +898,8 @@ namespace Il2CppString* (*uobject_get_name)(Il2CppObject* uObject); + Il2CppString* (*uobject_set_name)(Il2CppObject* uObject, Il2CppString* name); + Il2CppString* (*get_unityVersion)(); void PrintStackTrace() @@ -783,6 +927,18 @@ namespace methodInfo->klass = il2cpp_symbols::get_class("mscorlib.dll", "System.Reflection", "MethodInfo"); delegate->method = methodInfo; delegate->target = target; + + auto object = reinterpret_cast(delegate); + + // auto methodInfoField = il2cpp_class_get_field_from_name_wrap(object->klass, "method_info"); + // il2cpp_field_set_value(object, methodInfoField, methodInfo); + + // auto pointerField = il2cpp_class_get_field_from_name_wrap(object->klass, "method_ptr"); + // il2cpp_field_set_value(object, pointerField, fn); + + auto targetField = il2cpp_class_get_field_from_name_wrap(object->klass, "m_target"); + il2cpp_field_set_value(object, targetField, target); + return delegate; } @@ -801,6 +957,18 @@ namespace methodInfo->klass = il2cpp_symbols::get_class("mscorlib.dll", "System.Reflection", "MethodInfo"); delegate->method = methodInfo; delegate->target = target; + + auto object = reinterpret_cast(delegate); + + // auto methodInfoField = il2cpp_class_get_field_from_name_wrap(object->klass, "method_info"); + // il2cpp_field_set_value(object, methodInfoField, methodInfo); + + // auto pointerField = il2cpp_class_get_field_from_name_wrap(object->klass, "method_ptr"); + // il2cpp_field_set_value(object, pointerField, fn); + + auto targetField = il2cpp_class_get_field_from_name_wrap(object->klass, "m_target"); + il2cpp_field_set_value(object, targetField, target); + return delegate; } @@ -819,6 +987,18 @@ namespace methodInfo->klass = il2cpp_symbols::get_class("mscorlib.dll", "System.Reflection", "MethodInfo"); delegate->method = methodInfo; delegate->target = target; + + auto object = reinterpret_cast(delegate); + + // auto methodInfoField = il2cpp_class_get_field_from_name_wrap(object->klass, "method_info"); + // il2cpp_field_set_value(object, methodInfoField, methodInfo); + + // auto pointerField = il2cpp_class_get_field_from_name_wrap(object->klass, "method_ptr"); + // il2cpp_field_set_value(object, pointerField, fn); + + auto targetField = il2cpp_class_get_field_from_name_wrap(object->klass, "m_target"); + il2cpp_field_set_value(object, targetField, target); + return delegate; } @@ -1830,7 +2010,7 @@ namespace } } - return reinterpret_cast(canvas_scaler_setres_orig)(_this, res); + reinterpret_cast(canvas_scaler_setres_orig)(_this, res); } void* UIManager_UpdateCanvasScaler_orig = nullptr; @@ -1851,7 +2031,6 @@ namespace int height1 = il2cpp_symbols::get_method_pointer("UnityEngine.CoreModule.dll", "UnityEngine", "Screen", "get_height", -1)(); float ratio1 = (float)width1 / (float)height1; - // float ratio = (float)width / (float)height; float bgCanvasScalerBaseScale = il2cpp_class_get_method_from_name_type(_this->klass, "GetBgCanvasScalerBaseScale", 2)->methodPointer(_this, renderTextureWidth, renderTextureHeight); if (is_virt()) { @@ -1865,92 +2044,40 @@ namespace auto bgManager = il2cpp_symbols::get_method_pointer("umamusume.dll", "Gallop", "BGManager", "get_Instance", 0)(); if (bgManager) { - auto _bgCamera = il2cpp_class_get_method_from_name_type(bgManager->klass, "get__bgCamera", 0)->methodPointer(bgManager); - auto targetTexture = il2cpp_class_get_method_from_name_type(_bgCamera->klass, "get_targetTexture", 0)->methodPointer(_bgCamera); - + auto _mainBgField = il2cpp_class_get_field_from_name_wrap(bgManager->klass, "_mainBg"); + Il2CppObject* _mainBg; + il2cpp_field_get_value(bgManager, _mainBgField, &_mainBg); - auto mainBg = il2cpp_class_get_method_from_name_type(bgManager->klass, "get_MainBg", 0)->methodPointer(bgManager); - auto rectTransform = il2cpp_class_get_method_from_name_type(mainBg->klass, "get_rectTransform", 0)->methodPointer(mainBg); - auto rect = il2cpp_class_get_method_from_name_type(rectTransform->klass, "get_rect", 0)->methodPointer(rectTransform); - - auto _currentBgWidth = il2cpp_class_get_field_from_name_wrap(bgManager->klass, "_currentBgWidth"); - int bgWidth; - il2cpp_field_get_value(bgManager, _currentBgWidth, &bgWidth); - - auto _currentBgHeight = il2cpp_class_get_field_from_name_wrap(bgManager->klass, "_currentBgHeight"); - int bgHeight; - il2cpp_field_get_value(bgManager, _currentBgHeight, &bgHeight); - - if (targetTexture) + if (_mainBg) { - auto textureWidth = il2cpp_class_get_method_from_name_type(targetTexture->klass, "get_width", 0)->methodPointer(targetTexture); - auto textureHeight = il2cpp_class_get_method_from_name_type(targetTexture->klass, "get_height", 0)->methodPointer(targetTexture); - - float scale = BGManager_CalcBgScale_hook(bgManager, rect.width, rect.height, textureWidth, textureHeight); + auto transform = il2cpp_class_get_method_from_name_type(_mainBg->klass, "get_transform", 0)->methodPointer(_mainBg); - auto _mainBgField = il2cpp_class_get_field_from_name_wrap(bgManager->klass, "_mainBg"); - Il2CppObject* _mainBg; - il2cpp_field_get_value(bgManager, _mainBgField, &_mainBg); + int width = il2cpp_symbols::get_method_pointer("UnityEngine.CoreModule.dll", "UnityEngine", "Screen", "get_width", -1)(); + int height = il2cpp_symbols::get_method_pointer("UnityEngine.CoreModule.dll", "UnityEngine", "Screen", "get_height", -1)(); - if (_mainBg) + if (width > height) { - auto transform = il2cpp_class_get_method_from_name_type(_mainBg->klass, "get_transform", 0)->methodPointer(_mainBg); - il2cpp_class_get_method_from_name_type(transform->klass, "set_localScale", 1)->methodPointer(transform, Vector3_t{ scale, scale, 1 }); - } - - /*auto _bgCanvasScalerField = il2cpp_class_get_field_from_name_wrap(bgManager->klass, "_bgCanvasScaler"); - Il2CppObject* _bgCanvasScaler; - il2cpp_field_get_value(bgManager, _bgCanvasScalerField, &_bgCanvasScaler); - - if (_bgCanvasScaler) - { - auto GallopScreen = il2cpp_symbols::get_class("umamusume.dll", "Gallop", "Screen"); - - auto NUMBER1920_Field = il2cpp_class_get_field_from_name_wrap(GallopScreen, "NUMBER1920"); + auto pos = il2cpp_class_get_method_from_name_type(transform->klass, "get_localPosition", 0)->methodPointer(transform); - auto NUMBER1080_Field = il2cpp_class_get_field_from_name_wrap(GallopScreen, "NUMBER1080"); - - int number1920; - int number1080; - - il2cpp_field_static_get_value(NUMBER1920_Field, &number1920); - il2cpp_field_static_get_value(NUMBER1080_Field, &number1080); - - int bgSize = max(bgWidth, bgHeight); + if (pos.y == 0) + { + il2cpp_class_get_method_from_name_type(transform->klass, "set_localPosition", 1)->methodPointer(transform, Vector3_t{ 0, 0, 0 }); + } + } + } + auto _bgCanvasScalerField = il2cpp_class_get_field_from_name_wrap(bgManager->klass, "_bgCanvasScaler"); + Il2CppObject* _bgCanvasScaler; + il2cpp_field_get_value(bgManager, _bgCanvasScalerField, &_bgCanvasScaler); - if (number1920 < number1080) - { - if (bgWidth == 0 || bgHeight == 0) - { - bgWidth = number1080; - bgHeight = number1920; - } + if (_bgCanvasScaler) + { + il2cpp_class_get_method_from_name_type(_bgCanvasScaler->klass, "set_scaleFactor", 1)->methodPointer(_bgCanvasScaler, 1); - float size = number1080; - il2cpp_class_get_method_from_name_type(_bgCanvasScaler->klass, "set_referenceResolution", 1)->methodPointer( - _bgCanvasScaler, Vector2_t{ static_cast(number1080), static_cast(number1920) }); - il2cpp_class_get_method_from_name_type(_bgCanvasScaler->klass, "set_scaleFactor", 1)->methodPointer( - _bgCanvasScaler, scale); - } - else - { - if (bgWidth == 0 || bgHeight == 0) - { - bgWidth = number1920; - bgHeight = number1080; - } + il2cpp_class_get_method_from_name_type(_bgCanvasScaler->klass, "set_uiScaleMode", 1)->methodPointer(_bgCanvasScaler, 1); - float size = number1920; - il2cpp_class_get_method_from_name_type(_bgCanvasScaler->klass, "set_referenceResolution", 1)->methodPointer( - _bgCanvasScaler, Vector2_t{ static_cast(number1920), static_cast(number1080) }); - il2cpp_class_get_method_from_name_type(_bgCanvasScaler->klass, "set_scaleFactor", 1)->methodPointer( - _bgCanvasScaler, scale); - } - //il2cpp_class_get_method_from_name_type(_bgCanvasScaler->klass, "set_scaleFactor", 1)->methodPointer(_bgCanvasScaler, 1); - }*/ + il2cpp_class_get_method_from_name_type(_bgCanvasScaler->klass, "set_screenMatchMode", 1)->methodPointer(_bgCanvasScaler, 0); } - } } @@ -2015,24 +2142,53 @@ namespace void* UIManager_ChangeResizeUIForPC_orig = nullptr; void UIManager_ChangeResizeUIForPC_hook(Il2CppObject* _this, int width, int height) { - reinterpret_cast(UIManager_ChangeResizeUIForPC_orig)(_this, width, height); - auto scalers = UIManager_GetCanvasScalerList(_this); + // reinterpret_cast(UIManager_ChangeResizeUIForPC_orig)(_this, width, height); + Il2CppArraySize_t* scalers; + if (Game::CurrentGameRegion == Game::Region::KOR) + { + scalers = il2cpp_resolve_icall_type*(*)(Il2CppObject*, int, int)>("UnityEngine.Object::FindObjectsByType()")( + GetRuntimeType("UnityEngine.UI.dll", "UnityEngine.UI", "CanvasScaler"), 1, 0); + } + else + { + scalers = il2cpp_resolve_icall_type*(*)(Il2CppObject*, bool)>("UnityEngine.Object::FindObjectsOfType()")( + GetRuntimeType("UnityEngine.UI.dll", "UnityEngine.UI", "CanvasScaler"), true); + } + + // auto scalers = UIManager_GetCanvasScalerList(_this); for (int i = 0; i < scalers->max_length; i++) { auto scaler = scalers->vector[i]; if (scaler) { + auto gameObject = il2cpp_class_get_method_from_name_type(scaler->klass, "get_gameObject", 0)->methodPointer(scaler); + + bool keepActive = il2cpp_class_get_method_from_name_type(gameObject->klass, "get_activeSelf", 0)->methodPointer(gameObject); + + il2cpp_class_get_method_from_name_type(gameObject->klass, "SetActive", 1)->methodPointer(gameObject, true); + if (g_freeform_window) { + /*if (width < height) + { + float scale = min(g_freeform_ui_scale_portrait, max(1, height * ratio_vertical) * g_freeform_ui_scale_portrait); + il2cpp_class_get_method_from_name_type(scaler->klass, "set_referenceResolution", 1)->methodPointer(scaler, Vector2_t{ static_cast(width / scale), static_cast(height / scale) }); + } + else + { + float scale = min(g_freeform_ui_scale_landscape, max(1, width / ratio_horizontal) * g_freeform_ui_scale_landscape); + il2cpp_class_get_method_from_name_type(scaler->klass, "set_referenceResolution", 1)->methodPointer(scaler, Vector2_t{ static_cast(width / scale), static_cast(height / scale) }); + }*/ + if (width < height) { float scale = min(g_freeform_ui_scale_portrait, max(1, height * ratio_vertical) * g_freeform_ui_scale_portrait); - set_scale_factor(scaler, scale); + il2cpp_class_get_method_from_name_type(scaler->klass, "set_scaleFactor", 1)->methodPointer(scaler, scale); } else { float scale = min(g_freeform_ui_scale_landscape, max(1, width / ratio_horizontal) * g_freeform_ui_scale_landscape); - set_scale_factor(scaler, scale); + il2cpp_class_get_method_from_name_type(scaler->klass, "set_scaleFactor", 1)->methodPointer(scaler, scale); } } else @@ -2041,14 +2197,22 @@ namespace if (width < height) { float scale = min(g_ui_scale, max(1, height * ratio_vertical) * g_ui_scale); - set_scale_factor(scaler, scale); + il2cpp_class_get_method_from_name_type(scaler->klass, "set_scaleFactor", 1)->methodPointer(scaler, scale); + // il2cpp_class_get_method_from_name_type(scaler->klass, "set_referenceResolution", 1)->methodPointer(scaler, Vector2_t{ static_cast(width / scale), static_cast(height / scale) }); } else { float scale = min(g_ui_scale, max(1, width / ratio_horizontal) * g_ui_scale); - set_scale_factor(scaler, scale); + il2cpp_class_get_method_from_name_type(scaler->klass, "set_scaleFactor", 1)->methodPointer(scaler, scale); + // il2cpp_class_get_method_from_name_type(scaler->klass, "set_referenceResolution", 1)->methodPointer(scaler, Vector2_t{ static_cast(width / scale), static_cast(height / scale) }); } } + + il2cpp_class_get_method_from_name_type(scaler->klass, "set_uiScaleMode", 1)->methodPointer(scaler, 0); + + // il2cpp_class_get_method_from_name_type(scaler->klass, "set_screenMatchMode", 1)->methodPointer(scaler, 0); + + il2cpp_class_get_method_from_name_type(gameObject->klass, "SetActive", 1)->methodPointer(gameObject, keepActive); } } @@ -2073,399 +2237,264 @@ namespace Il2CppObject* delayTweener; - void resizeWindow(HWND hWnd, int updateWidth, int updateHeight) + void RemakeTextures() { - if (updateWidth < 72 || updateHeight < 72) - { - return; - } - - auto StandaloneWindowResize = il2cpp_symbols::get_class("umamusume.dll", "Gallop", "StandaloneWindowResize"); - - auto lastWidthField = il2cpp_class_get_field_from_name_wrap(StandaloneWindowResize, "windowLastWidth"); - auto lastHeightField = il2cpp_class_get_field_from_name_wrap(StandaloneWindowResize, "windowLastHeight"); - - RECT windowRect; - GetWindowRect(hWnd, &windowRect); - int windowWidth = windowRect.right - windowRect.left, - windowHeight = windowRect.bottom - windowRect.top; - - RECT clientRect; - GetClientRect(hWnd, &clientRect); - - int frameWidth = windowWidth - clientRect.right; - int frameHeight = windowHeight - clientRect.bottom; - - int contentWidth = updateWidth - frameWidth; - int contentHeight = updateHeight - frameHeight; + auto uiManager = GetSingletonInstance(il2cpp_symbols::get_class("umamusume.dll", "Gallop", "UIManager")); - auto ratio = static_cast(contentWidth) / static_cast(contentHeight); + auto graphicSettings = GetSingletonInstance(il2cpp_symbols::get_class("umamusume.dll", "Gallop", "GraphicSettings")); + il2cpp_class_get_method_from_name_type(graphicSettings->klass, "Update3DRenderTexture", 0)->methodPointer(graphicSettings); - if (contentWidth < contentHeight) + Il2CppArraySize_t* renders; + if (Game::CurrentGameRegion == Game::Region::KOR) { - ratio_vertical = static_cast(contentWidth) / static_cast(contentHeight); - // ratio_horizontal = static_cast(contentHeight) / static_cast (contentWidth); - - last_display_width = last_display_height * ratio; - - // last_hriz_window_height = last_hriz_window_width / ratio_horizontal; - last_virt_window_width = last_virt_window_height * ratio_vertical; + renders = il2cpp_resolve_icall_type*(*)(Il2CppObject*, int, int)>("UnityEngine.Object::FindObjectsByType()")( + GetRuntimeType("umamusume.dll", "Gallop", "CutInImageEffectPostRender"), 1, 0); } else { - // ratio_vertical = static_cast(contentHeight) / static_cast(contentWidth); - ratio_horizontal = static_cast(contentWidth) / static_cast(contentHeight); - - last_display_height = last_display_width / ratio; - - last_hriz_window_height = last_hriz_window_width / ratio_horizontal; - // last_virt_window_width = last_virt_window_height * ratio_vertical; + renders = il2cpp_resolve_icall_type*(*)(Il2CppObject*, bool)>("UnityEngine.Object::FindObjectsOfType()")( + GetRuntimeType("umamusume.dll", "Gallop", "CutInImageEffectPostRender"), true); } - auto lastWidth = updateWidth; - auto lastHeight = updateHeight; - - il2cpp_field_static_set_value(lastWidthField, &lastWidth); - il2cpp_field_static_set_value(lastHeightField, &lastHeight); - - il2cpp_class_get_method_from_name_type(StandaloneWindowResize, "SaveChangedWidth", 2)->methodPointer(lastWidth, lastHeight); - - auto _aspectRatioField = il2cpp_class_get_field_from_name_wrap(StandaloneWindowResize, "_aspectRatio"); - float _aspectRatio = contentWidth / contentHeight; - il2cpp_field_static_set_value(_aspectRatioField, &_aspectRatio); - - il2cpp_class_get_method_from_name_type(StandaloneWindowResize, "set_IsPreventReShape", 1)->methodPointer(true); - il2cpp_class_get_method_from_name_type(StandaloneWindowResize, "DisableWindowHitTest", -1)->methodPointer(); - - bool isPortrait = contentWidth < contentHeight; - - il2cpp_symbols::get_method_pointer("umamusume.dll", "Gallop", "StandaloneWindowResize", "set_IsVirt", 1)(isPortrait); - - auto GallopScreen = il2cpp_symbols::get_class("umamusume.dll", "Gallop", "Screen"); + if (renders) + { + for (int i = 0; i < renders->max_length; i++) + { + auto obj = renders->vector[i]; - auto NUMBER1920_Field = il2cpp_class_get_field_from_name_wrap(GallopScreen, "NUMBER1920"); + if (obj) + { + auto buffer = il2cpp_class_get_method_from_name_type(obj->klass, "get_FrameBuffer", 0)->methodPointer(obj); + if (buffer) + { + il2cpp_class_get_method_from_name_type(buffer->klass, "RemakeRenderTexture", 0)->methodPointer(buffer); + } + } + } + } - auto NUMBER1080_Field = il2cpp_class_get_field_from_name_wrap(GallopScreen, "NUMBER1080"); + Il2CppArraySize_t* cuts; + if (Game::CurrentGameRegion == Game::Region::KOR) + { + cuts = il2cpp_resolve_icall_type*(*)(Il2CppObject*, int, int)>("UnityEngine.Object::FindObjectsByType()")( + GetRuntimeType("umamusume.dll", "Gallop", "LimitBreakCut"), 1, 0); + } + else + { + cuts = il2cpp_resolve_icall_type*(*)(Il2CppObject*, bool)>("UnityEngine.Object::FindObjectsOfType()")( + GetRuntimeType("umamusume.dll", "Gallop", "LimitBreakCut"), true); + } - auto _originalScreenWidth_Field = il2cpp_class_get_field_from_name_wrap(GallopScreen, "_originalScreenWidth"); + if (cuts) + { + for (int i = 0; i < cuts->max_length; i++) + { + auto obj = cuts->vector[i]; - auto _originalScreenHeight_Field = il2cpp_class_get_field_from_name_wrap(GallopScreen, "_originalScreenHeight"); + if (obj) + { + auto _frameBufferField = il2cpp_class_get_field_from_name_wrap(obj->klass, "_frameBuffer"); + Il2CppObject* _frameBuffer; + il2cpp_field_get_value(obj, _frameBufferField, &_frameBuffer); - int unityWidth = il2cpp_symbols::get_method_pointer("UnityEngine.CoreModule.dll", "UnityEngine", "Screen", "get_width", -1)(); - int unityHeight = il2cpp_symbols::get_method_pointer("UnityEngine.CoreModule.dll", "UnityEngine", "Screen", "get_height", -1)(); + if (_frameBuffer) + { + il2cpp_class_get_method_from_name_type(_frameBuffer->klass, "RemakeRenderTexture", 0)->methodPointer(_frameBuffer); + } + } + } + } - if (unityWidth < unityHeight) + Il2CppArraySize_t* raceEffect; + if (Game::CurrentGameRegion == Game::Region::KOR) { - il2cpp_field_static_set_value(NUMBER1080_Field, &contentWidth); - il2cpp_field_static_set_value(NUMBER1920_Field, &contentHeight); - il2cpp_field_static_set_value(_originalScreenHeight_Field, &contentWidth); - il2cpp_field_static_set_value(_originalScreenWidth_Field, &contentHeight); + raceEffect = il2cpp_resolve_icall_type*(*)(Il2CppObject*, int, int)>("UnityEngine.Object::FindObjectsByType()")( + GetRuntimeType("umamusume.dll", "Gallop", "RaceImageEffect"), 1, 0); } else { - il2cpp_field_static_set_value(NUMBER1920_Field, &contentWidth); - il2cpp_field_static_set_value(NUMBER1080_Field, &contentHeight); - il2cpp_field_static_set_value(_originalScreenWidth_Field, &contentWidth); - il2cpp_field_static_set_value(_originalScreenHeight_Field, &contentHeight); + raceEffect = il2cpp_resolve_icall_type*(*)(Il2CppObject*, bool)>("UnityEngine.Object::FindObjectsOfType()")( + GetRuntimeType("umamusume.dll", "Gallop", "RaceImageEffect"), true); } - auto tapEffectController = GetSingletonInstance(il2cpp_symbols::get_class("umamusume.dll", "Gallop", "TapEffectController")); - - auto uiManager = GetSingletonInstance(il2cpp_symbols::get_class("umamusume.dll", "Gallop", "UIManager")); - - if (uiManager) + if (raceEffect) { - //auto loadingCanvas = il2cpp_class_get_method_from_name_type(uiManager->klass, "get_LoadingCanvas", -1)->methodPointer(); - //if (loadingCanvas) - //{ - // auto canvas = il2cpp_class_get_method_from_name_type(loadingCanvas->klass, "get_Canvas", 0)->methodPointer(loadingCanvas); - - // il2cpp_class_get_method_from_name_type(canvas->klass, "set_sortingLayerName", 1)->methodPointer(canvas, il2cpp_string_new("Default")); - // il2cpp_class_get_method_from_name_type(canvas->klass, "set_sortingOrder", 1)->methodPointer(canvas, 0); - // il2cpp_class_get_method_from_name_type(canvas->klass, "set_overrideSorting", 1)->methodPointer(canvas, true); - //} - - //auto nowLoading = il2cpp_symbols::get_method_pointer("umamusume.dll", "Gallop", "NowLoading", "get_Instance", -1)(); - //if (nowLoading) - //{ - // auto _bgImageField = il2cpp_class_get_field_from_name_wrap(nowLoading->klass, "_bgImage"); - // Il2CppObject* _bgImage; - // il2cpp_field_get_value(nowLoading, _bgImageField, &_bgImage); - - // if (_bgImage) - // { - // auto gameObject = il2cpp_class_get_method_from_name_type(_bgImage->klass, "get_gameObject", 0)->methodPointer(_bgImage); - // if (gameObject) - // { - // // il2cpp_class_get_method_from_name_type(gameObject->klass, "SetActive", 1)->methodPointer(gameObject, true); - // } - // } - - // auto _backCanvasGroupField = il2cpp_class_get_field_from_name_wrap(nowLoading->klass, "_backCanvasGroup"); - // Il2CppObject* _backCanvasGroup; - // il2cpp_field_get_value(nowLoading, _backCanvasGroupField, &_backCanvasGroup); - - // if (_backCanvasGroup) - // { - // il2cpp_class_get_method_from_name_type(_backCanvasGroup->klass, "set_alpha", 1)->methodPointer(_backCanvasGroup, 1); - // } - - // auto ids = il2cpp_symbols::get_method_pointer("UnityEngine.CoreModule.dll", "UnityEngine", "SortingLayer", "GetSortingLayerIDsInternal", -1)(); - // for (int i = 0; i < ids->max_length; i++) - // { - // auto id = reinterpret_cast(ids->vector[i]); - // cout << "Layer Id: " << id << endl; - // cout << "Layer name: " << local::wide_u8(il2cpp_symbols::get_method_pointer("UnityEngine.CoreModule.dll", "UnityEngine", "SortingLayer", "IDToName", 1)(id)->start_char) << endl; - // } - - // auto _activeHorseShoeParticleField = il2cpp_class_get_field_from_name_wrap(nowLoading->klass, isPortrait ? "_horseShoeParticleVertical" : "_horseShoeParticleHorizontal"); - // Il2CppObject* _activeHorseShoeParticle; - // il2cpp_field_get_value(nowLoading, _activeHorseShoeParticleField, &_activeHorseShoeParticle); - - // if (_activeHorseShoeParticle) - // { - // il2cpp_class_get_method_from_name_type(_activeHorseShoeParticle->klass, "SetActive", 1)->methodPointer(_activeHorseShoeParticle, true); - // il2cpp_class_get_method_from_name_type(_activeHorseShoeParticle->klass, "SetParticleAlpha", 1)->methodPointer(_activeHorseShoeParticle, 1); - // il2cpp_class_get_method_from_name_type(_activeHorseShoeParticle->klass, "SetLayer", 2)->methodPointer(_activeHorseShoeParticle, il2cpp_string_new("Default"), 0); - - // auto _particleRendererField = il2cpp_class_get_field_from_name_wrap(_activeHorseShoeParticle->klass, "_particleRenderer"); - // Il2CppObject* _particleRenderer; - // il2cpp_field_get_value(_activeHorseShoeParticle, _particleRendererField, &_particleRenderer); - - // if (_particleRenderer) - // { - // reinterpret_cast(il2cpp_resolve_icall("UnityEngine.Renderer::set_rendererPriority(System.Int32)"))(_particleRenderer, 0); - // } - // } - - // auto _activeHorseShoeParticle1Field = il2cpp_class_get_field_from_name_wrap(nowLoading->klass, isPortrait ? "_horseShoeParticleHorizontal" : "_horseShoeParticleVertical"); - // Il2CppObject* _activeHorseShoeParticle1; - // il2cpp_field_get_value(nowLoading, _activeHorseShoeParticle1Field, &_activeHorseShoeParticle1); - - // if (_activeHorseShoeParticle1) - // { - // il2cpp_class_get_method_from_name_type(_activeHorseShoeParticle1->klass, "SetActive", 1)->methodPointer(_activeHorseShoeParticle1, false); - // } - //} - - /*auto _bgCameraSettingsField = il2cpp_class_get_field_from_name_wrap(GallopScreen, "_bgCameraSettings"); - - Il2CppObject* _bgCameraSettings; - il2cpp_symbols::get_method_pointer("umamusume.dll", "Gallop", "Screen", "InitializeChangeScaleForPC", 2)(isPortrait, &_bgCameraSettings); - - il2cpp_field_static_set_value(_bgCameraSettingsField, &_bgCameraSettings);*/ - /*auto _bgCameraField = il2cpp_class_get_field_from_name_wrap(uiManager->klass, "_bgCamera"); - Il2CppObject* _bgCamera; - - il2cpp_field_get_value(uiManager, _bgCameraField, &_bgCamera); - - il2cpp_class_get_method_from_name_type(_bgCamera->klass, "set_backgroundColor", 1)->methodPointer(_bgCamera, - il2cpp_symbols::get_method_pointer("UnityEngine.CoreModule.dll", "UnityEngine", "Color", "get_clear", -1)());*/ + for (int i = 0; i < raceEffect->max_length; i++) + { + auto obj = raceEffect->vector[i]; - il2cpp_class_get_method_from_name_type(tapEffectController->klass, "Disable", 0)->methodPointer(tapEffectController); + if (obj) + { + auto buffer = il2cpp_class_get_method_from_name_type(obj->klass, "get_FrameBuffer", 0)->methodPointer(obj); + if (buffer) + { + il2cpp_class_get_method_from_name_type(buffer->klass, "RemakeRenderTexture", 0)->methodPointer(buffer); + } + } + } } - auto anRootManager = GetSingletonInstance(il2cpp_symbols::get_class("Plugins.dll", "AnimateToUnity", "AnRootManager")); - - if (anRootManager) + Il2CppArraySize_t* storyEffect; + if (Game::CurrentGameRegion == Game::Region::KOR) { - il2cpp_class_get_method_from_name_type(anRootManager->klass, "set_ScreenRate", 1)->methodPointer(anRootManager, _aspectRatio); + storyEffect = il2cpp_resolve_icall_type*(*)(Il2CppObject*, int, int)>("UnityEngine.Object::FindObjectsByType()")( + GetRuntimeType("umamusume.dll", "Gallop", "StoryImageEffect"), 1, 0); } - - // il2cpp_class_get_method_from_name_type(GallopScreen, "UpdateForPC", -1)->methodPointer(); - - if (uiManager) + else { - // il2cpp_class_get_method_from_name_type(uiManager->klass, "ChangeResizeUIForPC", 2)->methodPointer(uiManager, lastWidth, lastHeight); - - // AutoRotation - il2cpp_symbols::get_method_pointer("UnityEngine.CoreModule.dll", "UnityEngine", "Screen", "set_orientation", 1)(5); - - auto gameObject = il2cpp_class_get_method_from_name_type(uiManager->klass, "get_gameObject", 0)->methodPointer(uiManager); - - auto transform = il2cpp_class_get_method_from_name_type(gameObject->klass, "get_transform", 0)->methodPointer(gameObject); - - il2cpp_class_get_method_from_name_type(transform->klass, "set_localScale", 1)->methodPointer(transform, Vector3_t{ 1, 1, 1 }); - - // auto _bgCameraSettingsField = il2cpp_class_get_field_from_name_wrap(GallopScreen, "_bgCameraSettings"); - - // Il2CppObject* _bgCameraSettings; - // il2cpp_field_static_get_value(_bgCameraSettingsField, &_bgCameraSettings); - - // il2cpp_class_get_method_from_name_type(uiManager->klass, "EndOrientation", 1)->methodPointer(uiManager, &_bgCameraSettings); - - // il2cpp_field_static_set_value(_bgCameraSettingsField, &_bgCameraSettings); + storyEffect = il2cpp_resolve_icall_type*(*)(Il2CppObject*, bool)>("UnityEngine.Object::FindObjectsOfType()")( + GetRuntimeType("umamusume.dll", "Gallop", "StoryImageEffect"), true); + } - if (tapEffectController) + if (storyEffect) + { + for (int i = 0; i < storyEffect->max_length; i++) { - il2cpp_class_get_method_from_name_type(tapEffectController->klass, "Enable", 0)->methodPointer(tapEffectController); - } + auto obj = storyEffect->vector[i]; - auto canvasScalerList = il2cpp_class_get_method_from_name_type *(*)(Il2CppObject*)>(uiManager->klass, "GetCanvasScalerList", 0)->methodPointer(uiManager); - for (int i = 0; i < canvasScalerList->max_length; i++) - { - auto canvasScaler = canvasScalerList->vector[i]; - if (canvasScaler) + if (obj) { - auto gameObject = il2cpp_class_get_method_from_name_type(canvasScaler->klass, "get_gameObject", 0)->methodPointer(canvasScaler); - - bool keepActive = il2cpp_class_get_method_from_name_type(gameObject->klass, "get_activeSelf", 0)->methodPointer(gameObject); - - il2cpp_class_get_method_from_name_type(gameObject->klass, "SetActive", 1)->methodPointer(gameObject, true); - - il2cpp_class_get_method_from_name_type(canvasScaler->klass, "set_referenceResolution", 1)->methodPointer(canvasScaler, Vector2_t{ static_cast(contentWidth), static_cast(contentHeight) }); - - il2cpp_class_get_method_from_name_type(gameObject->klass, "SetActive", 1)->methodPointer(gameObject, keepActive); - - if (isPortrait) - { - float scale = min(g_freeform_ui_scale_portrait, max(1, contentHeight * ratio_vertical) * g_freeform_ui_scale_portrait); - il2cpp_class_get_method_from_name_type(canvasScaler->klass, "set_scaleFactor", 1)->methodPointer(canvasScaler, scale); - } - else + auto buffer = il2cpp_class_get_method_from_name_type(obj->klass, "get_FrameBuffer", 0)->methodPointer(obj); + if (buffer) { - float scale = min(g_freeform_ui_scale_landscape, max(1, contentWidth / ratio_horizontal) * g_freeform_ui_scale_landscape); - il2cpp_class_get_method_from_name_type(canvasScaler->klass, "set_scaleFactor", 1)->methodPointer(canvasScaler, scale); + il2cpp_class_get_method_from_name_type(buffer->klass, "RemakeRenderTexture", 0)->methodPointer(buffer); } } } - - SetBGCanvasScalerSize(); } - if (uiManager) + Il2CppArraySize_t* lowResCameras; + if (Game::CurrentGameRegion == Game::Region::KOR) { - il2cpp_class_get_method_from_name_type(uiManager->klass, "AdjustSafeArea", 0)->methodPointer(uiManager); - auto _bgManagerField = il2cpp_class_get_field_from_name_wrap(uiManager->klass, "_bgManager"); - Il2CppObject* _bgManager; - il2cpp_field_get_value(uiManager, _bgManagerField, &_bgManager); - if (_bgManager) - { - il2cpp_class_get_method_from_name_type(_bgManager->klass, "OnChangeResolutionByGraphicsSettings", 0)->methodPointer(_bgManager); - } - - il2cpp_class_get_method_from_name_type(uiManager->klass, "CheckUIToFrameBufferBlitInstance", 0)->methodPointer(uiManager); - il2cpp_class_get_method_from_name_type(uiManager->klass, "ReleaseRenderTexture", 0)->methodPointer(uiManager); - - - auto renderTexture = il2cpp_object_new(il2cpp_symbols::get_class("UnityEngine.CoreModule.dll", "UnityEngine", "RenderTexture")); - il2cpp_class_get_method_from_name_type(renderTexture->klass, ".ctor", 3)->methodPointer(renderTexture, contentWidth, contentHeight, 24); - il2cpp_class_get_method_from_name_type(renderTexture->klass, "set_autoGenerateMips", 1)->methodPointer(renderTexture, false); - il2cpp_class_get_method_from_name_type(renderTexture->klass, "set_useMipMap", 1)->methodPointer(renderTexture, false); - il2cpp_class_get_method_from_name_type(renderTexture->klass, "set_antiAliasing", 1)->methodPointer(renderTexture, 1); - - auto _uiTextureField = il2cpp_class_get_field_from_name_wrap(uiManager->klass, "_uiTexture"); - il2cpp_field_set_value(uiManager, _uiTextureField, renderTexture); - - if (!il2cpp_class_get_method_from_name_type(renderTexture->klass, "Create", 0)->methodPointer(renderTexture)) - { - il2cpp_class_get_method_from_name_type(uiManager->klass, "ReleaseRenderTexture", 0)->methodPointer(uiManager); - } - - auto _uiCommandBufferField = il2cpp_class_get_field_from_name_wrap(uiManager->klass, "_uiCommandBuffer"); - Il2CppObject* _uiCommandBuffer; - il2cpp_field_get_value(uiManager, _uiCommandBufferField, &_uiCommandBuffer); - - auto _blitToFrameMaterialField = il2cpp_class_get_field_from_name_wrap(uiManager->klass, "_blitToFrameMaterial"); - Il2CppObject* _blitToFrameMaterial; - il2cpp_field_get_value(uiManager, _blitToFrameMaterialField, &_blitToFrameMaterial); - - auto _uiCameraField = il2cpp_class_get_field_from_name_wrap(uiManager->klass, "_uiCamera"); - Il2CppObject* _uiCamera; - il2cpp_field_get_value(uiManager, _uiCameraField, &_uiCamera); - - auto _bgCameraField = il2cpp_class_get_field_from_name_wrap(uiManager->klass, "_bgCamera"); - Il2CppObject* _bgCamera; - il2cpp_field_get_value(uiManager, _bgCameraField, &_bgCamera); - - auto _noImageEffectUICameraField = il2cpp_class_get_field_from_name_wrap(uiManager->klass, "_noImageEffectUICamera"); - Il2CppObject* _noImageEffectUICamera; - il2cpp_field_get_value(uiManager, _noImageEffectUICameraField, &_noImageEffectUICamera); - - auto _uiToFrameBufferBlitCameraField = il2cpp_class_get_field_from_name_wrap(uiManager->klass, "_uiToFrameBufferBlitCamera"); - Il2CppObject* _uiToFrameBufferBlitCamera; - il2cpp_field_get_value(uiManager, _uiToFrameBufferBlitCameraField, &_uiToFrameBufferBlitCamera); + lowResCameras = il2cpp_resolve_icall_type*(*)(Il2CppObject*, int, int)>("UnityEngine.Object::FindObjectsByType()")( + GetRuntimeType("umamusume.dll", "Gallop", "LowResolutionCameraBase"), 1, 0); + } + else + { + lowResCameras = il2cpp_resolve_icall_type*(*)(Il2CppObject*, bool)>("UnityEngine.Object::FindObjectsOfType()")( + GetRuntimeType("umamusume.dll", "Gallop", "LowResolutionCameraBase"), true); + } - if (_uiCommandBuffer) - { - auto dest = il2cpp_symbols::get_method_pointer("UnityEngine.CoreModule.dll", "UnityEngine.Rendering", "RenderTargetIdentifier", "op_Implicit", 1)( - il2cpp_symbols::get_class("UnityEngine.CoreModule.dll", "UnityEngine.Rendering", "RenderTargetIdentifier"), 1); - il2cpp_class_get_method_from_name_type(_uiCommandBuffer->klass, "Blit", 3)->methodPointer(_uiCommandBuffer, renderTexture, dest, _blitToFrameMaterial); - } - if (_uiCamera) - { - il2cpp_class_get_method_from_name_type(_uiCamera->klass, "set_targetTexture", 1)->methodPointer(_uiCamera, renderTexture); - } - if (_bgCamera) - { - il2cpp_class_get_method_from_name_type(_bgCamera->klass, "set_targetTexture", 1)->methodPointer(_bgCamera, renderTexture); - } - if (_noImageEffectUICamera) + if (lowResCameras) + { + for (int i = 0; i < lowResCameras->max_length; i++) { - il2cpp_class_get_method_from_name_type(_noImageEffectUICamera->klass, "set_targetTexture", 1)->methodPointer(_noImageEffectUICamera, renderTexture); - } + auto obj = lowResCameras->vector[i]; - if (_uiToFrameBufferBlitCamera) - { - il2cpp_class_get_method_from_name_type(_uiToFrameBufferBlitCamera->klass, "set_enabled", 1)->methodPointer(_uiToFrameBufferBlitCamera, true); + if (obj) + { + auto method = il2cpp_class_get_method_from_name_type(obj->klass, "UpdateDirection", 0); + if (method) + { + method->methodPointer(obj); + } + } } } - auto graphicSettings = GetSingletonInstance(il2cpp_symbols::get_class("umamusume.dll", "Gallop", "GraphicSettings")); - il2cpp_class_get_method_from_name_type(graphicSettings->klass, "Update3DRenderTexture", 0)->methodPointer(graphicSettings); - - Il2CppArraySize_t* renders; + Il2CppArraySize_t* liveTheaterCharaSelects; if (Game::CurrentGameRegion == Game::Region::KOR) { - renders = il2cpp_resolve_icall_type*(*)(Il2CppObject*, int, int)>("UnityEngine.Object::FindObjectsByType()")( - GetRuntimeType("umamusume.dll", "Gallop", "CutInImageEffectPostRender"), 1, 0); + liveTheaterCharaSelects = il2cpp_resolve_icall_type*(*)(Il2CppObject*, int, int)>("UnityEngine.Object::FindObjectsByType()")( + GetRuntimeType("umamusume.dll", "Gallop", "LiveTheaterCharaSelect"), 1, 0); } else { - renders = il2cpp_resolve_icall_type*(*)(Il2CppObject*, bool)>("UnityEngine.Object::FindObjectsOfType()")( - GetRuntimeType("umamusume.dll", "Gallop", "CutInImageEffectPostRender"), true); + liveTheaterCharaSelects = il2cpp_resolve_icall_type*(*)(Il2CppObject*, bool)>("UnityEngine.Object::FindObjectsOfType()")( + GetRuntimeType("umamusume.dll", "Gallop", "LiveTheaterCharaSelect"), true); } - if (renders) + if (liveTheaterCharaSelects) { - for (int i = 0; i < renders->max_length; i++) + for (int i = 0; i < liveTheaterCharaSelects->max_length; i++) { - auto obj = renders->vector[i]; + auto obj = liveTheaterCharaSelects->vector[i]; if (obj) { - auto buffer = il2cpp_class_get_method_from_name_type(obj->klass, "get_FrameBuffer", 0)->methodPointer(obj); - if (buffer) + auto _sceneField = il2cpp_class_get_field_from_name_wrap(obj->klass, "_scene"); + Il2CppObject* _scene; + il2cpp_field_get_value(obj, _sceneField, &_scene); + + if (_scene) { - il2cpp_class_get_method_from_name_type(buffer->klass, "RemakeRenderTexture", 0)->methodPointer(buffer); + auto camera = il2cpp_class_get_method_from_name_type(_scene->klass, "GetCamera", 0)->methodPointer(_scene); + auto texture = il2cpp_class_get_method_from_name_type(camera->klass, "get_RenderTexture", 0)->methodPointer(camera); + + auto _formationAllField = il2cpp_class_get_field_from_name_wrap(obj->klass, "_formationAll"); + Il2CppObject* _formationAll; + il2cpp_field_get_value(obj, _formationAllField, &_formationAll); + + if (_formationAll) + { + il2cpp_class_get_method_from_name_type(_formationAll->klass, "SetRenderTex", 1)->methodPointer(_formationAll, texture); + } + + auto _formationMainField = il2cpp_class_get_field_from_name_wrap(obj->klass, "_formationMain"); + Il2CppObject* _formationMain; + il2cpp_field_get_value(obj, _formationMainField, &_formationMain); + + if (_formationMain) + { + il2cpp_class_get_method_from_name_type(_formationMain->klass, "SetRenderTex", 1)->methodPointer(_formationMain, texture); + } + + // TODO: reposition } } } } - Il2CppArraySize_t* cuts; + Il2CppArraySize_t* miniDirectors; if (Game::CurrentGameRegion == Game::Region::KOR) { - cuts = il2cpp_resolve_icall_type*(*)(Il2CppObject*, int, int)>("UnityEngine.Object::FindObjectsByType()")( - GetRuntimeType("umamusume.dll", "Gallop", "LimitBreakCut"), 1, 0); + miniDirectors = il2cpp_resolve_icall_type*(*)(Il2CppObject*, int, int)>("UnityEngine.Object::FindObjectsByType()")( + GetRuntimeType("umamusume.dll", "Gallop", "MiniDirector"), 1, 0); } else { - cuts = il2cpp_resolve_icall_type*(*)(Il2CppObject*, bool)>("UnityEngine.Object::FindObjectsOfType()")( - GetRuntimeType("umamusume.dll", "Gallop", "LimitBreakCut"), true); + miniDirectors = il2cpp_resolve_icall_type*(*)(Il2CppObject*, bool)>("UnityEngine.Object::FindObjectsOfType()")( + GetRuntimeType("umamusume.dll", "Gallop", "MiniDirector"), true); } - if (cuts) + if (miniDirectors && miniDirectors->max_length) { - for (int i = 0; i < cuts->max_length; i++) + + if (delayTweener) { - auto obj = cuts->vector[i]; + il2cpp_symbols::get_method_pointer("DOTween.dll", "DG.Tweening", "TweenExtensions", "Complete", 2)(delayTweener, true); + } - if (obj) + auto callback = CreateDelegateWithClass(il2cpp_symbols::get_class("DOTween.dll", "DG.Tweening", "TweenCallback"), uiManager, *([](Il2CppObject* _this) { - auto _frameBufferField = il2cpp_class_get_field_from_name_wrap(obj->klass, "_frameBuffer"); + ResizeMiniDirector(); + delayTweener = nullptr; + })); + + // Delay 50ms + delayTweener = il2cpp_symbols::get_method_pointer("DOTween.dll", "DG.Tweening", "DOVirtual", "DelayedCall", 3)(0.05, callback, true); + } + + auto sceneManager = GetSingletonInstance(il2cpp_symbols::get_class("umamusume.dll", "Gallop", "SceneManager")); + auto GetCurrentViewController = il2cpp_symbols::find_method("umamusume.dll", "Gallop", "SceneManager", [](const MethodInfo* info) + { + return info->name == "GetCurrentViewController"s && info->methodPointer; + }); + auto controller = GetCurrentViewController(sceneManager); + + if (controller) + { + if (controller->klass->name == "FanRaidViewController"s) + { + auto _fanRaidTopSequenceField = il2cpp_class_get_field_from_name_wrap(controller->klass, "_fanRaidTopSequence"); + Il2CppObject* _fanRaidTopSequence; + il2cpp_field_get_value(controller, _fanRaidTopSequenceField, &_fanRaidTopSequence); + + if (_fanRaidTopSequence) + { + auto _frameBufferField = il2cpp_class_get_field_from_name_wrap(_fanRaidTopSequence->klass, "_frameBuffer"); Il2CppObject* _frameBuffer; - il2cpp_field_get_value(obj, _frameBufferField, &_frameBuffer); + il2cpp_field_get_value(_fanRaidTopSequence, _frameBufferField, &_frameBuffer); if (_frameBuffer) { @@ -2473,268 +2502,628 @@ namespace } } } - } - Il2CppArraySize_t* raceEffect; - if (Game::CurrentGameRegion == Game::Region::KOR) - { - raceEffect = il2cpp_resolve_icall_type*(*)(Il2CppObject*, int, int)>("UnityEngine.Object::FindObjectsByType()")( - GetRuntimeType("umamusume.dll", "Gallop", "RaceImageEffect"), 1, 0); + if (controller->klass->name == "GachaMainViewController"s) + { + auto _contextField = il2cpp_class_get_field_from_name_wrap(controller->klass, "_context"); + Il2CppObject* _context; + il2cpp_field_get_value(controller, _contextField, &_context); + + if (_context) + { + auto FrameBufferField = il2cpp_class_get_field_from_name_wrap(_context->klass, "FrameBuffer"); + Il2CppObject* FrameBuffer; + il2cpp_field_get_value(_context, FrameBufferField, &FrameBuffer); + + if (FrameBuffer) + { + il2cpp_class_get_method_from_name_type(FrameBuffer->klass, "RemakeRenderTexture", 0)->methodPointer(FrameBuffer); + } + } + } + + if (controller->klass->name == "SingleModeSuccessionCutViewController"s || + controller->klass->name == "EpisodeMainUnlockRaceCutinViewController"s || + controller->klass->name == "SingleModeSuccessionEventViewController"s) + { + auto _resultField = il2cpp_class_get_field_from_name_wrap(controller->klass, "_result"); + Il2CppObject* _result; + il2cpp_field_get_value(controller, _resultField, &_result); + + if (_result) + { + auto _resultCameraField = il2cpp_class_get_field_from_name_wrap(_result->klass, "_resultCamera"); + Il2CppObject* _resultCamera; + il2cpp_field_get_value(_result, _resultCameraField, &_resultCamera); + + if (_resultCamera) + { + auto texture = il2cpp_class_get_method_from_name_type(uiManager->klass, "get_UITexture", 0)->methodPointer(uiManager); + il2cpp_class_get_method_from_name_type(_resultCamera->klass, "set_targetTexture", 1)->methodPointer(_resultCamera, texture); + } + } + } + + if (string(controller->klass->name).ends_with("PaddockViewController")) + { + auto _frameBufferField = il2cpp_class_get_field_from_name_wrap(controller->klass, "_frameBuffer"); + Il2CppObject* _frameBuffer; + il2cpp_field_get_value(controller, _frameBufferField, &_frameBuffer); + + if (_frameBuffer) + { + il2cpp_class_get_method_from_name_type(_frameBuffer->klass, "RemakeRenderTexture", 0)->methodPointer(_frameBuffer); + } + + } } - else + + if (GetSingletonInstance(il2cpp_symbols::get_class("umamusume.dll", "Gallop", "StoryManager"))) { - raceEffect = il2cpp_resolve_icall_type*(*)(Il2CppObject*, bool)>("UnityEngine.Object::FindObjectsOfType()")( - GetRuntimeType("umamusume.dll", "Gallop", "RaceImageEffect"), true); + auto storySceneController = il2cpp_symbols::get_method_pointer("umamusume.dll", "Gallop", "StoryManager", "get_StorySceneController", -1)(); + if (storySceneController) + { + auto CurrentDisplayModeField = il2cpp_class_get_field_from_name_wrap(il2cpp_symbols::get_class("umamusume.dll", "Gallop", "StoryTimelineController"), "CurrentDisplayMode"); + int mode; + il2cpp_field_static_get_value(CurrentDisplayModeField, &mode); + + il2cpp_class_get_method_from_name_type(storySceneController->klass, "ChangeCameraDirection", 1)->methodPointer(storySceneController, mode); + } } + } - if (raceEffect) + void MoviePlayerForUI_AdjustScreenSize_hook(Il2CppObject* _this, Vector2_t dispRectWH, bool isPanScan); + + void ResizeMoviePlayer() + { + auto movieManager = il2cpp_symbols::get_method_pointer("Cute.Cri.Assembly.dll", "Cute.Cri", "MovieManager", "get_Instance", -1)(); + + if (movieManager) { - for (int i = 0; i < raceEffect->max_length; i++) + auto playerDicField = il2cpp_class_get_field_from_name_wrap(movieManager->klass, "playerDic"); + Il2CppObject* playerDic; + il2cpp_field_get_value(movieManager, playerDicField, &playerDic); + + if (playerDic) { - auto obj = raceEffect->vector[i]; + auto entriesField = il2cpp_class_get_field_from_name_wrap(playerDic->klass, "entries"); + Il2CppArraySize_t>* entries; + il2cpp_field_get_value(playerDic, entriesField, &entries); - if (obj) + if (entries) { - auto buffer = il2cpp_class_get_method_from_name_type(obj->klass, "get_FrameBuffer", 0)->methodPointer(obj); - if (buffer) + for (int i = 0; i < entries->max_length; i++) { - il2cpp_class_get_method_from_name_type(buffer->klass, "RemakeRenderTexture", 0)->methodPointer(buffer); + auto entry = entries->vector[i]; + + auto player = entry.value; + + if (player) + { + auto gameObject = il2cpp_class_get_method_from_name_type(player->klass, "get_gameObject", 0)->methodPointer(player); + + if (gameObject) + { + auto transform = il2cpp_class_get_method_from_name_type(gameObject->klass, "get_transform", 0)->methodPointer(gameObject); + + if (transform) + { + auto parent = il2cpp_class_get_method_from_name_type(transform->klass, "get_parent", 0)->methodPointer(transform); + + if (parent) + { + auto parentGameObject = il2cpp_class_get_method_from_name_type(parent->klass, "get_gameObject", 0)->methodPointer(parent); + auto getComponents = il2cpp_class_get_method_from_name_type(parentGameObject->klass, "GetComponentsInternal", 6)->methodPointer; + + if (uobject_get_name(parent)->start_char == L"MainCanvas"s) + { + auto array1 = getComponents(parentGameObject, reinterpret_cast(GetRuntimeType( + "umamusume.dll", "Gallop", "StoryMovieView")), true, true, false, false, nullptr); + + if (array1) + { + if (array1->max_length > 0) + { + auto fullPlayer = il2cpp_object_new(il2cpp_symbols::get_class("umamusume.dll", "Gallop", "StoryFullMoviePlayer")); + auto _handleField = il2cpp_class_get_field_from_name_wrap(fullPlayer->klass, "_handle"); + il2cpp_field_set_value(fullPlayer, _handleField, &entry.key); + + il2cpp_class_get_method_from_name_type(fullPlayer->klass, "AdjustMovieSize", 1)->methodPointer(fullPlayer, is_virt() ? 0 : 1); + + return; + } + } + + auto array2 = getComponents(parentGameObject, reinterpret_cast(GetRuntimeType( + "umamusume.dll", "Gallop", "StoryView")), true, true, false, false, nullptr); + + if (array2) + { + if (array2->max_length > 0) + { + auto sceneManager = GetSingletonInstance(il2cpp_symbols::get_class("umamusume.dll", "Gallop", "SceneManager")); + auto GetCurrentViewController = il2cpp_symbols::find_method("umamusume.dll", "Gallop", "SceneManager", [](const MethodInfo* info) + { + return info->name == "GetCurrentViewController"s && info->methodPointer; + }); + auto controller = GetCurrentViewController(sceneManager); + + auto _wipeControllerField = il2cpp_class_get_field_from_name_wrap(controller->klass, "_wipeController"); + Il2CppObject* _wipeController; + il2cpp_field_get_value(controller, _wipeControllerField, &_wipeController); + + if (_wipeController) + { + auto _moviePlayerField = il2cpp_class_get_field_from_name_wrap(_wipeController->klass, "_moviePlayer"); + Il2CppObject* _moviePlayer; + il2cpp_field_get_value(_wipeController, _moviePlayerField, &_moviePlayer); + + if (_moviePlayer) + { + auto StoryTimelineController = il2cpp_symbols::get_class("umamusume.dll", "Gallop", "StoryTimelineController"); + auto CurrentDisplayModeField = il2cpp_class_get_field_from_name_wrap(StoryTimelineController->klass, "CurrentDisplayMode"); + int CurrentDisplayMode; + il2cpp_field_static_get_value(CurrentDisplayModeField, &CurrentDisplayMode); + + if (CurrentDisplayMode == 3 && !is_virt()) + { + int tmpMode = 2; + il2cpp_field_static_get_value(CurrentDisplayModeField, &tmpMode); + } + + il2cpp_class_get_method_from_name_type(_moviePlayer->klass, "AdjustScreenSize", 0)->methodPointer(_moviePlayer); + + il2cpp_field_static_set_value(CurrentDisplayModeField, &CurrentDisplayMode); + } + } + return; + } + } + + auto newSize = il2cpp_symbols::get_method_pointer("umamusume.dll", "Gallop", "MovieScreenSizeHelper", "GetMovieTargetCanvasSize", -1)(); + + auto criPlayer = il2cpp_class_get_method_from_name_type(player->klass, "get_Player", 0)->methodPointer(player); + + if (criPlayer) + { + auto status = il2cpp_class_get_method_from_name_type(criPlayer->klass, "get_status", 0)->methodPointer(criPlayer); + if (status == 5) + { + MoviePlayerForUI_AdjustScreenSize_hook(player, newSize, true); + } + } + + } + else if (parent->klass->name == "RectTransform"s) + { + auto parentGameObject = il2cpp_class_get_method_from_name_type(parent->klass, "get_gameObject", 0)->methodPointer(parent); + auto getComponents = il2cpp_class_get_method_from_name_type(parentGameObject->klass, "GetComponentsInternal", 6)->methodPointer; + + auto array = getComponents(parentGameObject, reinterpret_cast(GetRuntimeType( + "umamusume.dll", "Gallop", "PartsEpisodeList")), true, true, false, true, nullptr); + + if (array) + { + for (int j = 0; j < array->max_length; j++) + { + auto obj = + il2cpp_symbols::get_method_pointer("mscorlib.dll", "System", "Array", "GetValue", 1)(&array->obj, j); + if (!obj) continue; + + auto newSize = il2cpp_class_get_method_from_name_type(obj->klass, "CalcMovieRectSize", 0)->methodPointer(obj); + + il2cpp_class_get_method_from_name_type(parent->klass, "set_sizeDelta", 1)->methodPointer(parent, newSize); + + auto criPlayer = il2cpp_class_get_method_from_name_type(player->klass, "get_Player", 0)->methodPointer(player); + + if (criPlayer) + { + auto status = il2cpp_class_get_method_from_name_type(criPlayer->klass, "get_status", 0)->methodPointer(criPlayer); + if (status == 5) + { + MoviePlayerForUI_AdjustScreenSize_hook(player, newSize, true); + } + } + } + } + } + } + } + } + } } } } } + } - Il2CppArraySize_t* storyEffect; - if (Game::CurrentGameRegion == Game::Region::KOR) + void resizeWindow(HWND hWnd, int updateWidth, int updateHeight) + { + if (updateWidth < 72 || updateHeight < 72) { - storyEffect = il2cpp_resolve_icall_type*(*)(Il2CppObject*, int, int)>("UnityEngine.Object::FindObjectsByType()")( - GetRuntimeType("umamusume.dll", "Gallop", "StoryImageEffect"), 1, 0); + return; + } + + auto StandaloneWindowResize = il2cpp_symbols::get_class("umamusume.dll", "Gallop", "StandaloneWindowResize"); + + auto lastWidthField = il2cpp_class_get_field_from_name_wrap(StandaloneWindowResize, "windowLastWidth"); + auto lastHeightField = il2cpp_class_get_field_from_name_wrap(StandaloneWindowResize, "windowLastHeight"); + + RECT windowRect; + GetWindowRect(hWnd, &windowRect); + int windowWidth = windowRect.right - windowRect.left; + int windowHeight = windowRect.bottom - windowRect.top; + + RECT clientRect; + GetClientRect(hWnd, &clientRect); + + int frameWidth = windowWidth - clientRect.right; + int frameHeight = windowHeight - clientRect.bottom; + + int contentWidth = updateWidth - frameWidth; + int contentHeight = updateHeight - frameHeight; + + auto ratio = static_cast(contentWidth) / static_cast(contentHeight); + + if (contentWidth < contentHeight) + { + last_display_width = contentWidth; + last_display_height = contentHeight; + + last_virt_window_width = contentWidth; + last_virt_window_height = contentHeight; } else { - storyEffect = il2cpp_resolve_icall_type*(*)(Il2CppObject*, bool)>("UnityEngine.Object::FindObjectsOfType()")( - GetRuntimeType("umamusume.dll", "Gallop", "StoryImageEffect"), true); + last_display_width = contentWidth; + last_display_height = contentHeight; + + last_hriz_window_width = contentWidth; + last_hriz_window_height = contentHeight; } - if (storyEffect) - { - for (int i = 0; i < storyEffect->max_length; i++) - { - auto obj = storyEffect->vector[i]; + auto lastWidth = updateWidth; + auto lastHeight = updateHeight; + + il2cpp_field_static_set_value(lastWidthField, &lastWidth); + il2cpp_field_static_set_value(lastHeightField, &lastHeight); + + il2cpp_class_get_method_from_name_type(StandaloneWindowResize, "SaveChangedWidth", 2)->methodPointer(lastWidth, lastHeight); + + auto _aspectRatioField = il2cpp_class_get_field_from_name_wrap(StandaloneWindowResize, "_aspectRatio"); + float _aspectRatio = contentWidth / contentHeight; + il2cpp_field_static_set_value(_aspectRatioField, &_aspectRatio); + + il2cpp_class_get_method_from_name_type(StandaloneWindowResize, "set_IsPreventReShape", 1)->methodPointer(true); + il2cpp_class_get_method_from_name_type(StandaloneWindowResize, "DisableWindowHitTest", -1)->methodPointer(); + + bool isPortrait = contentWidth < contentHeight; + + il2cpp_symbols::get_method_pointer("umamusume.dll", "Gallop", "StandaloneWindowResize", "set_IsVirt", 1)(isPortrait); + + auto GallopScreen = il2cpp_symbols::get_class("umamusume.dll", "Gallop", "Screen"); + + auto NUMBER1920_Field = il2cpp_class_get_field_from_name_wrap(GallopScreen, "NUMBER1920"); + + auto NUMBER1080_Field = il2cpp_class_get_field_from_name_wrap(GallopScreen, "NUMBER1080"); - if (obj) - { - auto buffer = il2cpp_class_get_method_from_name_type(obj->klass, "get_FrameBuffer", 0)->methodPointer(obj); - if (buffer) - { - il2cpp_class_get_method_from_name_type(buffer->klass, "RemakeRenderTexture", 0)->methodPointer(buffer); - } - } - } - } + auto _originalScreenWidth_Field = il2cpp_class_get_field_from_name_wrap(GallopScreen, "_originalScreenWidth"); - Il2CppArraySize_t* lowResCameras; - if (Game::CurrentGameRegion == Game::Region::KOR) + auto _originalScreenHeight_Field = il2cpp_class_get_field_from_name_wrap(GallopScreen, "_originalScreenHeight"); + + auto SCREEN_ORIENTATION_CATEGORIES_Field = il2cpp_class_get_field_from_name_wrap(GallopScreen, "SCREEN_ORIENTATION_CATEGORIES"); + Il2CppObject* SCREEN_ORIENTATION_CATEGORIES; + il2cpp_field_static_get_value(SCREEN_ORIENTATION_CATEGORIES_Field, &SCREEN_ORIENTATION_CATEGORIES); + + if (lastWidth < lastHeight) { - lowResCameras = il2cpp_resolve_icall_type*(*)(Il2CppObject*, int, int)>("UnityEngine.Object::FindObjectsByType()")( - GetRuntimeType("umamusume.dll", "Gallop", "LowResolutionCameraBase"), 1, 0); + il2cpp_class_get_method_from_name_type(SCREEN_ORIENTATION_CATEGORIES->klass, "Clear", 0)->methodPointer(SCREEN_ORIENTATION_CATEGORIES); + il2cpp_class_get_method_from_name_type(SCREEN_ORIENTATION_CATEGORIES->klass, "Add", 2)->methodPointer(SCREEN_ORIENTATION_CATEGORIES, 1, 1); + il2cpp_class_get_method_from_name_type(SCREEN_ORIENTATION_CATEGORIES->klass, "Add", 2)->methodPointer(SCREEN_ORIENTATION_CATEGORIES, 2, 1); + il2cpp_class_get_method_from_name_type(SCREEN_ORIENTATION_CATEGORIES->klass, "Add", 2)->methodPointer(SCREEN_ORIENTATION_CATEGORIES, 3, 1); + il2cpp_class_get_method_from_name_type(SCREEN_ORIENTATION_CATEGORIES->klass, "Add", 2)->methodPointer(SCREEN_ORIENTATION_CATEGORIES, 4, 1); + il2cpp_class_get_method_from_name_type(SCREEN_ORIENTATION_CATEGORIES->klass, "Add", 2)->methodPointer(SCREEN_ORIENTATION_CATEGORIES, 5, 1); } else { - lowResCameras = il2cpp_resolve_icall_type*(*)(Il2CppObject*, bool)>("UnityEngine.Object::FindObjectsOfType()")( - GetRuntimeType("umamusume.dll", "Gallop", "LowResolutionCameraBase"), true); + il2cpp_class_get_method_from_name_type(SCREEN_ORIENTATION_CATEGORIES->klass, "Clear", 0)->methodPointer(SCREEN_ORIENTATION_CATEGORIES); + il2cpp_class_get_method_from_name_type(SCREEN_ORIENTATION_CATEGORIES->klass, "Add", 2)->methodPointer(SCREEN_ORIENTATION_CATEGORIES, 1, 3); + il2cpp_class_get_method_from_name_type(SCREEN_ORIENTATION_CATEGORIES->klass, "Add", 2)->methodPointer(SCREEN_ORIENTATION_CATEGORIES, 2, 3); + il2cpp_class_get_method_from_name_type(SCREEN_ORIENTATION_CATEGORIES->klass, "Add", 2)->methodPointer(SCREEN_ORIENTATION_CATEGORIES, 3, 3); + il2cpp_class_get_method_from_name_type(SCREEN_ORIENTATION_CATEGORIES->klass, "Add", 2)->methodPointer(SCREEN_ORIENTATION_CATEGORIES, 4, 3); + il2cpp_class_get_method_from_name_type(SCREEN_ORIENTATION_CATEGORIES->klass, "Add", 2)->methodPointer(SCREEN_ORIENTATION_CATEGORIES, 5, 3); } - if (lowResCameras) - { - for (int i = 0; i < lowResCameras->max_length; i++) - { - auto obj = lowResCameras->vector[i]; - - if (obj) - { - auto method = il2cpp_class_get_method_from_name_type(obj->klass, "UpdateDirection", 0); - if (method) - { - method->methodPointer(obj); - } - } - } - } + int unityWidth = il2cpp_symbols::get_method_pointer("UnityEngine.CoreModule.dll", "UnityEngine", "Screen", "get_width", -1)(); + int unityHeight = il2cpp_symbols::get_method_pointer("UnityEngine.CoreModule.dll", "UnityEngine", "Screen", "get_height", -1)(); - Il2CppArraySize_t* liveTheaterCharaSelects; - if (Game::CurrentGameRegion == Game::Region::KOR) + if (unityWidth < unityHeight) { - liveTheaterCharaSelects = il2cpp_resolve_icall_type*(*)(Il2CppObject*, int, int)>("UnityEngine.Object::FindObjectsByType()")( - GetRuntimeType("umamusume.dll", "Gallop", "LiveTheaterCharaSelect"), 1, 0); + il2cpp_field_static_set_value(NUMBER1080_Field, &contentWidth); + il2cpp_field_static_set_value(NUMBER1920_Field, &contentHeight); + il2cpp_field_static_set_value(_originalScreenHeight_Field, &contentWidth); + il2cpp_field_static_set_value(_originalScreenWidth_Field, &contentHeight); } else { - liveTheaterCharaSelects = il2cpp_resolve_icall_type*(*)(Il2CppObject*, bool)>("UnityEngine.Object::FindObjectsOfType()")( - GetRuntimeType("umamusume.dll", "Gallop", "LiveTheaterCharaSelect"), true); + il2cpp_field_static_set_value(NUMBER1920_Field, &contentWidth); + il2cpp_field_static_set_value(NUMBER1080_Field, &contentHeight); + il2cpp_field_static_set_value(_originalScreenWidth_Field, &contentWidth); + il2cpp_field_static_set_value(_originalScreenHeight_Field, &contentHeight); } - if (liveTheaterCharaSelects) + auto tapEffectController = GetSingletonInstance(il2cpp_symbols::get_class("umamusume.dll", "Gallop", "TapEffectController")); + + auto uiManager = GetSingletonInstance(il2cpp_symbols::get_class("umamusume.dll", "Gallop", "UIManager")); + + if (uiManager) { - for (int i = 0; i < liveTheaterCharaSelects->max_length; i++) - { - auto obj = liveTheaterCharaSelects->vector[i]; + //auto loadingCanvas = il2cpp_class_get_method_from_name_type(uiManager->klass, "get_LoadingCanvas", -1)->methodPointer(); + //if (loadingCanvas) + //{ + // auto canvas = il2cpp_class_get_method_from_name_type(loadingCanvas->klass, "get_Canvas", 0)->methodPointer(loadingCanvas); - if (obj) - { - auto _sceneField = il2cpp_class_get_field_from_name_wrap(obj->klass, "_scene"); - Il2CppObject* _scene; - il2cpp_field_get_value(obj, _sceneField, &_scene); + // il2cpp_class_get_method_from_name_type(canvas->klass, "set_sortingLayerName", 1)->methodPointer(canvas, il2cpp_string_new("Default")); + // il2cpp_class_get_method_from_name_type(canvas->klass, "set_sortingOrder", 1)->methodPointer(canvas, 0); + // il2cpp_class_get_method_from_name_type(canvas->klass, "set_overrideSorting", 1)->methodPointer(canvas, true); + //} - if (_scene) - { - auto camera = il2cpp_class_get_method_from_name_type(_scene->klass, "GetCamera", 0)->methodPointer(_scene); - auto texture = il2cpp_class_get_method_from_name_type(camera->klass, "get_RenderTexture", 0)->methodPointer(camera); + //auto nowLoading = il2cpp_symbols::get_method_pointer("umamusume.dll", "Gallop", "NowLoading", "get_Instance", -1)(); + //if (nowLoading) + //{ + // auto _bgImageField = il2cpp_class_get_field_from_name_wrap(nowLoading->klass, "_bgImage"); + // Il2CppObject* _bgImage; + // il2cpp_field_get_value(nowLoading, _bgImageField, &_bgImage); - auto _formationAllField = il2cpp_class_get_field_from_name_wrap(obj->klass, "_formationAll"); - Il2CppObject* _formationAll; - il2cpp_field_get_value(obj, _formationAllField, &_formationAll); + // if (_bgImage) + // { + // auto gameObject = il2cpp_class_get_method_from_name_type(_bgImage->klass, "get_gameObject", 0)->methodPointer(_bgImage); + // if (gameObject) + // { + // // il2cpp_class_get_method_from_name_type(gameObject->klass, "SetActive", 1)->methodPointer(gameObject, true); + // } + // } - if (_formationAll) - { - il2cpp_class_get_method_from_name_type(_formationAll->klass, "SetRenderTex", 1)->methodPointer(_formationAll, texture); - } + // auto _backCanvasGroupField = il2cpp_class_get_field_from_name_wrap(nowLoading->klass, "_backCanvasGroup"); + // Il2CppObject* _backCanvasGroup; + // il2cpp_field_get_value(nowLoading, _backCanvasGroupField, &_backCanvasGroup); - auto _formationMainField = il2cpp_class_get_field_from_name_wrap(obj->klass, "_formationMain"); - Il2CppObject* _formationMain; - il2cpp_field_get_value(obj, _formationMainField, &_formationMain); + // if (_backCanvasGroup) + // { + // il2cpp_class_get_method_from_name_type(_backCanvasGroup->klass, "set_alpha", 1)->methodPointer(_backCanvasGroup, 1); + // } - if (_formationMain) - { - il2cpp_class_get_method_from_name_type(_formationMain->klass, "SetRenderTex", 1)->methodPointer(_formationMain, texture); - } + // auto ids = il2cpp_symbols::get_method_pointer("UnityEngine.CoreModule.dll", "UnityEngine", "SortingLayer", "GetSortingLayerIDsInternal", -1)(); + // for (int i = 0; i < ids->max_length; i++) + // { + // auto id = reinterpret_cast(ids->vector[i]); + // cout << "Layer Id: " << id << endl; + // cout << "Layer name: " << local::wide_u8(il2cpp_symbols::get_method_pointer("UnityEngine.CoreModule.dll", "UnityEngine", "SortingLayer", "IDToName", 1)(id)->start_char) << endl; + // } - // TODO: reposition - } - } - } + // auto _activeHorseShoeParticleField = il2cpp_class_get_field_from_name_wrap(nowLoading->klass, isPortrait ? "_horseShoeParticleVertical" : "_horseShoeParticleHorizontal"); + // Il2CppObject* _activeHorseShoeParticle; + // il2cpp_field_get_value(nowLoading, _activeHorseShoeParticleField, &_activeHorseShoeParticle); + + // if (_activeHorseShoeParticle) + // { + // il2cpp_class_get_method_from_name_type(_activeHorseShoeParticle->klass, "SetActive", 1)->methodPointer(_activeHorseShoeParticle, true); + // il2cpp_class_get_method_from_name_type(_activeHorseShoeParticle->klass, "SetParticleAlpha", 1)->methodPointer(_activeHorseShoeParticle, 1); + // il2cpp_class_get_method_from_name_type(_activeHorseShoeParticle->klass, "SetLayer", 2)->methodPointer(_activeHorseShoeParticle, il2cpp_string_new("Default"), 0); + + // auto _particleRendererField = il2cpp_class_get_field_from_name_wrap(_activeHorseShoeParticle->klass, "_particleRenderer"); + // Il2CppObject* _particleRenderer; + // il2cpp_field_get_value(_activeHorseShoeParticle, _particleRendererField, &_particleRenderer); + + // if (_particleRenderer) + // { + // reinterpret_cast(il2cpp_resolve_icall("UnityEngine.Renderer::set_rendererPriority(System.Int32)"))(_particleRenderer, 0); + // } + // } + + // auto _activeHorseShoeParticle1Field = il2cpp_class_get_field_from_name_wrap(nowLoading->klass, isPortrait ? "_horseShoeParticleHorizontal" : "_horseShoeParticleVertical"); + // Il2CppObject* _activeHorseShoeParticle1; + // il2cpp_field_get_value(nowLoading, _activeHorseShoeParticle1Field, &_activeHorseShoeParticle1); + + // if (_activeHorseShoeParticle1) + // { + // il2cpp_class_get_method_from_name_type(_activeHorseShoeParticle1->klass, "SetActive", 1)->methodPointer(_activeHorseShoeParticle1, false); + // } + //} + + /*auto _bgCameraSettingsField = il2cpp_class_get_field_from_name_wrap(GallopScreen, "_bgCameraSettings"); + + Il2CppObject* _bgCameraSettings; + il2cpp_symbols::get_method_pointer("umamusume.dll", "Gallop", "Screen", "InitializeChangeScaleForPC", 2)(isPortrait, &_bgCameraSettings); + + il2cpp_field_static_set_value(_bgCameraSettingsField, &_bgCameraSettings);*/ + /*auto _bgCameraField = il2cpp_class_get_field_from_name_wrap(uiManager->klass, "_bgCamera"); + Il2CppObject* _bgCamera; + + il2cpp_field_get_value(uiManager, _bgCameraField, &_bgCamera); + + il2cpp_class_get_method_from_name_type(_bgCamera->klass, "set_backgroundColor", 1)->methodPointer(_bgCamera, + il2cpp_symbols::get_method_pointer("UnityEngine.CoreModule.dll", "UnityEngine", "Color", "get_clear", -1)());*/ + + il2cpp_class_get_method_from_name_type(tapEffectController->klass, "Disable", 0)->methodPointer(tapEffectController); + + il2cpp_class_get_method_from_name_type(uiManager->klass, "SetCameraSizeByOrientation", 1)->methodPointer(uiManager, ScreenOrientation::Portrait); } - if (delayTweener) + auto anRootManager = GetSingletonInstance(il2cpp_symbols::get_class("Plugins.dll", "AnimateToUnity", "AnRootManager")); + + if (anRootManager) { - il2cpp_symbols::get_method_pointer("DOTween.dll", "DG.Tweening", "TweenExtensions", "Complete", 2)(delayTweener, true); + il2cpp_class_get_method_from_name_type(anRootManager->klass, "set_ScreenRate", 1)->methodPointer(anRootManager, _aspectRatio); } - auto callback = CreateDelegateWithClass(il2cpp_symbols::get_class("DOTween.dll", "DG.Tweening", "TweenCallback"), uiManager, *([](Il2CppObject* _this) - { - ResizeMiniDirector(); - delayTweener = nullptr; - })); + // il2cpp_class_get_method_from_name_type(GallopScreen, "UpdateForPC", -1)->methodPointer(); - // Delay 50ms - delayTweener = il2cpp_symbols::get_method_pointer("DOTween.dll", "DG.Tweening", "DOVirtual", "DelayedCall", 3)(0.05, callback, true); + if (uiManager) + { + // il2cpp_class_get_method_from_name_type(uiManager->klass, "ChangeResizeUIForPC", 2)->methodPointer(uiManager, lastWidth, lastHeight); - auto sceneManager = GetSingletonInstance(il2cpp_symbols::get_class("umamusume.dll", "Gallop", "SceneManager")); - auto GetCurrentViewController = il2cpp_symbols::find_method("umamusume.dll", "Gallop", "SceneManager", [](const MethodInfo* info) + // AutoRotation + // il2cpp_symbols::get_method_pointer("UnityEngine.CoreModule.dll", "UnityEngine", "Screen", "set_orientation", 1)(5); + + auto gameObject = il2cpp_class_get_method_from_name_type(uiManager->klass, "get_gameObject", 0)->methodPointer(uiManager); + + auto transform = il2cpp_class_get_method_from_name_type(gameObject->klass, "get_transform", 0)->methodPointer(gameObject); + + il2cpp_class_get_method_from_name_type(transform->klass, "set_localScale", 1)->methodPointer(transform, Vector3_t{ 1, 1, 1 }); + + // auto _bgCameraSettingsField = il2cpp_class_get_field_from_name_wrap(GallopScreen, "_bgCameraSettings"); + + // Il2CppObject* _bgCameraSettings; + // il2cpp_field_static_get_value(_bgCameraSettingsField, &_bgCameraSettings); + + // il2cpp_class_get_method_from_name_type(uiManager->klass, "EndOrientation", 1)->methodPointer(uiManager, &_bgCameraSettings); + + // il2cpp_field_static_set_value(_bgCameraSettingsField, &_bgCameraSettings); + + if (tapEffectController) { - return info->name == "GetCurrentViewController"s && info->methodPointer; - }); - auto controller = GetCurrentViewController(sceneManager); + il2cpp_class_get_method_from_name_type(tapEffectController->klass, "Enable", 0)->methodPointer(tapEffectController); + } - if (controller) - { - if (controller->klass->name == "FanRaidViewController"s) + Il2CppArraySize_t* canvasScalerList; + if (Game::CurrentGameRegion == Game::Region::KOR) { - auto _fanRaidTopSequenceField = il2cpp_class_get_field_from_name_wrap(controller->klass, "_fanRaidTopSequence"); - Il2CppObject* _fanRaidTopSequence; - il2cpp_field_get_value(controller, _fanRaidTopSequenceField, &_fanRaidTopSequence); + canvasScalerList = il2cpp_resolve_icall_type*(*)(Il2CppObject*, int, int)>("UnityEngine.Object::FindObjectsByType()")( + GetRuntimeType("UnityEngine.UI.dll", "UnityEngine.UI", "CanvasScaler"), 1, 0); + } + else + { + canvasScalerList = il2cpp_resolve_icall_type*(*)(Il2CppObject*, bool)>("UnityEngine.Object::FindObjectsOfType()")( + GetRuntimeType("UnityEngine.UI.dll", "UnityEngine.UI", "CanvasScaler"), true); + } + // auto canvasScalerList = il2cpp_class_get_method_from_name_type *(*)(Il2CppObject*)>(uiManager->klass, "GetCanvasScalerList", 0)->methodPointer(uiManager); - if (_fanRaidTopSequence) + for (int i = 0; i < canvasScalerList->max_length; i++) + { + auto canvasScaler = canvasScalerList->vector[i]; + if (canvasScaler) { - auto _frameBufferField = il2cpp_class_get_field_from_name_wrap(_fanRaidTopSequence->klass, "_frameBuffer"); - Il2CppObject* _frameBuffer; - il2cpp_field_get_value(_fanRaidTopSequence, _frameBufferField, &_frameBuffer); + auto gameObject = il2cpp_class_get_method_from_name_type(canvasScaler->klass, "get_gameObject", 0)->methodPointer(canvasScaler); - if (_frameBuffer) + bool keepActive = il2cpp_class_get_method_from_name_type(gameObject->klass, "get_activeSelf", 0)->methodPointer(gameObject); + + il2cpp_class_get_method_from_name_type(gameObject->klass, "SetActive", 1)->methodPointer(gameObject, true); + + + /*if (isPortrait) { - il2cpp_class_get_method_from_name_type(_frameBuffer->klass, "RemakeRenderTexture", 0)->methodPointer(_frameBuffer); + float scale = min(g_freeform_ui_scale_portrait, max(1, contentHeight * ratio_vertical) * g_freeform_ui_scale_portrait); + il2cpp_class_get_method_from_name_type(canvasScaler->klass, "set_referenceResolution", 1)->methodPointer(canvasScaler, Vector2_t{ static_cast(contentWidth / scale), static_cast(contentHeight / scale) }); } - } - } + else + { + float scale = min(g_freeform_ui_scale_landscape, max(1, contentWidth / ratio_horizontal) * g_freeform_ui_scale_landscape); + il2cpp_class_get_method_from_name_type(canvasScaler->klass, "set_referenceResolution", 1)->methodPointer(canvasScaler, Vector2_t{ static_cast(contentWidth / scale), static_cast(contentHeight / scale) }); + }*/ - if (controller->klass->name == "GachaMainViewController"s) - { - auto _contextField = il2cpp_class_get_field_from_name_wrap(controller->klass, "_context"); - Il2CppObject* _context; - il2cpp_field_get_value(controller, _contextField, &_context); + il2cpp_class_get_method_from_name_type(canvasScaler->klass, "set_uiScaleMode", 1)->methodPointer(canvasScaler, 0); - if (_context) - { - auto FrameBufferField = il2cpp_class_get_field_from_name_wrap(_context->klass, "FrameBuffer"); - Il2CppObject* FrameBuffer; - il2cpp_field_get_value(_context, FrameBufferField, &FrameBuffer); + // il2cpp_class_get_method_from_name_type(canvasScaler->klass, "set_screenMatchMode", 1)->methodPointer(canvasScaler, 0); + + il2cpp_class_get_method_from_name_type(gameObject->klass, "SetActive", 1)->methodPointer(gameObject, keepActive); - if (FrameBuffer) + if (isPortrait) { - il2cpp_class_get_method_from_name_type(FrameBuffer->klass, "RemakeRenderTexture", 0)->methodPointer(FrameBuffer); + float scale = min(g_freeform_ui_scale_portrait, max(1, contentHeight * ratio_vertical) * g_freeform_ui_scale_portrait); + il2cpp_class_get_method_from_name_type(canvasScaler->klass, "set_scaleFactor", 1)->methodPointer(canvasScaler, scale); + } + else + { + float scale = min(g_freeform_ui_scale_landscape, max(1, contentWidth / ratio_horizontal) * g_freeform_ui_scale_landscape); + il2cpp_class_get_method_from_name_type(canvasScaler->klass, "set_scaleFactor", 1)->methodPointer(canvasScaler, scale); } } } - if (controller->klass->name == "SingleModeSuccessionCutViewController"s || - controller->klass->name == "EpisodeMainUnlockRaceCutinViewController"s || - controller->klass->name == "SingleModeSuccessionEventViewController"s) + SetBGCanvasScalerSize(); + } + + if (uiManager) + { + il2cpp_class_get_method_from_name_type(uiManager->klass, "AdjustSafeArea", 0)->methodPointer(uiManager); + auto _bgManagerField = il2cpp_class_get_field_from_name_wrap(uiManager->klass, "_bgManager"); + Il2CppObject* _bgManager; + il2cpp_field_get_value(uiManager, _bgManagerField, &_bgManager); + if (_bgManager) { - auto _resultField = il2cpp_class_get_field_from_name_wrap(controller->klass, "_result"); - Il2CppObject* _result; - il2cpp_field_get_value(controller, _resultField, &_result); + il2cpp_class_get_method_from_name_type(_bgManager->klass, "OnChangeResolutionByGraphicsSettings", 0)->methodPointer(_bgManager); + } - if (_result) - { - auto _resultCameraField = il2cpp_class_get_field_from_name_wrap(_result->klass, "_resultCamera"); - Il2CppObject* _resultCamera; - il2cpp_field_get_value(_result, _resultCameraField, &_resultCamera); + il2cpp_class_get_method_from_name_type(uiManager->klass, "CheckUIToFrameBufferBlitInstance", 0)->methodPointer(uiManager); + il2cpp_class_get_method_from_name_type(uiManager->klass, "ReleaseRenderTexture", 0)->methodPointer(uiManager); - if (_resultCamera) - { - auto texture = il2cpp_class_get_method_from_name_type(uiManager->klass, "get_UITexture", 0)->methodPointer(uiManager); - il2cpp_class_get_method_from_name_type(_resultCamera->klass, "set_targetTexture", 1)->methodPointer(_resultCamera, texture); - } - } - } - if (string(controller->klass->name).ends_with("PaddockViewController")) - { - auto _frameBufferField = il2cpp_class_get_field_from_name_wrap(controller->klass, "_frameBuffer"); - Il2CppObject* _frameBuffer; - il2cpp_field_get_value(controller, _frameBufferField, &_frameBuffer); + auto renderTexture = il2cpp_object_new(il2cpp_symbols::get_class("UnityEngine.CoreModule.dll", "UnityEngine", "RenderTexture")); + il2cpp_class_get_method_from_name_type(renderTexture->klass, ".ctor", 3)->methodPointer(renderTexture, contentWidth, contentHeight, 24); + il2cpp_class_get_method_from_name_type(renderTexture->klass, "set_autoGenerateMips", 1)->methodPointer(renderTexture, false); + il2cpp_class_get_method_from_name_type(renderTexture->klass, "set_useMipMap", 1)->methodPointer(renderTexture, false); + il2cpp_class_get_method_from_name_type(renderTexture->klass, "set_antiAliasing", 1)->methodPointer(renderTexture, 1); - if (_frameBuffer) - { - il2cpp_class_get_method_from_name_type(_frameBuffer->klass, "RemakeRenderTexture", 0)->methodPointer(_frameBuffer); - } + auto _uiTextureField = il2cpp_class_get_field_from_name_wrap(uiManager->klass, "_uiTexture"); + il2cpp_field_set_value(uiManager, _uiTextureField, renderTexture); + if (!il2cpp_class_get_method_from_name_type(renderTexture->klass, "Create", 0)->methodPointer(renderTexture)) + { + il2cpp_class_get_method_from_name_type(uiManager->klass, "ReleaseRenderTexture", 0)->methodPointer(uiManager); } - } + auto _uiCommandBufferField = il2cpp_class_get_field_from_name_wrap(uiManager->klass, "_uiCommandBuffer"); + Il2CppObject* _uiCommandBuffer; + il2cpp_field_get_value(uiManager, _uiCommandBufferField, &_uiCommandBuffer); - if (tapEffectController) - { - il2cpp_class_get_method_from_name_type(tapEffectController->klass, "RefreshAll", 0)->methodPointer(tapEffectController); - } + auto _blitToFrameMaterialField = il2cpp_class_get_field_from_name_wrap(uiManager->klass, "_blitToFrameMaterial"); + Il2CppObject* _blitToFrameMaterial; + il2cpp_field_get_value(uiManager, _blitToFrameMaterialField, &_blitToFrameMaterial); - if (uiManager) - { - il2cpp_class_get_method_from_name_type(uiManager->klass, "AdjustMissionClearContentsRootRect", 0)->methodPointer(uiManager); - il2cpp_class_get_method_from_name_type(uiManager->klass, "AdjustSafeAreaToAnnounceRect", 0)->methodPointer(uiManager); + auto _uiCameraField = il2cpp_class_get_field_from_name_wrap(uiManager->klass, "_uiCamera"); + Il2CppObject* _uiCamera; + il2cpp_field_get_value(uiManager, _uiCameraField, &_uiCamera); auto _bgCameraField = il2cpp_class_get_field_from_name_wrap(uiManager->klass, "_bgCamera"); Il2CppObject* _bgCamera; il2cpp_field_get_value(uiManager, _bgCameraField, &_bgCamera); + auto _noImageEffectUICameraField = il2cpp_class_get_field_from_name_wrap(uiManager->klass, "_noImageEffectUICamera"); + Il2CppObject* _noImageEffectUICamera; + il2cpp_field_get_value(uiManager, _noImageEffectUICameraField, &_noImageEffectUICamera); + + auto _uiToFrameBufferBlitCameraField = il2cpp_class_get_field_from_name_wrap(uiManager->klass, "_uiToFrameBufferBlitCamera"); + Il2CppObject* _uiToFrameBufferBlitCamera; + il2cpp_field_get_value(uiManager, _uiToFrameBufferBlitCameraField, &_uiToFrameBufferBlitCamera); + + if (_uiCommandBuffer) + { + auto dest = il2cpp_symbols::get_method_pointer("UnityEngine.CoreModule.dll", "UnityEngine.Rendering", "RenderTargetIdentifier", "op_Implicit", 1)( + il2cpp_symbols::get_class("UnityEngine.CoreModule.dll", "UnityEngine.Rendering", "RenderTargetIdentifier"), 1); + il2cpp_class_get_method_from_name_type(_uiCommandBuffer->klass, "Blit", 3)->methodPointer(_uiCommandBuffer, renderTexture, dest, _blitToFrameMaterial); + } + if (_uiCamera) + { + il2cpp_class_get_method_from_name_type(_uiCamera->klass, "set_targetTexture", 1)->methodPointer(_uiCamera, renderTexture); + } if (_bgCamera) { - il2cpp_class_get_method_from_name_type(_bgCamera->klass, "set_backgroundColor", 1)->methodPointer(_bgCamera, - il2cpp_symbols::get_method_pointer("UnityEngine.CoreModule.dll", "UnityEngine", "Color", "get_clear", -1)()); + il2cpp_class_get_method_from_name_type(_bgCamera->klass, "set_targetTexture", 1)->methodPointer(_bgCamera, renderTexture); + } + if (_noImageEffectUICamera) + { + il2cpp_class_get_method_from_name_type(_noImageEffectUICamera->klass, "set_targetTexture", 1)->methodPointer(_noImageEffectUICamera, renderTexture); + } + + if (_uiToFrameBufferBlitCamera) + { + il2cpp_class_get_method_from_name_type(_uiToFrameBufferBlitCamera->klass, "set_enabled", 1)->methodPointer(_uiToFrameBufferBlitCamera, true); } } - // RaceManager + RemakeTextures(); + auto raceCameraManager = GetSingletonInstance(il2cpp_symbols::get_class("umamusume.dll", "Gallop", "RaceCameraManager")); if (raceCameraManager) { @@ -2747,16 +3136,24 @@ namespace il2cpp_class_get_method_from_name_type(director->klass, "SetupOrientation", 1)->methodPointer(director, isPortrait ? 2 : 1); } - if (GetSingletonInstance(il2cpp_symbols::get_class("umamusume.dll", "Gallop", "StoryManager"))) + if (tapEffectController) { - auto storySceneController = il2cpp_symbols::get_method_pointer("umamusume.dll", "Gallop", "StoryManager", "get_StorySceneController", -1)(); - if (storySceneController) - { - auto CurrentDisplayModeField = il2cpp_class_get_field_from_name_wrap(il2cpp_symbols::get_class("umamusume.dll", "Gallop", "StoryTimelineController"), "CurrentDisplayMode"); - int mode; - il2cpp_field_static_get_value(CurrentDisplayModeField, &mode); + il2cpp_class_get_method_from_name_type(tapEffectController->klass, "RefreshAll", 0)->methodPointer(tapEffectController); + } - il2cpp_class_get_method_from_name_type(storySceneController->klass, "ChangeCameraDirection", 1)->methodPointer(storySceneController, mode); + if (uiManager) + { + il2cpp_class_get_method_from_name_type(uiManager->klass, "AdjustMissionClearContentsRootRect", 0)->methodPointer(uiManager); + il2cpp_class_get_method_from_name_type(uiManager->klass, "AdjustSafeAreaToAnnounceRect", 0)->methodPointer(uiManager); + + auto _bgCameraField = il2cpp_class_get_field_from_name_wrap(uiManager->klass, "_bgCamera"); + Il2CppObject* _bgCamera; + il2cpp_field_get_value(uiManager, _bgCameraField, &_bgCamera); + + if (_bgCamera) + { + il2cpp_class_get_method_from_name_type(_bgCamera->klass, "set_backgroundColor", 1)->methodPointer(_bgCamera, + il2cpp_symbols::get_method_pointer("UnityEngine.CoreModule.dll", "UnityEngine", "Color", "get_clear", -1)()); } } @@ -2820,6 +3217,28 @@ namespace return false; } + void* Camera_set_orthographicSize_orig = nullptr; + void Camera_set_orthographicSize_hook(Il2CppObject* _this, float value) + { + if (wstring(uobject_get_name(_this)->start_char).find(L"UICamera") != wstring::npos) + { + auto callback = CreateDelegateWithClass(il2cpp_symbols::get_class("DOTween.dll", "DG.Tweening", "TweenCallback"), _this, *([](Il2CppObject* _this) + { + RemakeTextures(); + })); + + il2cpp_symbols::get_method_pointer("DOTween.dll", "DG.Tweening", "DOVirtual", "DelayedCall", 3)(0.1, callback, true); + + auto current = il2cpp_class_get_method_from_name_type(_this->klass, "get_orthographicSize", 0)->methodPointer(_this); + if (current == 5.0f) + { + return; + } + value = 5.0f; + } + reinterpret_cast(Camera_set_orthographicSize_orig)(_this, value); + } + void* RectTransform_get_rect_Injected_orig = nullptr; void RectTransform_get_rect_Injected_hook(Il2CppObject* _this, Rect_t* rect) { @@ -2833,6 +3252,7 @@ namespace return; } + auto sceneManager = GetSingletonInstance(il2cpp_symbols::get_class("umamusume.dll", "Gallop", "SceneManager")); if (sceneManager) { @@ -2843,6 +3263,7 @@ namespace if (_changeViewEnumerator) { auto current = il2cpp_class_get_method_from_name_type(_changeViewEnumerator->klass, "System.Collections.IEnumerator.get_Current", 0)->methodPointer(_changeViewEnumerator); + if (current && string(current->klass->name).find("ChangeScreenOrientation") != string::npos) { auto scaler = il2cpp_class_get_method_from_name_type(_this->klass, "GetComponent", 1)->methodPointer(_this, GetRuntimeType("UnityEngine.UI.dll", "UnityEngine.UI", "CanvasScaler")); @@ -2860,7 +3281,6 @@ namespace isRequestChangeResolution = false; } } - } } } @@ -2903,7 +3323,7 @@ namespace auto hWnd = FindWindowW(L"UnityWndClass", title.data()); - long style = GetWindowLongW(FindWindowW(L"UnityWndClass", title.data()), GWL_STYLE); + long style = GetWindowLongW(hWnd, GWL_STYLE); style |= WS_MAXIMIZEBOX; SetWindowLongPtrW(hWnd, GWL_STYLE, style); @@ -3160,7 +3580,7 @@ namespace CreateDelegate(dialogData, *[](Il2CppObject* data) { isExitOpened = false; - exit(0); + ExitProcess(0); }), GetTextIdByName("Common0004"), GetTextIdByName("Common0003"), @@ -3406,8 +3826,6 @@ namespace } else { - cout << get_rendering_width(display) << " " << get_rendering_height(display) << endl; - RECT windowRect; GetClientRect(hWnd, &windowRect); if (get_rendering_width(display) > get_rendering_height(display)) @@ -3488,196 +3906,195 @@ namespace } } - if (g_unlock_size || g_freeform_window) + if (uMsg == WM_NCHITTEST) { - if (uMsg == WM_NCHITTEST) + auto StandaloneWindowResize = il2cpp_symbols::get_class("umamusume.dll", "Gallop", "StandaloneWindowResize"); + if (!il2cpp_class_get_method_from_name_type(StandaloneWindowResize, "get_IsEnableWindowHitTest", -1)->methodPointer()) { - auto StandaloneWindowResize = il2cpp_symbols::get_class("umamusume.dll", "Gallop", "StandaloneWindowResize"); - if (!il2cpp_class_get_method_from_name_type(StandaloneWindowResize, "get_IsEnableWindowHitTest", -1)->methodPointer()) - { - return FALSE; - } + return FALSE; } + } - if (uMsg == WM_ENTERSIZEMOVE) - { - auto StandaloneWindowResize = il2cpp_symbols::get_class("umamusume.dll", "Gallop", "StandaloneWindowResize"); - auto _isWindowSizeChangingField = il2cpp_class_get_field_from_name_wrap(StandaloneWindowResize->klass, "_isWindowSizeChanging"); - bool _isWindowSizeChanging = true; - il2cpp_field_static_set_value(_isWindowSizeChangingField, &_isWindowSizeChanging); - } + if (uMsg == WM_ENTERSIZEMOVE) + { + auto StandaloneWindowResize = il2cpp_symbols::get_class("umamusume.dll", "Gallop", "StandaloneWindowResize"); + auto _isWindowSizeChangingField = il2cpp_class_get_field_from_name_wrap(StandaloneWindowResize->klass, "_isWindowSizeChanging"); + bool _isWindowSizeChanging = true; + il2cpp_field_static_set_value(_isWindowSizeChangingField, &_isWindowSizeChanging); + } - if (uMsg == WM_MOVING) - { - auto StandaloneWindowResize = il2cpp_symbols::get_class("umamusume.dll", "Gallop", "StandaloneWindowResize"); - auto _isWindowDraggingField = il2cpp_class_get_field_from_name_wrap(StandaloneWindowResize->klass, "_isWindowDragging"); - bool _isWindowDragging = true; - il2cpp_field_static_set_value(_isWindowDraggingField, &_isWindowDragging); - } + if (uMsg == WM_MOVING) + { + auto StandaloneWindowResize = il2cpp_symbols::get_class("umamusume.dll", "Gallop", "StandaloneWindowResize"); + auto _isWindowDraggingField = il2cpp_class_get_field_from_name_wrap(StandaloneWindowResize->klass, "_isWindowDragging"); + bool _isWindowDragging = true; + il2cpp_field_static_set_value(_isWindowDraggingField, &_isWindowDragging); + } - if (uMsg == WM_EXITSIZEMOVE) + if (uMsg == WM_SIZE) + { + auto StandaloneWindowResize = il2cpp_symbols::get_class("umamusume.dll", "Gallop", "StandaloneWindowResize"); + + switch (wParam) + { + case SIZE_RESTORED: { - auto StandaloneWindowResize = il2cpp_symbols::get_class("umamusume.dll", "Gallop", "StandaloneWindowResize"); - auto _isWindowDraggingField = il2cpp_class_get_field_from_name_wrap(StandaloneWindowResize->klass, "_isWindowDragging"); - auto _isWindowSizeChangingField = il2cpp_class_get_field_from_name_wrap(StandaloneWindowResize->klass, "_isWindowSizeChanging"); - bool _isWindowSizeChanging = false; - il2cpp_field_static_set_value(_isWindowDraggingField, &_isWindowSizeChanging); - il2cpp_field_static_set_value(_isWindowSizeChangingField, &_isWindowSizeChanging); - if (g_freeform_window) + auto StartCoroutine = il2cpp_symbols::find_method("UnityEngine.CoreModule.dll", "UnityEngine", "MonoBehaviour", [](const MethodInfo* method) + { + return method->name == "StartCoroutine"s && method->parameters[0].parameter_type->type == IL2CPP_TYPE_CLASS; + }); + auto uiManager = GetSingletonInstance(il2cpp_symbols::get_class("umamusume.dll", "Gallop", "UIManager")); + if (uiManager) { - RECT windowRect; - GetWindowRect(hWnd, &windowRect); - int windowWidth = windowRect.right - windowRect.left, - windowHeight = windowRect.bottom - windowRect.top; - resizeWindow(hWnd, windowWidth, windowHeight); + StartCoroutine(uiManager, il2cpp_class_get_method_from_name_type(StandaloneWindowResize->klass, "ClearStopFlagAfterWhile", 0)->methodPointer()); } + break; } - - if (uMsg == WM_SIZE) + case SIZE_MINIMIZED: { - auto StandaloneWindowResize = il2cpp_symbols::get_class("umamusume.dll", "Gallop", "StandaloneWindowResize"); - switch (wParam) - { - case SIZE_RESTORED: - { + auto _isWindowDraggingField = il2cpp_class_get_field_from_name_wrap(StandaloneWindowResize->klass, "_isWindowDragging"); + bool _isWindowDragging = true; + il2cpp_field_static_set_value(_isWindowDraggingField, &_isWindowDragging); + break; + } + } + } - auto StartCoroutine = il2cpp_symbols::find_method("UnityEngine.CoreModule.dll", "UnityEngine", "MonoBehaviour", [](const MethodInfo* method) - { - return method->name == "StartCoroutine"s && method->parameters[0].parameter_type->type == IL2CPP_TYPE_CLASS; - }); - auto uiManager = GetSingletonInstance(il2cpp_symbols::get_class("umamusume.dll", "Gallop", "UIManager")); - if (uiManager) - { - StartCoroutine(uiManager, il2cpp_class_get_method_from_name_type(StandaloneWindowResize->klass, "ClearStopFlagAfterWhile", 0)->methodPointer()); - } - break; - } - case SIZE_MINIMIZED: - { + if (uMsg == WM_EXITSIZEMOVE) + { + auto StandaloneWindowResize = il2cpp_symbols::get_class("umamusume.dll", "Gallop", "StandaloneWindowResize"); + auto _isWindowDraggingField = il2cpp_class_get_field_from_name_wrap(StandaloneWindowResize->klass, "_isWindowDragging"); + auto _isWindowSizeChangingField = il2cpp_class_get_field_from_name_wrap(StandaloneWindowResize->klass, "_isWindowSizeChanging"); + bool _isWindowSizeChanging = false; + il2cpp_field_static_set_value(_isWindowDraggingField, &_isWindowSizeChanging); + il2cpp_field_static_set_value(_isWindowSizeChangingField, &_isWindowSizeChanging); - auto _isWindowDraggingField = il2cpp_class_get_field_from_name_wrap(StandaloneWindowResize->klass, "_isWindowDragging"); - bool _isWindowDragging = true; - il2cpp_field_static_set_value(_isWindowDraggingField, &_isWindowDragging); - break; - } - } + if (g_freeform_window) + { + RECT windowRect; + GetWindowRect(hWnd, &windowRect); + int windowWidth = windowRect.right - windowRect.left, + windowHeight = windowRect.bottom - windowRect.top; + resizeWindow(hWnd, windowWidth, windowHeight); + } + } - if (g_freeform_window) - { - auto lastWidthField = il2cpp_class_get_field_from_name_wrap(StandaloneWindowResize, "windowLastWidth"); - auto lastHeightField = il2cpp_class_get_field_from_name_wrap(StandaloneWindowResize, "windowLastHeight"); + if (uMsg == WM_SIZE && g_freeform_window) + { + auto StandaloneWindowResize = il2cpp_symbols::get_class("umamusume.dll", "Gallop", "StandaloneWindowResize"); - int lastWidth, lastHeight; + auto lastWidthField = il2cpp_class_get_field_from_name_wrap(StandaloneWindowResize, "windowLastWidth"); + auto lastHeightField = il2cpp_class_get_field_from_name_wrap(StandaloneWindowResize, "windowLastHeight"); - il2cpp_field_static_get_value(lastWidthField, &lastWidth); - il2cpp_field_static_get_value(lastHeightField, &lastHeight); + int lastWidth, lastHeight; - if (lastWidth != LOWORD(lParam) || lastHeight != HIWORD(lParam)) - { - RECT windowRect; - GetWindowRect(hWnd, &windowRect); - int windowWidth = windowRect.right - windowRect.left, - windowHeight = windowRect.bottom - windowRect.top; - resizeWindow(hWnd, windowWidth, windowHeight); + il2cpp_field_static_get_value(lastWidthField, &lastWidth); + il2cpp_field_static_get_value(lastHeightField, &lastHeight); + if (lastWidth != LOWORD(lParam) || lastHeight != HIWORD(lParam)) + { + RECT windowRect; + GetWindowRect(hWnd, &windowRect); + int windowWidth = windowRect.right - windowRect.left, + windowHeight = windowRect.bottom - windowRect.top; + resizeWindow(hWnd, windowWidth, windowHeight); - WNDPROC oldWndProcPtr = nullptr; - auto oldWndProcPtrField = il2cpp_class_get_field_from_name_wrap(StandaloneWindowResize, "oldWndProcPtr"); - il2cpp_field_static_get_value(oldWndProcPtrField, &oldWndProcPtr); + WNDPROC oldWndProcPtr = nullptr; + auto oldWndProcPtrField = il2cpp_class_get_field_from_name_wrap(StandaloneWindowResize, "oldWndProcPtr"); + il2cpp_field_static_get_value(oldWndProcPtrField, &oldWndProcPtr); - if (oldWndProcPtr) - { - return CallWindowProcW(oldWndProcPtr, hWnd, uMsg, wParam, lParam); - } - return TRUE; - } + if (oldWndProcPtr) + { + return CallWindowProcW(oldWndProcPtr, hWnd, uMsg, wParam, lParam); } - } - if (uMsg == WM_SIZING && g_freeform_window) - { - auto StandaloneWindowResize = il2cpp_symbols::get_class("umamusume.dll", "Gallop", "StandaloneWindowResize"); - auto lastWidthField = il2cpp_class_get_field_from_name_wrap(StandaloneWindowResize, "windowLastWidth"); - auto lastHeightField = il2cpp_class_get_field_from_name_wrap(StandaloneWindowResize, "windowLastHeight"); + return TRUE; + } + } - int lastWidth, lastHeight; + if (uMsg == WM_SIZING && g_freeform_window) + { + auto StandaloneWindowResize = il2cpp_symbols::get_class("umamusume.dll", "Gallop", "StandaloneWindowResize"); + auto lastWidthField = il2cpp_class_get_field_from_name_wrap(StandaloneWindowResize, "windowLastWidth"); + auto lastHeightField = il2cpp_class_get_field_from_name_wrap(StandaloneWindowResize, "windowLastHeight"); - il2cpp_field_static_get_value(lastWidthField, &lastWidth); - il2cpp_field_static_get_value(lastHeightField, &lastHeight); + int lastWidth, lastHeight; - RECT* rect = reinterpret_cast(lParam); + il2cpp_field_static_get_value(lastWidthField, &lastWidth); + il2cpp_field_static_get_value(lastHeightField, &lastHeight); - if (lastWidth != rect->right - rect->left || lastHeight != rect->bottom - rect->top) - { - RECT windowRect; - GetWindowRect(hWnd, &windowRect); - int windowWidth = windowRect.right - windowRect.left, - windowHeight = windowRect.bottom - windowRect.top; + RECT* rect = reinterpret_cast(lParam); - RECT clientRect; - GetClientRect(hWnd, &clientRect); + if (lastWidth != rect->right - rect->left || lastHeight != rect->bottom - rect->top) + { + RECT windowRect; + GetWindowRect(hWnd, &windowRect); + int windowWidth = windowRect.right - windowRect.left, + windowHeight = windowRect.bottom - windowRect.top; - int frameWidth = windowWidth - clientRect.right; - int frameHeight = windowHeight - clientRect.bottom; + RECT clientRect; + GetClientRect(hWnd, &clientRect); - int contentWidth = rect->right - rect->left - frameWidth; - int contentHeight = rect->bottom - rect->top - frameHeight; + int frameWidth = windowWidth - clientRect.right; + int frameHeight = windowHeight - clientRect.bottom; - bool resizeLeft = wParam == WMSZ_BOTTOMLEFT || wParam == WMSZ_LEFT || wParam == WMSZ_TOPLEFT; - bool resizeTop = wParam == WMSZ_TOP || wParam == WMSZ_TOPLEFT || wParam == WMSZ_TOPRIGHT; + int contentWidth = rect->right - rect->left - frameWidth; + int contentHeight = rect->bottom - rect->top - frameHeight; - if (resizeLeft) - { - rect->left = rect->right - (contentWidth + frameWidth); - } - else - { - rect->right = rect->left + (contentWidth + frameWidth); - } + bool resizeLeft = wParam == WMSZ_BOTTOMLEFT || wParam == WMSZ_LEFT || wParam == WMSZ_TOPLEFT; + bool resizeTop = wParam == WMSZ_TOP || wParam == WMSZ_TOPLEFT || wParam == WMSZ_TOPRIGHT; - if (resizeTop) - { - rect->top = rect->bottom - (contentHeight + frameHeight); - } - else - { - rect->bottom = rect->top + (contentHeight + frameHeight); - } + if (resizeLeft) + { + rect->left = rect->right - (contentWidth + frameWidth); + } + else + { + rect->right = rect->left + (contentWidth + frameWidth); + } - lastWidth = rect->right - rect->left; - lastHeight = rect->bottom - rect->top; + if (resizeTop) + { + rect->top = rect->bottom - (contentHeight + frameHeight); + } + else + { + rect->bottom = rect->top + (contentHeight + frameHeight); + } - il2cpp_field_static_set_value(lastWidthField, &lastWidth); - il2cpp_field_static_set_value(lastHeightField, &lastHeight); + lastWidth = rect->right - rect->left; + lastHeight = rect->bottom - rect->top; - int width = il2cpp_symbols::get_method_pointer("UnityEngine.CoreModule.dll", "UnityEngine", "Screen", "get_width", -1)(); - int height = il2cpp_symbols::get_method_pointer("UnityEngine.CoreModule.dll", "UnityEngine", "Screen", "get_height", -1)(); + il2cpp_field_static_set_value(lastWidthField, &lastWidth); + il2cpp_field_static_set_value(lastHeightField, &lastHeight); - il2cpp_class_get_method_from_name_type(StandaloneWindowResize, "SaveChangedWidth", 2)->methodPointer(width, height); + int width = il2cpp_symbols::get_method_pointer("UnityEngine.CoreModule.dll", "UnityEngine", "Screen", "get_width", -1)(); + int height = il2cpp_symbols::get_method_pointer("UnityEngine.CoreModule.dll", "UnityEngine", "Screen", "get_height", -1)(); - auto _aspectRatioField = il2cpp_class_get_field_from_name_wrap(StandaloneWindowResize, "_aspectRatio"); - float _aspectRatio = contentWidth / contentHeight; - il2cpp_field_static_set_value(_aspectRatioField, &_aspectRatio); - } + il2cpp_class_get_method_from_name_type(StandaloneWindowResize, "SaveChangedWidth", 2)->methodPointer(width, height); - WNDPROC oldWndProcPtr = nullptr; + auto _aspectRatioField = il2cpp_class_get_field_from_name_wrap(StandaloneWindowResize, "_aspectRatio"); + float _aspectRatio = contentWidth / contentHeight; + il2cpp_field_static_set_value(_aspectRatioField, &_aspectRatio); + } - auto oldWndProcPtrField = il2cpp_class_get_field_from_name_wrap(StandaloneWindowResize, "oldWndProcPtr"); - il2cpp_field_static_get_value(oldWndProcPtrField, &oldWndProcPtr); + WNDPROC oldWndProcPtr = nullptr; + auto oldWndProcPtrField = il2cpp_class_get_field_from_name_wrap(StandaloneWindowResize, "oldWndProcPtr"); + il2cpp_field_static_get_value(oldWndProcPtrField, &oldWndProcPtr); - if (oldWndProcPtr) - { - return CallWindowProcW(oldWndProcPtr, hWnd, uMsg, wParam, lParam); - } - return TRUE; + if (oldWndProcPtr) + { + return CallWindowProcW(oldWndProcPtr, hWnd, uMsg, wParam, lParam); } + + return TRUE; } if (uMsg == WM_SIZING && !g_freeform_window) @@ -3788,7 +4205,9 @@ namespace bool isVirt = width < height; if (g_unlock_size) { - UIManager_ChangeResizeUIForPC_hook(uiManager, (isVirt ? last_display_height : last_display_width), (isVirt ? last_display_width : last_display_height)); + UIManager_ChangeResizeUIForPC_hook(uiManager, isVirt ? min(last_display_width, last_display_height) : max(last_display_width, last_display_height), + isVirt ? max(last_display_width, last_display_height) : min(last_display_width, last_display_height)); + } else { @@ -3814,7 +4233,7 @@ namespace { if (isExitOpened) { - exit(0); + ExitProcess(0); return TRUE; } @@ -3885,7 +4304,7 @@ namespace void* Screen_IsCurrentOrientation_orig = nullptr; - bool Screen_IsCurrentOrientation_hook(int target) + bool Screen_IsCurrentOrientation_hook(ScreenOrientation target) { return true; } @@ -4614,10 +5033,336 @@ namespace return obj; } + Il2CppObject* resources_load_hook(Il2CppString* path, Il2CppObject* type); + + Il2CppObject* GetOptionItemTitle(const char* title) + { + auto object = resources_load_hook(il2cpp_string_new("ui/parts/outgame/option/partsoptionitemtitle"), GetRuntimeType("UnityEngine.CoreModule.dll", "UnityEngine", "GameObject")); + + auto optionItemTitle = il2cpp_symbols::get_method_pointer("UnityEngine.CoreModule.dll", "UnityEngine", "Object", "Internal_CloneSingle", 1)(object); + + auto getComponents = il2cpp_class_get_method_from_name_type *(*)(Il2CppObject*, Il2CppType*, bool, bool, bool, bool, Il2CppObject*)>(optionItemTitle->klass, "GetComponentsInternal", 6)->methodPointer; + auto array = getComponents(optionItemTitle, reinterpret_cast(GetRuntimeType( + "umamusume.dll", "Gallop", "TextCommon")), true, true, false, false, nullptr); + + auto textCommon = array->vector[0]; + + text_set_text(textCommon, il2cpp_string_new(title)); + + auto textIdStrField = il2cpp_class_get_field_from_name_wrap(textCommon->klass, "m_textid_str"); + il2cpp_field_set_value(textCommon, textIdStrField, nullptr); + + return optionItemTitle; + } + + Il2CppObject* GetOptionItemOnOff(const char* name, const char* title) + { + auto object = resources_load_hook(il2cpp_string_new("ui/parts/outgame/option/partsoptionitemonoff"), GetRuntimeType("UnityEngine.CoreModule.dll", "UnityEngine", "GameObject")); + + auto optionItemOnOff = il2cpp_symbols::get_method_pointer("UnityEngine.CoreModule.dll", "UnityEngine", "Object", "Internal_CloneSingle", 1)(object); + + uobject_set_name(optionItemOnOff, il2cpp_string_new(name)); + + auto getComponents = il2cpp_class_get_method_from_name_type *(*)(Il2CppObject*, Il2CppType*, bool, bool, bool, bool, Il2CppObject*)>(optionItemOnOff->klass, "GetComponentsInternal", 6)->methodPointer; + auto array = getComponents(optionItemOnOff, reinterpret_cast(GetRuntimeType( + "umamusume.dll", "Gallop", "TextCommon")), true, true, false, false, nullptr); + + auto textCommon = array->vector[0]; + + text_set_text(textCommon, il2cpp_string_new(title)); + + auto textIdStrField = il2cpp_class_get_field_from_name_wrap(textCommon->klass, "m_textid_str"); + il2cpp_field_set_value(textCommon, textIdStrField, nullptr); + + return optionItemOnOff; + } + + void SetOptionItemOnOffAction(const char* name, bool isOn, void (*onChange)(Il2CppObject*, bool)) + { + auto optionItemOnOff = reinterpret_cast(il2cpp_resolve_icall("UnityEngine.GameObject::Find()"))(il2cpp_string_new(name)); + + if (optionItemOnOff) + { + auto getComponents = il2cpp_class_get_method_from_name_type *(*)(Il2CppObject*, Il2CppType*, bool, bool, bool, bool, Il2CppObject*)>(optionItemOnOff->klass, "GetComponentsInternal", 6)->methodPointer; + auto array2 = getComponents(optionItemOnOff, reinterpret_cast(GetRuntimeType( + "umamusume.dll", "Gallop", "PartsOnOffToggleSwitch")), true, true, false, false, nullptr); + + auto toggleSwitch = array2->vector[0]; + + auto action = CreateUnityAction(toggleSwitch, onChange); + il2cpp_class_get_method_from_name_type(toggleSwitch->klass, "Setup", 2)->methodPointer(toggleSwitch, isOn, action); + } + } + + Il2CppObject* GetOptionItemButton(const char* name, const char* title) + { + auto object = resources_load_hook(il2cpp_string_new("ui/parts/outgame/option/partsoptionitembutton"), GetRuntimeType("UnityEngine.CoreModule.dll", "UnityEngine", "GameObject")); + + auto optionItemButton = il2cpp_symbols::get_method_pointer("UnityEngine.CoreModule.dll", "UnityEngine", "Object", "Internal_CloneSingle", 1)(object); + + uobject_set_name(optionItemButton, il2cpp_string_new(name)); + + auto getComponents = il2cpp_class_get_method_from_name_type *(*)(Il2CppObject*, Il2CppType*, bool, bool, bool, bool, Il2CppObject*)>(optionItemButton->klass, "GetComponentsInternal", 6)->methodPointer; + auto array1 = getComponents(optionItemButton, reinterpret_cast(GetRuntimeType( + "umamusume.dll", "Gallop", "TextCommon")), true, true, false, false, nullptr); + + auto textCommon = array1->vector[0]; + + text_set_text(textCommon, il2cpp_string_new(title)); + + auto textIdStrField = il2cpp_class_get_field_from_name_wrap(textCommon->klass, "m_textid_str"); + il2cpp_field_set_value(textCommon, textIdStrField, nullptr); + + auto array2 = getComponents(optionItemButton, reinterpret_cast(GetRuntimeType( + "umamusume.dll", "Gallop", "ButtonCommon")), true, true, false, false, nullptr); + + auto buttonCommon = array2->vector[0]; + + il2cpp_class_get_method_from_name_type(buttonCommon->klass, "SetInteractable", 1)->methodPointer(buttonCommon, true); + + return optionItemButton; + } + + void SetOptionItemButtonAction(const char* name, void (*onClick)(Il2CppObject*)) + { + auto optionItemButton = reinterpret_cast(il2cpp_resolve_icall("UnityEngine.GameObject::Find()"))(il2cpp_string_new(name)); + + if (optionItemButton) + { + auto getComponents = il2cpp_class_get_method_from_name_type *(*)(Il2CppObject*, Il2CppType*, bool, bool, bool, bool, Il2CppObject*)>(optionItemButton->klass, "GetComponentsInternal", 6)->methodPointer; + auto array2 = getComponents(optionItemButton, reinterpret_cast(GetRuntimeType( + "umamusume.dll", "Gallop", "ButtonCommon")), true, true, false, false, nullptr); + + auto buttonCommon = array2->vector[0]; + + auto action = CreateUnityAction(buttonCommon, onClick); + il2cpp_class_get_method_from_name_type(buttonCommon->klass, "SetOnClick", 1)->methodPointer(buttonCommon, action); + } + } + + Il2CppObject* GetOptionItemAttention(const char* text) + { + auto object = resources_load_hook(il2cpp_string_new("ui/parts/outgame/option/partsoptionitemattention"), GetRuntimeType("UnityEngine.CoreModule.dll", "UnityEngine", "GameObject")); + + auto optionItemAttention = il2cpp_symbols::get_method_pointer("UnityEngine.CoreModule.dll", "UnityEngine", "Object", "Internal_CloneSingle", 1)(object); + + auto getComponents = il2cpp_class_get_method_from_name_type *(*)(Il2CppObject*, Il2CppType*, bool, bool, bool, bool, Il2CppObject*)>(optionItemAttention->klass, "GetComponentsInternal", 6)->methodPointer; + auto array = getComponents(optionItemAttention, reinterpret_cast(GetRuntimeType( + "umamusume.dll", "Gallop", "TextCommon")), true, true, false, false, nullptr); + + auto textCommon = array->vector[0]; + + text_set_text(textCommon, il2cpp_string_new(text)); + + auto textIdStrField = il2cpp_class_get_field_from_name_wrap(textCommon->klass, "m_textid_str"); + il2cpp_field_set_value(textCommon, textIdStrField, nullptr); + + return optionItemAttention; + } + + Il2CppObject* GetOptionItemInfo(const char* text) + { + auto object = resources_load_hook(il2cpp_string_new("ui/parts/outgame/option/partsoptioniteminfo"), GetRuntimeType("UnityEngine.CoreModule.dll", "UnityEngine", "GameObject")); + + auto optionItemInfo = il2cpp_symbols::get_method_pointer("UnityEngine.CoreModule.dll", "UnityEngine", "Object", "Internal_CloneSingle", 1)(object); + + auto getComponents = il2cpp_class_get_method_from_name_type *(*)(Il2CppObject*, Il2CppType*, bool, bool, bool, bool, Il2CppObject*)>(optionItemInfo->klass, "GetComponentsInternal", 6)->methodPointer; + auto array = getComponents(optionItemInfo, reinterpret_cast(GetRuntimeType( + "umamusume.dll", "Gallop", "TextCommon")), true, true, false, false, nullptr); + + auto textCommon = array->vector[0]; + + text_set_text(textCommon, il2cpp_string_new(text)); + + auto textIdStrField = il2cpp_class_get_field_from_name_wrap(textCommon->klass, "m_textid_str"); + il2cpp_field_set_value(textCommon, textIdStrField, nullptr); + + return optionItemInfo; + } + + Il2CppObject* GetOptionItemSimple(const char* title) + { + auto object = resources_load_hook(il2cpp_string_new("ui/parts/outgame/option/partsoptionitemsimple"), GetRuntimeType("UnityEngine.CoreModule.dll", "UnityEngine", "GameObject")); + + auto optionItemSimple = il2cpp_symbols::get_method_pointer("UnityEngine.CoreModule.dll", "UnityEngine", "Object", "Internal_CloneSingle", 1)(object); + + auto getComponents = il2cpp_class_get_method_from_name_type *(*)(Il2CppObject*, Il2CppType*, bool, bool, bool, bool, Il2CppObject*)>(optionItemSimple->klass, "GetComponentsInternal", 6)->methodPointer; + auto array = getComponents(optionItemSimple, reinterpret_cast(GetRuntimeType( + "umamusume.dll", "Gallop", "TextCommon")), true, true, false, false, nullptr); + + auto textCommon = array->vector[0]; + + text_set_text(textCommon, il2cpp_string_new(title)); + + auto textIdStrField = il2cpp_class_get_field_from_name_wrap(textCommon->klass, "m_textid_str"); + il2cpp_field_set_value(textCommon, textIdStrField, nullptr); + + return optionItemSimple; + } + + Il2CppObject* GetRectTransform(Il2CppObject* object) + { + auto getComponents = il2cpp_class_get_method_from_name_type *(*)(Il2CppObject*, Il2CppType*, bool, bool, bool, bool, Il2CppObject*)>(object->klass, "GetComponentsInternal", 6)->methodPointer; + auto rectTransformArray = getComponents(object, reinterpret_cast(GetRuntimeType( + "UnityEngine.CoreModule.dll", "UnityEngine", "RectTransform")), true, true, false, false, nullptr); + + if (rectTransformArray->max_length) + { + return rectTransformArray->vector[0]; + } + + return nullptr; + } + + void AddToLayout(Il2CppObject* parentRectTransform, vector objects) + { + for (int i = objects.size() - 1; i >= 0; i--) + //for (int i = 0; i < objects.size(); i++) + { + auto rectTransform = GetRectTransform(objects[i]); + il2cpp_class_get_method_from_name_type(rectTransform->klass, "SetParent", 1)->methodPointer(rectTransform, parentRectTransform); + il2cpp_class_get_method_from_name_type(rectTransform->klass, "SetAsFirstSibling", 0)->methodPointer(rectTransform); + } + } + + void OpenSettings() + { + auto dialogData = il2cpp_object_new( + il2cpp_symbols::get_class("umamusume.dll", "Gallop", "DialogCommon/Data")); + il2cpp_runtime_object_init(dialogData); + + auto onLeft = CreateDelegate(dialogData, *([](Il2CppObject*) + { + cout << "onLeft" << endl; + })); + + auto onRight = CreateDelegate(dialogData, *([](Il2CppObject*) + { + cout << "onRight" << endl; + })); + + dialogData = reinterpret_cast( + il2cpp_class_get_method_from_name(dialogData->klass, "SetSimpleTwoButtonMessage", + 7)->methodPointer + )(dialogData, il2cpp_string_new("Localify Settings"), nullptr, onRight, GetTextIdByName("Common0004"), GetTextIdByName("Common0261"), onLeft, 10); + + cout << "dialogData " << dialogData << endl; + + auto DispStackTypeField = il2cpp_class_get_field_from_name_wrap(dialogData->klass, "DispStackType"); + int DispStackType = 1; + il2cpp_field_set_value(dialogData, DispStackTypeField, &DispStackType); + + auto ObjParentTypeField = il2cpp_class_get_field_from_name_wrap(dialogData->klass, "ObjParentType"); + int ObjParentType = 1; + il2cpp_field_set_value(dialogData, ObjParentTypeField, &ObjParentType); + + auto basicSetting = resources_load_hook(il2cpp_string_new("ui/parts/outgame/option/partsoptionpagebasicsetting"), GetRuntimeType("UnityEngine.CoreModule.dll", "UnityEngine", "GameObject")); + + auto uiManager = GetSingletonInstance(il2cpp_symbols::get_class("umamusume.dll", "Gallop", "UIManager")); + auto _mainCanvasField = il2cpp_class_get_field_from_name_wrap(uiManager->klass, "_mainCanvas"); + Il2CppObject* _mainCanvas; + il2cpp_field_get_value(uiManager, _mainCanvasField, &_mainCanvas); + + auto transform = il2cpp_class_get_method_from_name_type(_mainCanvas->klass, "get_transform", 0)->methodPointer(_mainCanvas); + + basicSetting = il2cpp_symbols::get_method_pointer("UnityEngine.CoreModule.dll", "UnityEngine", "Object", "Internal_CloneSingleWithParent", 3) + (basicSetting, transform, false); + + cout << "basicSetting " << basicSetting << endl; + + auto getComponents = il2cpp_class_get_method_from_name_type *(*)(Il2CppObject*, Il2CppType*, bool, bool, bool, bool, Il2CppObject*)>(basicSetting->klass, "GetComponentsInternal", 6)->methodPointer; + + auto rectTransformArray = getComponents(basicSetting, reinterpret_cast(GetRuntimeType( + "UnityEngine.CoreModule.dll", "UnityEngine", "RectTransform")), true, true, false, false, nullptr); + + for (int j = 0; j < rectTransformArray->max_length; j++) + { + auto rectTransform = rectTransformArray->vector[j]; + + if (rectTransform && local::wide_u8(uobject_get_name(rectTransform)->start_char) == "Content") + { + // il2cpp_resolve_icall_type("UnityEngine.Transform::DetachChildren()")(rectTransform); + break; + } + } + + auto ContentsObjectField = il2cpp_class_get_field_from_name_wrap(dialogData->klass, "ContentsObject"); + + il2cpp_field_set_value(dialogData, ContentsObjectField, basicSetting); + + il2cpp_symbols::get_method_pointer("umamusume.dll", "Gallop", "DialogManager", "PushDialog", 1)(dialogData); + } + + void InitOptionLayout(Il2CppObject* parentRectTransform) + { + AddToLayout(parentRectTransform, + { + GetOptionItemTitle("Localify Settings"), + GetOptionItemButton("open_settings", "Open Settings"), + GetOptionItemButton("show_caption", "Show caption"), + GetOptionItemAttention("Attention with Color\nAttention"), + GetOptionItemSimple("Simple"), + GetOptionItemOnOff("on_off", "On Off"), + GetOptionItemInfo("Info with Color\nInfo"), + } + ); + } + + void SetupOptionLayout() + { + SetOptionItemButtonAction("open_settings", *([](Il2CppObject*) + { + // OpenSettings(); + auto uiManager = GetSingletonInstance(il2cpp_symbols::get_class("umamusume.dll", "Gallop", "UIManager")); + + il2cpp_class_get_method_from_name_type(uiManager->klass, "ShowNotification", 1)->methodPointer(uiManager, localize_get_hook(GetTextIdByName("Home0072"))); + })); + + SetOptionItemOnOffAction("on_off", false, *([](Il2CppObject*, bool isOn) + { + auto uiManager = GetSingletonInstance(il2cpp_symbols::get_class("umamusume.dll", "Gallop", "UIManager")); + + stringstream text; + + text << "Changed to " << (isOn ? "On" : "Off"); + + il2cpp_class_get_method_from_name_type(uiManager->klass, "ShowNotification", 1)->methodPointer(uiManager, il2cpp_string_new(text.str().data())); + })); + + SetOptionItemButtonAction("show_caption", *([](Il2CppObject*) + { + SetNotificationDisplayTime(1); + ShowNotification(il2cpp_string_new("Sample caption")); + })); + } + + void* Object_Internal_CloneSingleWithParent_orig = nullptr; + Il2CppObject* Object_Internal_CloneSingleWithParent_hook(Il2CppObject* data, Il2CppObject* parent, bool worldPositionStays) + { + auto cloned = reinterpret_cast(Object_Internal_CloneSingleWithParent_orig)(data, parent, worldPositionStays); + + if (wstring(uobject_get_name(cloned)->start_char).find(L"DialogOptionHome") != wstring::npos) + { + SetupOptionLayout(); + } + + return cloned; + } + + Il2CppObject* currentOptionObj = nullptr; + void* resources_load_orig = nullptr; - Il2CppObject* resources_load_hook(Il2CppString* path, Il2CppType* type) + Il2CppObject* resources_load_hook(Il2CppString* path, Il2CppObject* type) { string u8Name = local::wide_u8(path->start_char); + if (u8Name == "ui/views/titleview"s) { if (find_if(replaceAssetNames.begin(), replaceAssetNames.end(), [](const string& item) @@ -4640,6 +5385,7 @@ namespace return gameObj; } } + if (u8Name == "TMP Settings"s && g_replace_to_custom_font && fontAssets) { auto object = reinterpret_cast(resources_load_orig)(path, type); @@ -4647,6 +5393,76 @@ namespace il2cpp_field_set_value(object, fontAssetField, GetCustomTMPFont()); return object; } + + if (u8Name.ends_with("dialogoptionhome")) + { + auto object = reinterpret_cast(resources_load_orig)(path, type); + + if (object != currentOptionObj) + { + currentOptionObj = object; + } + else + { + return object; + } + + auto getComponents = il2cpp_class_get_method_from_name_type *(*)(Il2CppObject*, Il2CppType*, bool, bool, bool, bool, Il2CppObject*)>(object->klass, "GetComponentsInternal", 6)->methodPointer; + + il2cpp_class_get_method_from_name_type(object->klass, "SetActive", 1)->methodPointer(object, true); + + + auto array = getComponents(object, reinterpret_cast(GetRuntimeType( + "umamusume.dll", "Gallop", "PartsOptionPageBasicSetting")), true, true, false, false, nullptr); + + if (array) + { + for (int i = 0; i < array->max_length; i++) + { + auto obj = array->vector[i]; + + if (obj && obj->klass->name == "PartsOptionPageBasicSetting"s) + { + auto _notityObjListField = il2cpp_class_get_field_from_name_wrap(obj->klass, "_notityObjList"); + Il2CppObject* _notityObjList; + il2cpp_field_get_value(obj, _notityObjListField, &_notityObjList); + + if (_notityObjList) + { + il2cpp_class_get_method_from_name_type(_notityObjList->klass, "Clear", 0)->methodPointer(_notityObjList); + } + + /*auto _fpsObjListField = il2cpp_class_get_field_from_name_wrap(obj->klass, "_fpsObjList"); + Il2CppObject* _fpsObjList; + il2cpp_field_get_value(obj, _fpsObjListField, &_fpsObjList); + + if (_fpsObjList) + { + il2cpp_class_get_method_from_name_type(_fpsObjList->klass, "Clear", 0)->methodPointer(_fpsObjList); + }*/ + + auto gameObject = il2cpp_class_get_method_from_name_type(obj->klass, "get_gameObject", 0)->methodPointer(obj); + + auto rectTransformArray = getComponents(gameObject, reinterpret_cast(GetRuntimeType( + "UnityEngine.CoreModule.dll", "UnityEngine", "RectTransform")), true, true, false, false, nullptr); + + for (int j = 0; j < rectTransformArray->max_length; j++) + { + auto rectTransform = rectTransformArray->vector[j]; + + if (rectTransform && local::wide_u8(uobject_get_name(rectTransform)->start_char) == "Content") + { + InitOptionLayout(rectTransform); + break; + } + } + } + } + } + + return object; + } + return reinterpret_cast(resources_load_orig)(path, type); } @@ -4914,8 +5730,10 @@ namespace }; void* GameObject_GetComponentFastPath_orig = nullptr; - void GameObject_GetComponentFastPath_hook(Il2CppObject* _this, const Il2CppType* type, uintptr_t oneFurtherThanResultValue) + void GameObject_GetComponentFastPath_hook(Il2CppObject* _this, Il2CppObject* type, uintptr_t oneFurtherThanResultValue) { + /*auto name = il2cpp_class_get_method_from_name_type(type->klass, "get_FullName", 0)->methodPointer(type); + cout << "GameObject_GetComponentFastPath " << local::wide_u8(name->start_char) << endl;*/ reinterpret_cast(GameObject_GetComponentFastPath_orig)(_this, type, oneFurtherThanResultValue); auto helper = CastHelper{}; int objSize = sizeof(helper.obj); @@ -4988,6 +5806,8 @@ namespace { if (g_freeform_window) { + reinterpret_cast(Screen_RequestOrientation_orig)(ScreenOrientation::AutoRotation); + auto title = local::u8_wide(g_custom_title_name); if (title.empty()) { @@ -5150,8 +5970,6 @@ namespace // no-op } - struct MoviePlayerHandle {}; - Il2CppObject* (*MoviePlayerBase_get_MovieInfo)(Il2CppObject* _this); Il2CppObject* (*MovieManager_GetMovieInfo)(Il2CppObject* _this, MoviePlayerHandle playerHandle); @@ -5160,6 +5978,11 @@ namespace void MovieManager_SetImageUvRect_hook(Il2CppObject* _this, MoviePlayerHandle playerHandle, Rect_t uv) { auto movieInfo = MovieManager_GetMovieInfo(_this, playerHandle); + if (!movieInfo) + { + return; + } + auto widthField = il2cpp_class_get_field_from_name_wrap(movieInfo->klass, "width"); auto heightField = il2cpp_class_get_field_from_name_wrap(movieInfo->klass, "height"); unsigned int width, height; @@ -5184,70 +6007,91 @@ namespace void MovieManager_SetScreenSize_hook(Il2CppObject* _this, MoviePlayerHandle playerHandle, Vector2_t screenSize) { auto movieInfo = MovieManager_GetMovieInfo(_this, playerHandle); - auto widthField = il2cpp_class_get_field_from_name_wrap(movieInfo->klass, "width"); - auto heightField = il2cpp_class_get_field_from_name_wrap(movieInfo->klass, "height"); - unsigned int width, height; - il2cpp_field_get_value(movieInfo, widthField, &width); - il2cpp_field_get_value(movieInfo, heightField, &height); - if (width < height && !is_virt()) + if (!movieInfo) { - int rWidth = il2cpp_symbols::get_method_pointer("UnityEngine.CoreModule.dll", "UnityEngine", "Screen", "get_width", -1)(); - int rHeight = il2cpp_symbols::get_method_pointer("UnityEngine.CoreModule.dll", "UnityEngine", "Screen", "get_height", -1)(); - if (roundf(ratio_horizontal * (max(1.0f, rHeight * ratio_vertical) * (g_freeform_window ? g_freeform_ui_scale_landscape : g_ui_scale))) == screenSize.y) - { - screenSize.y = rWidth; - } - screenSize.x = rHeight; + return; } - reinterpret_cast(MovieManager_SetScreenSize_orig)(_this, playerHandle, screenSize); - } - - void* MoviePlayerForUI_AdjustScreenSize_orig = nullptr; - - void MoviePlayerForUI_AdjustScreenSize_hook(Il2CppObject* _this, Vector2_t dispRectWH, bool isPanScan) - { - auto movieInfo = MoviePlayerBase_get_MovieInfo(_this); auto widthField = il2cpp_class_get_field_from_name_wrap(movieInfo->klass, "width"); auto heightField = il2cpp_class_get_field_from_name_wrap(movieInfo->klass, "height"); unsigned int width, height; il2cpp_field_get_value(movieInfo, widthField, &width); il2cpp_field_get_value(movieInfo, heightField, &height); - auto ratio = floorf(static_cast(width) / height * 100) / 100; - if ((width < height || ratio == 1.33f) && !is_virt()) + if (width < height && !is_virt()) { int rWidth = il2cpp_symbols::get_method_pointer("UnityEngine.CoreModule.dll", "UnityEngine", "Screen", "get_width", -1)(); int rHeight = il2cpp_symbols::get_method_pointer("UnityEngine.CoreModule.dll", "UnityEngine", "Screen", "get_height", -1)(); - if (roundf(ratio_horizontal * (max(1.0f, rHeight * ratio_vertical) * (g_freeform_window ? g_freeform_ui_scale_landscape : g_ui_scale))) == dispRectWH.y) + if (roundf(ratio_horizontal * (max(1.0f, rHeight * ratio_vertical) * (g_freeform_window ? g_freeform_ui_scale_landscape : g_ui_scale))) == screenSize.y) { - dispRectWH.y = rWidth; + screenSize.y = rWidth; } - dispRectWH.x = rHeight; + screenSize.x = rHeight; } - reinterpret_cast(MoviePlayerForUI_AdjustScreenSize_orig)(_this, dispRectWH, isPanScan); + + reinterpret_cast(MovieManager_SetScreenSize_orig)(_this, playerHandle, screenSize); } - void* MoviePlayerForObj_AdjustScreenSize_orig = nullptr; + void* MoviePlayerForUI_AdjustScreenSize_orig = nullptr; - void MoviePlayerForObj_AdjustScreenSize_hook(Il2CppObject* _this, Vector2_t dispRectWH, bool isPanScan) + void MoviePlayerForUI_AdjustScreenSize_hook(Il2CppObject* _this, Vector2_t dispRectWH, bool isPanScan) { auto movieInfo = MoviePlayerBase_get_MovieInfo(_this); + if (!movieInfo) + { + return; + } + auto widthField = il2cpp_class_get_field_from_name_wrap(movieInfo->klass, "width"); auto heightField = il2cpp_class_get_field_from_name_wrap(movieInfo->klass, "height"); + unsigned int width, height; il2cpp_field_get_value(movieInfo, widthField, &width); il2cpp_field_get_value(movieInfo, heightField, &height); - if (width < height && !is_virt()) + + auto ratio = floorf(static_cast(width) / height * 100) / 100; + auto ratio1 = static_cast(width) / static_cast(height); + + if ((width < height || ratio == 1.33f) && !is_virt()) { - int rWidth = il2cpp_symbols::get_method_pointer("UnityEngine.CoreModule.dll", "UnityEngine", "Screen", "get_width", -1)(); - int rHeight = il2cpp_symbols::get_method_pointer("UnityEngine.CoreModule.dll", "UnityEngine", "Screen", "get_height", -1)(); + int rWidth; + int rHeight; + + auto GallopScreen = il2cpp_symbols::get_class("umamusume.dll", "Gallop", "Screen"); + + auto NUMBER1920_Field = il2cpp_class_get_field_from_name_wrap(GallopScreen, "NUMBER1920"); + + auto NUMBER1080_Field = il2cpp_class_get_field_from_name_wrap(GallopScreen, "NUMBER1080"); + + int number1920; + int number1080; + + il2cpp_field_static_get_value(NUMBER1920_Field, &number1920); + il2cpp_field_static_get_value(NUMBER1080_Field, &number1080); + + rWidth = number1920; + rHeight = number1080; + if (roundf(ratio_horizontal * (max(1.0f, rHeight * ratio_vertical) * (g_freeform_window ? g_freeform_ui_scale_landscape : g_ui_scale))) == dispRectWH.y) { dispRectWH.y = rWidth; + dispRectWH.x = rHeight; + } + else + { + float scale = min(g_freeform_ui_scale_landscape, max(1, rWidth / ratio_horizontal) * g_freeform_ui_scale_landscape); + + if (roundf(dispRectWH.y * scale) != rHeight) + { + dispRectWH.x = dispRectWH.y * ratio_16_9; + } + else + { + dispRectWH.x = dispRectWH.y * ratio1; + } } - dispRectWH.x = rHeight; } - reinterpret_cast(MoviePlayerForObj_AdjustScreenSize_orig)(_this, dispRectWH, isPanScan); + + reinterpret_cast(MoviePlayerForUI_AdjustScreenSize_orig)(_this, dispRectWH, isPanScan); } void* FrameRateController_OverrideByNormalFrameRate_orig = nullptr; @@ -5328,6 +6172,126 @@ namespace return reinterpret_cast(CriMana_Player_SetFile_orig)(_this, binder, moviePath, setMode); } + Il2CppObject* voiceButtonTarget = nullptr; + + Il2CppDelegate* updateVoiceButton = nullptr; + + void UpdateVoiceButton() + { + Il2CppArraySize_t* voiceButtonList; + if (Game::CurrentGameRegion == Game::Region::KOR) + { + voiceButtonList = il2cpp_resolve_icall_type*(*)(Il2CppObject*, int, int)>("UnityEngine.Object::FindObjectsByType()")( + GetRuntimeType("umamusume.dll", "Gallop", "PartsEpisodeExtraVoiceButton"), 0, 0); + } + else + { + voiceButtonList = il2cpp_resolve_icall_type*(*)(Il2CppObject*, bool)>("UnityEngine.Object::FindObjectsOfType()")( + GetRuntimeType("umamusume.dll", "Gallop", "PartsEpisodeExtraVoiceButton"), false); + } + + if (voiceButtonList && voiceButtonList->max_length) + { + for (int i = 0; i < voiceButtonList->max_length; i++) + { + auto voiceButton = voiceButtonList->vector[i]; + + if (voiceButton) + { + auto buttonField = il2cpp_class_get_field_from_name_wrap(voiceButton->klass, "_playVoiceButton"); + Il2CppObject* button; + il2cpp_field_get_value(voiceButton, buttonField, &button); + + auto callback = GetButtonCommonOnClickDelegate(button); + if (callback) + { + if (voiceButtonTarget != callback->target) + { + voiceButtonTarget = callback->target; + + auto newFn = *( + [](Il2CppObject* _this) + { + auto storyIdField = il2cpp_class_get_field_from_name_wrap(voiceButtonTarget->klass, "storyId"); + int storyId; + il2cpp_field_get_value(voiceButtonTarget, storyIdField, &storyId); + + auto masterDataManager = GetSingletonInstance( + il2cpp_symbols::get_class( + "umamusume.dll", "Gallop", + "MasterDataManager")); + auto masterBannerData = il2cpp_class_get_method_from_name_type( + masterDataManager->klass, + "get_masterBannerData", + 0)->methodPointer(masterDataManager); + + auto bannerList = il2cpp_class_get_method_from_name_type( + masterBannerData->klass, + "GetListWithGroupId", + 1)->methodPointer(masterBannerData, + 7); + + FieldInfo* itemsField = il2cpp_class_get_field_from_name_wrap( + bannerList->klass, "_items"); + Il2CppArraySize* arr; + il2cpp_field_get_value(bannerList, itemsField, + &arr); + + int announceId = -1; + + for (int i = 0; i < arr->max_length; i++) + { + auto item = reinterpret_cast(arr->vector[i]); + if (item) + { + auto typeField = il2cpp_class_get_field_from_name_wrap( + item->klass, "Type"); + int type; + il2cpp_field_get_value(item, typeField, + &type); + auto conditionValueField = il2cpp_class_get_field_from_name_wrap( + item->klass, "ConditionValue"); + int conditionValue; + il2cpp_field_get_value(item, + conditionValueField, + &conditionValue); + if (type == 7 && + conditionValue == storyId) + { + auto transitionField = il2cpp_class_get_field_from_name_wrap( + item->klass, "Transition"); + il2cpp_field_get_value(item, + transitionField, + &announceId); + break; + } + } + } + + if (announceId == -1 && storyId < 1005) + { + announceId = storyId - 1002; + } + + auto action = CreateDelegate(voiceButtonTarget, *([](Il2CppObject*) {})); + + il2cpp_symbols::get_method_pointer( + "umamusume.dll", "Gallop", + "DialogAnnounceEvent", "Open", 3)(announceId, action, action); + }); + il2cpp_class_get_method_from_name_type(button->klass, "SetOnClick", 1)->methodPointer(button, + CreateUnityAction(voiceButtonTarget, newFn)); + } + } + } + } + } + } + void* PartsEpisodeList_SetupStoryExtraEpisodeList_orig = nullptr; void PartsEpisodeList_SetupStoryExtraEpisodeList_hook(Il2CppObject* _this, Il2CppObject* extraSubCategory, Il2CppObject* partDataList, Il2CppObject* partData, Il2CppDelegate* onClick) @@ -5476,7 +6440,6 @@ namespace Il2CppObject* UIManager_WaitBootSetup_hook(Il2CppObject* _this) { - cout << "UIManager_WaitBootSetup_hook" << endl; auto enumerator = reinterpret_cast(UIManager_WaitBootSetup_orig)(_this); auto move_next = il2cpp_class_get_method_from_name_typeklass, "UNCHEATER_DATA"); + auto array = il2cpp_array_new(il2cpp_symbols::get_class("mscorlib.dll", "System", "Object"), 128); + + auto byteArray = il2cpp_array_new(il2cpp_symbols::get_class("mscorlib.dll", "System", "Byte"), 0); + + il2cpp_array_setref(array, 8, byteArray); + il2cpp_array_setref(array, 9, byteArray); + + il2cpp_field_static_set_value(binArrayField, array); + } + if (!mh_inited) return; @@ -5655,6 +6632,10 @@ namespace "UnityEngine.CoreModule.dll", "UnityEngine", "Object", "GetName", -1); + uobject_set_name = il2cpp_symbols::get_method_pointer( + "UnityEngine.CoreModule.dll", "UnityEngine", + "Object", "SetName", 2); + uobject_IsNativeObjectAlive = il2cpp_symbols::get_method_pointer( "UnityEngine.CoreModule.dll", "UnityEngine", "Object", "IsNativeObjectAlive", 1); @@ -6066,12 +7047,16 @@ namespace auto UIManager_WaitBootSetup_addr = il2cpp_symbols::get_method_pointer("umamusume.dll", "Gallop", "UIManager", "WaitBootSetup", 0); + auto Object_Internal_CloneSingleWithParent_addr = il2cpp_resolve_icall("UnityEngine.Object::Internal_CloneSingleWithParent()"); + auto Input_get_mousePosition_Injected_addr = il2cpp_resolve_icall("UnityEngine.Input::get_mousePosition_Injected(UnityEngine.Vector3&)"); auto load_scene_internal_addr = il2cpp_resolve_icall("UnityEngine.SceneManagement.SceneManager::LoadSceneAsyncNameIndexInternal_Injected(System.String,System.Int32,UnityEngine.SceneManagement.LoadSceneParameters&,System.bool)"); #pragma endregion + ADD_HOOK(Object_Internal_CloneSingleWithParent, "UnityEngine.Object::Internal_CloneSingleWithParent at %p\n"); + // ADD_HOOK(UIManager_WaitBootSetup, "Gallop.UIManager::WaitBootSetup at %p\n"); ADD_HOOK(PartsEpisodeList_SetupStoryExtraEpisodeList, "Gallop.PartsEpisodeList::SetupStoryExtraEpisodeList at %p\n"); @@ -6210,12 +7195,12 @@ namespace "umamusume.dll", "", "UncheaterInit", "OnApplicationPause", 1);*/ - auto SplashViewController_KakaoStart_addr = il2cpp_symbols::get_method_pointer( - "umamusume.dll", - "Gallop", "SplashViewController", "KakaoStart", 0); + /*auto SplashViewController_KakaoStart_addr = il2cpp_symbols::get_method_pointer( + "umamusume.dll", + "Gallop", "SplashViewController", "KakaoStart", 0);*/ - // ADD_HOOK(UncheaterInit_OnApplicationPause, "UncheaterInit::OnApplicationPause at %p\n"); - ADD_HOOK(SplashViewController_KakaoStart, "SplashViewController::KakaoStart at %p\n"); + // ADD_HOOK(UncheaterInit_OnApplicationPause, "UncheaterInit::OnApplicationPause at %p\n"); + // ADD_HOOK(SplashViewController_KakaoStart, "SplashViewController::KakaoStart at %p\n"); } if (g_unlock_size || g_freeform_window) @@ -6354,6 +7339,8 @@ namespace } } + Il2CppDelegate* moviePlayerResize = nullptr; + void patch_after_criware() { auto get_virt_size_addr = il2cpp_symbols::get_method_pointer( @@ -6376,6 +7363,8 @@ namespace "Screen", "get_Height", 0 ); + auto Camera_set_orthographicSize_addr = il2cpp_resolve_icall("UnityEngine.Camera::set_orthographicSize(System.Single)"); + auto RectTransform_get_rect_Injected_addr = il2cpp_resolve_icall("UnityEngine.RectTransform::get_rect_Injected(UnityEngine.Rect&)"); auto ChangeScreenOrientation_addr = il2cpp_symbols::get_method_pointer( @@ -6421,9 +7410,6 @@ namespace auto MoviePlayerForUI_AdjustScreenSize_addr = il2cpp_symbols::get_method_pointer( "Cute.Cri.Assembly.dll", "Cute.Cri", "MoviePlayerForUI", "AdjustScreenSize", 2); - auto MoviePlayerForObj_AdjustScreenSize_addr = il2cpp_symbols::get_method_pointer( - "Cute.Cri.Assembly.dll", "Cute.Cri", "MoviePlayerForObj", "AdjustScreenSize", 2); - auto assetbundle_LoadFromFile_addr = il2cpp_resolve_icall("UnityEngine.AssetBundle::LoadFromFile_Internal(System.String,System.UInt32,System.UInt64)"); auto AssetBundleRequest_GetResult_addr = il2cpp_symbols::get_method_pointer( @@ -6434,7 +7420,7 @@ namespace auto assetbundle_unload_addr = il2cpp_symbols::get_method_pointer("UnityEngine.AssetBundleModule.dll", "UnityEngine", "AssetBundle", "Unload", 1); - auto resources_load_addr = il2cpp_symbols::get_method_pointer("UnityEngine.CoreModule.dll", "UnityEngine", "Resources", "Load", 2); + auto resources_load_addr = il2cpp_resolve_icall("UnityEngine.ResourcesAPIInternal::Load()"); auto Sprite_get_texture_addr = il2cpp_resolve_icall("UnityEngine.Sprite::get_texture(UnityEngine.Sprite)"); @@ -6561,15 +7547,15 @@ namespace ADD_HOOK(assetbundle_unload, "UnityEngine.AssetBundle::Unload at %p\n"); + ADD_HOOK(resources_load, "UnityEngine.Resources::Load at %p\n"); + if (!replaceAssets.empty()) { ADD_HOOK(assetbundle_load_asset, "UnityEngine.AssetBundle::LoadAsset at %p\n"); - ADD_HOOK(resources_load, "UnityEngine.Resources::Load at %p\n"); - ADD_HOOK(GameObject_GetComponent, "UnityEngine.GameObject::GetComponent at %p\n"); - ADD_HOOK(GameObject_GetComponentFastPath, "UnityEngine.GameObject::GetComponentFastPath at %p\n"); + // ADD_HOOK(GameObject_GetComponentFastPath, "UnityEngine.GameObject::GetComponentFastPath at %p\n"); ADD_HOOK(Sprite_get_texture, "UnityEngine.Sprite::get_texture at %p\n"); @@ -6634,19 +7620,42 @@ namespace il2cpp_field_static_set_value(_originalScreenHeight_Field, &height); } + auto SCREEN_ORIENTATION_CATEGORIES_Field = il2cpp_class_get_field_from_name_wrap(GallopScreen, "SCREEN_ORIENTATION_CATEGORIES"); + Il2CppObject* SCREEN_ORIENTATION_CATEGORIES; + il2cpp_field_static_get_value(SCREEN_ORIENTATION_CATEGORIES_Field, &SCREEN_ORIENTATION_CATEGORIES); + + if (width < height) + { + il2cpp_class_get_method_from_name_type(SCREEN_ORIENTATION_CATEGORIES->klass, "Clear", 0)->methodPointer(SCREEN_ORIENTATION_CATEGORIES); + il2cpp_class_get_method_from_name_type(SCREEN_ORIENTATION_CATEGORIES->klass, "Add", 2)->methodPointer(SCREEN_ORIENTATION_CATEGORIES, ScreenOrientation::Portrait, ScreenOrientation::Portrait); + il2cpp_class_get_method_from_name_type(SCREEN_ORIENTATION_CATEGORIES->klass, "Add", 2)->methodPointer(SCREEN_ORIENTATION_CATEGORIES, ScreenOrientation::PortraitUpsideDown, ScreenOrientation::Portrait); + il2cpp_class_get_method_from_name_type(SCREEN_ORIENTATION_CATEGORIES->klass, "Add", 2)->methodPointer(SCREEN_ORIENTATION_CATEGORIES, ScreenOrientation::LandscapeLeft, ScreenOrientation::Portrait); + il2cpp_class_get_method_from_name_type(SCREEN_ORIENTATION_CATEGORIES->klass, "Add", 2)->methodPointer(SCREEN_ORIENTATION_CATEGORIES, ScreenOrientation::LandscapeRight, ScreenOrientation::Portrait); + il2cpp_class_get_method_from_name_type(SCREEN_ORIENTATION_CATEGORIES->klass, "Add", 2)->methodPointer(SCREEN_ORIENTATION_CATEGORIES, ScreenOrientation::AutoRotation, ScreenOrientation::Portrait); + } + else + { + il2cpp_class_get_method_from_name_type(SCREEN_ORIENTATION_CATEGORIES->klass, "Clear", 0)->methodPointer(SCREEN_ORIENTATION_CATEGORIES); + il2cpp_class_get_method_from_name_type(SCREEN_ORIENTATION_CATEGORIES->klass, "Add", 2)->methodPointer(SCREEN_ORIENTATION_CATEGORIES, ScreenOrientation::Portrait, ScreenOrientation::LandscapeLeft); + il2cpp_class_get_method_from_name_type(SCREEN_ORIENTATION_CATEGORIES->klass, "Add", 2)->methodPointer(SCREEN_ORIENTATION_CATEGORIES, ScreenOrientation::PortraitUpsideDown, ScreenOrientation::LandscapeLeft); + il2cpp_class_get_method_from_name_type(SCREEN_ORIENTATION_CATEGORIES->klass, "Add", 2)->methodPointer(SCREEN_ORIENTATION_CATEGORIES, ScreenOrientation::LandscapeLeft, ScreenOrientation::LandscapeLeft); + il2cpp_class_get_method_from_name_type(SCREEN_ORIENTATION_CATEGORIES->klass, "Add", 2)->methodPointer(SCREEN_ORIENTATION_CATEGORIES, ScreenOrientation::LandscapeRight, ScreenOrientation::LandscapeLeft); + il2cpp_class_get_method_from_name_type(SCREEN_ORIENTATION_CATEGORIES->klass, "Add", 2)->methodPointer(SCREEN_ORIENTATION_CATEGORIES, ScreenOrientation::AutoRotation, ScreenOrientation::LandscapeLeft); + } + + ADD_HOOK(Camera_set_orthographicSize, "UnityEngine.Camera::set_orthographicSize at %p\n"); ADD_HOOK(RectTransform_get_rect_Injected, "UnityEngine.RectTransform::get_rect_Injected at %p\n"); ADD_HOOK(WaitDeviceOrientation, "Gallop.Screen::WaitDeviceOrientation at %p\n"); - ADD_HOOK(Screen_set_orientation, "Gallop.Screen::set_orientation at %p\n"); + // ADD_HOOK(Screen_set_orientation, "Gallop.Screen::set_orientation at %p\n"); ADD_HOOK(Screen_RequestOrientation, "UnityEngine.Screen::RequestOrientation at %p\n"); ADD_HOOK(DeviceOrientationGuide_Show, "DeviceOrientationGuide::Show at %p\n"); - ADD_HOOK(ChangeScreenOrientation, "ChangeScreenOrientation at %p\n"); - ADD_HOOK(ChangeScreenOrientationPortraitAsync, "ChangeScreenOrientationPortraitAsync at %p\n"); + // ADD_HOOK(ChangeScreenOrientation, "ChangeScreenOrientation at %p\n"); + // ADD_HOOK(ChangeScreenOrientationPortraitAsync, "ChangeScreenOrientationPortraitAsync at %p\n"); ADD_HOOK(get_IsVertical, "get_IsVertical at %p\n"); - ADD_HOOK(MovieManager_SetScreenSize, "MovieManager::SetScreenSize at %p\n"); - ADD_HOOK(MovieManager_SetImageUvRect, "MovieManager::SetImageUvRect at %p\n"); + // ADD_HOOK(MovieManager_SetScreenSize, "MovieManager::SetScreenSize at %p\n"); + // ADD_HOOK(MovieManager_SetImageUvRect, "MovieManager::SetImageUvRect at %p\n"); ADD_HOOK(MoviePlayerForUI_AdjustScreenSize, "MoviePlayerForUI::AdjustScreenSize at %p\n"); - ADD_HOOK(MoviePlayerForObj_AdjustScreenSize, "MoviePlayerForObj::AdjustScreenSize at %p\n"); } if (g_dump_entries) @@ -6716,8 +7725,30 @@ namespace } else { - last_display_width = get_rendering_width(display); - last_display_height = get_rendering_height(display); + if (g_freeform_window) + { + auto title = local::u8_wide(g_custom_title_name); + if (title.empty()) + { + title = L"umamusume"; + } + + auto hWnd = FindWindowW(L"UnityWndClass", title.data()); + + RECT windowRect; + GetWindowRect(hWnd, &windowRect); + + RECT clientRect; + GetClientRect(hWnd, &clientRect); + + last_display_width = windowRect.left; + last_display_height = clientRect.left; + } + else + { + last_display_width = get_system_width(display); + last_display_height = get_system_height(display); + } } auto GallopScreen = il2cpp_symbols::get_class("umamusume.dll", "Gallop", "Screen"); @@ -6751,7 +7782,7 @@ namespace auto t = il2cpp_thread_attach(il2cpp_domain_get()); while (true) { - Sleep(500); + Sleep(100); SetBGCanvasScalerSize(); } }).detach(); @@ -6805,13 +7836,20 @@ namespace } else { - Resolution_t r; - get_resolution(&r); - - last_hriz_window_width = r.width - 400; - last_hriz_window_height = last_hriz_window_width / ratio_horizontal; - last_virt_window_height = r.height - 400; - last_virt_window_width = last_virt_window_height * ratio_vertical; + if (g_freeform_window) + { + last_hriz_window_width = last_display_width; + last_hriz_window_height = last_display_height; + last_virt_window_height = last_display_height; + last_virt_window_width = last_display_width; + } + else + { + last_hriz_window_width = last_display_width - 400; + last_hriz_window_height = last_hriz_window_width / ratio_horizontal; + last_virt_window_height = last_display_height - 400; + last_virt_window_width = last_virt_window_height * ratio_vertical; + } } @@ -6823,10 +7861,10 @@ namespace if (g_discord_rich_presence) { - discord::Core::Create(1080397170215223367, DiscordCreateFlags_Default, &discord); - startTime = chrono::duration_cast(chrono::system_clock::now().time_since_epoch()).count(); + discord::Core::Create(1080397170215223367, static_cast(discord::CreateFlags::NoRequireDiscord), &discord); if (discord) { + startTime = chrono::duration_cast(chrono::system_clock::now().time_since_epoch()).count(); thread t([]() { il2cpp_thread_attach(il2cpp_domain_get()); @@ -6874,15 +7912,36 @@ namespace } else { + auto uiManager = GetSingletonInstance(il2cpp_symbols::get_class("umamusume.dll", "Gallop", "UIManager")); auto sceneManager = GetSingletonInstance(il2cpp_symbols::get_class("umamusume.dll", "Gallop", "SceneManager")); - if (sceneManager) + if (uiManager && sceneManager) { - auto viewId = il2cpp_class_get_method_from_name_type(sceneManager->klass, "GetCurrentViewId", 0)->methodPointer(sceneManager); - auto viewName = local::wide_u8(GetEnumName(GetRuntimeType("umamusume.dll", "Gallop", "SceneDefine/ViewId"), viewId)->start_char); - auto detail = GetViewName(viewName); + string detail; + + auto CommonHeaderTitle = il2cpp_class_get_method_from_name_type(uiManager->klass, "get_CommonHeaderTitle", 0)->methodPointer(uiManager); + + if (CommonHeaderTitle) + { + auto _cacheTextField = il2cpp_class_get_field_from_name_wrap(CommonHeaderTitle->klass, "_cacheText"); + Il2CppString* _cacheText; + il2cpp_field_get_value(CommonHeaderTitle, _cacheTextField, &_cacheText); + + if (_cacheText) + { + detail = local::wide_u8(_cacheText->start_char); + } + } + if (detail.empty()) { - // detail = GetSceneName() + auto viewId = il2cpp_class_get_method_from_name_type(sceneManager->klass, "GetCurrentViewId", 0)->methodPointer(sceneManager); + auto viewName = local::wide_u8(GetEnumName(GetRuntimeType("umamusume.dll", "Gallop", "SceneDefine/ViewId"), viewId)->start_char); + detail = GetViewName(viewName); + + if (detail.empty()) + { + // detail = GetSceneName() + } } if (discord && !detail.empty()) @@ -6897,14 +7956,17 @@ namespace } } Sleep(100); - discord->RunCallbacks(); + + if (discord) + { + discord->RunCallbacks(); + } } }); t.detach(); } } - if (g_max_fps > -1 || g_unlock_size || g_freeform_window || g_discord_rich_presence || g_character_system_text_caption) { auto sceneManagerClass = il2cpp_symbols::get_class("UnityEngine.CoreModule.dll", "UnityEngine.SceneManagement", "SceneManager"); @@ -6992,14 +8054,117 @@ namespace } } + if (Game::CurrentGameRegion == Game::Region::KOR) + { + auto uiManager = GetSingletonInstance(il2cpp_symbols::get_class("umamusume.dll", "Gallop", "UIManager")); + updateVoiceButton = CreateDelegateWithClass(il2cpp_symbols::get_class("DOTween.dll", "DG.Tweening", "TweenCallback"), uiManager, *([](Il2CppObject* _this) + { + UpdateVoiceButton(); + il2cpp_symbols::get_method_pointer("DOTween.dll", "DG.Tweening", "DOVirtual", "DelayedCall", 3)(0.05, updateVoiceButton, true); + })); + + // Delay 50ms + il2cpp_symbols::get_method_pointer("DOTween.dll", "DG.Tweening", "DOVirtual", "DelayedCall", 3)(0.05, updateVoiceButton, true); + } + + if (g_freeform_window) + { + int width = il2cpp_symbols::get_method_pointer("UnityEngine.CoreModule.dll", "UnityEngine", "Screen", "get_width", -1)(); + int height = il2cpp_symbols::get_method_pointer("UnityEngine.CoreModule.dll", "UnityEngine", "Screen", "get_height", -1)(); + + bool isVirt = width < height; + il2cpp_symbols::get_method_pointer("umamusume.dll", "Gallop", "StandaloneWindowResize", "set_IsVirt", 1)(isVirt); + + auto uiManager = GetSingletonInstance(il2cpp_symbols::get_class("umamusume.dll", "Gallop", "UIManager")); + moviePlayerResize = CreateDelegateWithClass(il2cpp_symbols::get_class("DOTween.dll", "DG.Tweening", "TweenCallback"), uiManager, *([](Il2CppObject* _this) + { + ResizeMoviePlayer(); + il2cpp_symbols::get_method_pointer("DOTween.dll", "DG.Tweening", "DOVirtual", "DelayedCall", 3)(0.05, moviePlayerResize, true); + })); + + // Delay 50ms + il2cpp_symbols::get_method_pointer("DOTween.dll", "DG.Tweening", "DOVirtual", "DelayedCall", 3)(0.05, moviePlayerResize, true); + } + + if (uiManager && (g_unlock_size || g_freeform_window)) + { + int width = il2cpp_symbols::get_method_pointer("UnityEngine.CoreModule.dll", "UnityEngine", "Screen", "get_width", -1)(); + int height = il2cpp_symbols::get_method_pointer("UnityEngine.CoreModule.dll", "UnityEngine", "Screen", "get_height", -1)(); + + bool isVirt = width < height; + if (g_freeform_window) + { + UIManager_ChangeResizeUIForPC_hook(uiManager, isVirt ? min(last_virt_window_width, last_virt_window_height) : max(last_hriz_window_width, last_hriz_window_height), + isVirt ? max(last_virt_window_width, last_virt_window_height) : min(last_hriz_window_width, last_hriz_window_height)); + } + else + { + UIManager_ChangeResizeUIForPC_hook(uiManager, isVirt ? min(last_display_width, last_display_height) : max(last_display_width, last_display_height), + isVirt ? max(last_display_width, last_display_height) : min(last_display_width, last_display_height)); + } + } } + if (sceneName == "Home") { if (g_character_system_text_caption) { InitNotification(); } + + thread([]() + { + auto t = il2cpp_thread_attach(il2cpp_domain_get()); + + while (true) + { + Sleep(100); + __try + { + Il2CppArraySize_t* CharacterHomeTopUIList; + if (Game::CurrentGameRegion == Game::Region::KOR) + { + CharacterHomeTopUIList = il2cpp_resolve_icall_type*(*)(Il2CppObject*, int, int)>("UnityEngine.Object::FindObjectsByType()")( + GetRuntimeType("umamusume.dll", "Gallop", "CharacterHomeTopUI"), 1, 0); + } + else + { + CharacterHomeTopUIList = il2cpp_resolve_icall_type*(*)(Il2CppObject*, bool)>("UnityEngine.Object::FindObjectsOfType()")( + GetRuntimeType("umamusume.dll", "Gallop", "CharacterHomeTopUI"), true); + } + + for (int i = 0; i < CharacterHomeTopUIList->max_length; i++) + { + auto CharacterHomeTopUI = CharacterHomeTopUIList->vector[i]; + if (CharacterHomeTopUI) + { + auto _cardRootButtonField = il2cpp_class_get_field_from_name_wrap(CharacterHomeTopUI->klass, "_cardRootButton"); + Il2CppObject* _cardRootButton; + il2cpp_field_get_value(CharacterHomeTopUI, _cardRootButtonField, &_cardRootButton); + + if (_cardRootButton) + { + auto targetText = il2cpp_class_get_method_from_name_type(_cardRootButton->klass, "get_TargetText", 0)->methodPointer(_cardRootButton); + + if (targetText) + { + text_set_horizontalOverflow(targetText, 1); + text_set_verticalOverflow(targetText, 1); + + il2cpp_thread_detach(t); + return; + } + } + } + } + } + __except (EXCEPTION_EXECUTE_HANDLER) + { + } + } + + }).detach(); } if (g_discord_rich_presence && discord) @@ -7021,18 +8186,6 @@ namespace discord->ActivityManager().UpdateActivity(activity, [](discord::Result res) {}); } } - - if (uiManager && (g_unlock_size || g_freeform_window)) - { - int width = il2cpp_symbols::get_method_pointer("UnityEngine.CoreModule.dll", "UnityEngine", "Screen", "get_width", -1)(); - int height = il2cpp_symbols::get_method_pointer("UnityEngine.CoreModule.dll", "UnityEngine", "Screen", "get_height", -1)(); - - bool isVirt = width < height; - - UIManager_ChangeResizeUIForPC_hook(uiManager, isVirt ? last_virt_window_width : last_hriz_window_width, - isVirt ? last_virt_window_height : last_hriz_window_height); - - } }) ); il2cpp_field_static_set_value(activeSceneChangedField, action); @@ -7118,7 +8271,7 @@ MessageBoxW_hook( { if (wstring(lpCaption).starts_with(L"AppSign")) { - lpText = L"Wellbia AppSign이 의도치 않은 동작을 감지하여 프로그램이 종료됩니다.\n\n문제가 지속되는 경우 https://wellbia.com/에 방문하거나, support@wellbia.com으로 문의하시기 바랍니다."; + lpText = L"Wellbia AppSign이 의도치 않은 동작을 감지하여 프로그램이 종료됩니다.\n\n문제가 지속되는 경우 https://wellbia.com/ 에 방문하거나, support@wellbia.com 으로 문의하시기 바랍니다."; lpCaption = L"Warning"; uType = MB_ICONWARNING; } @@ -7141,7 +8294,53 @@ SetWindowLongPtrW_hook( return reinterpret_cast(SetWindowLongPtrW_orig)(hWnd, nIndex, dwNewLong); } -bool init_hook() +void* SetWindowLongPtrA_orig = nullptr; + +LONG_PTR +WINAPI +SetWindowLongPtrA_hook( + _In_ HWND hWnd, + _In_ int nIndex, + _In_ LONG_PTR dwNewLong) +{ + if (nIndex == GWL_STYLE) + { + dwNewLong |= WS_MAXIMIZEBOX; + } + return reinterpret_cast(SetWindowLongPtrA_orig)(hWnd, nIndex, dwNewLong); +} + +void* ExitProcess_orig = nullptr; + +DECLSPEC_NORETURN +VOID +WINAPI +ExitProcess_hook( + _In_ UINT uExitCode +) +{ + if (Game::CurrentGameRegion == Game::Region::KOR) + { + auto module_path = filesystem::current_path(); + auto uncheater_path_new = module_path.string().append("\\umamusume_Data\\StreamingAssets\\_Uncheater"s).data(); + auto uncheater_path = module_path.string().append("\\umamusume_Data\\StreamingAssets\\Uncheater"s).data(); + if (filesystem::exists(uncheater_path_new)) + { + try + { + filesystem::rename(uncheater_path_new, uncheater_path); + } + catch (exception& e) + { + cout << "Uncheater rename error: " << e.what() << endl; + } + } + } + + reinterpret_cast(ExitProcess_orig)(uExitCode); +} + +bool init_hook_base() { if (mh_inited) return false; @@ -7151,6 +8350,26 @@ bool init_hook() mh_inited = true; + MH_CreateHook(MessageBoxW, MessageBoxW_hook, &MessageBoxW_orig); + MH_EnableHook(MessageBoxW); + + MH_CreateHook(LoadLibraryExW, load_library_ex_w_hook, &load_library_ex_w_orig); + MH_EnableHook(LoadLibraryExW); + + MH_CreateHook(LoadLibraryW, load_library_w_hook, &load_library_w_orig); + MH_EnableHook(LoadLibraryW); + + if (Game::CurrentGameRegion == Game::Region::KOR) + { + MH_CreateHook(ExitProcess, ExitProcess_hook, &ExitProcess_orig); + MH_EnableHook(ExitProcess); + } + + return true; +} + +bool init_hook() +{ // auto ntdll = GetModuleHandleA("ntdll.dll"); /*auto NtCreateSection = GetProcAddress(ntdll, "NtCreateSection"); @@ -7170,59 +8389,53 @@ bool init_hook() { MH_CreateHook(SetWindowLongPtrW, SetWindowLongPtrW_hook, &SetWindowLongPtrW_orig); MH_EnableHook(SetWindowLongPtrW); + MH_CreateHook(SetWindowLongPtrA, SetWindowLongPtrA_hook, &SetWindowLongPtrA_orig); + MH_EnableHook(SetWindowLongPtrA); } - MH_CreateHook(MessageBoxW, MessageBoxW_hook, &MessageBoxW_orig); - MH_EnableHook(MessageBoxW); - - MH_CreateHook(LoadLibraryW, load_library_w_hook, &load_library_w_orig); - MH_EnableHook(LoadLibraryW); - - // if (Game::CurrentGameRegion != Game::Region::KOR) + while (true) { auto il2cpp = GetModuleHandleW(L"GameAssembly.dll"); if (!il2cpp) { - il2cpp = LoadLibraryW(L"GameAssembly.dll"); + Sleep(1000); } - - if (!il2cpp) + else { - exit(0); - } - - const auto il2cpp_init_addr = GetProcAddress(il2cpp, "il2cpp_init"); - MH_CreateHook(il2cpp_init_addr, il2cpp_init_hook, &il2cpp_init_orig); - MH_EnableHook(il2cpp_init_addr); + /*std::ofstream out("./GameAssembly.decrypted.dll", std::ios_base::binary); + MODULEINFO info; + if (out && GetModuleInformation(GetCurrentProcess(), il2cpp, &info, sizeof(info))) + { + const auto header = static_cast(info.lpBaseOfDll); + const auto ntHeader = reinterpret_cast( + static_cast(info.lpBaseOfDll) + header->e_lfanew); + const auto sections = IMAGE_FIRST_SECTION(ntHeader); - il2cpp_init_hook("IL2CPP Root Domain"); - // reinterpret_cast(il2cpp_init_orig)("IL2CPP Root Domain"); + out.write(static_cast(info.lpBaseOfDll), + reinterpret_cast(sections) + + ntHeader->FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER) - + static_cast(info.lpBaseOfDll)); - /*std::ofstream out("./GameAssembly.decrypted.dll", std::ios_base::binary); - MODULEINFO info; - if (out && GetModuleInformation(GetCurrentProcess(), il2cpp, &info, sizeof(info))) - { - const auto header = static_cast(info.lpBaseOfDll); - const auto ntHeader = reinterpret_cast( - static_cast(info.lpBaseOfDll) + header->e_lfanew); - const auto sections = IMAGE_FIRST_SECTION(ntHeader); + for (std::size_t i = 0; i < ntHeader->FileHeader.NumberOfSections; ++i) + { + const auto& section = sections[i]; - out.write(static_cast(info.lpBaseOfDll), - reinterpret_cast(sections) + - ntHeader->FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER) - - static_cast(info.lpBaseOfDll)); + out.seekp(section.PointerToRawData); + out.write(static_cast(info.lpBaseOfDll) + section.VirtualAddress, + section.SizeOfRawData); + } + }*/ - for (std::size_t i = 0; i < ntHeader->FileHeader.NumberOfSections; ++i) - { - const auto& section = sections[i]; + const auto il2cpp_init_addr = GetProcAddress(il2cpp, "il2cpp_init"); + MH_CreateHook(il2cpp_init_addr, il2cpp_init_hook, &il2cpp_init_orig); + MH_EnableHook(il2cpp_init_addr); - out.seekp(section.PointerToRawData); - out.write(static_cast(info.lpBaseOfDll) + section.VirtualAddress, - section.SizeOfRawData); - } - }*/ + il2cpp_init_hook("IL2CPP Root Domain"); + break; + } } + // reinterpret_cast(il2cpp_init_orig)("IL2CPP Root Domain"); return true; } diff --git a/src/il2cpp/il2cpp_symbols.cpp b/src/il2cpp/il2cpp_symbols.cpp index 2dd17c8..7c5e04b 100644 --- a/src/il2cpp/il2cpp_symbols.cpp +++ b/src/il2cpp/il2cpp_symbols.cpp @@ -57,6 +57,7 @@ il2cpp_field_get_parent_t il2cpp_field_get_parent; il2cpp_field_get_offset_t il2cpp_field_get_offset; il2cpp_class_get_property_from_name_t il2cpp_class_get_property_from_name; il2cpp_runtime_object_init_t il2cpp_runtime_object_init; +il2cpp_runtime_object_init_exception_t il2cpp_runtime_object_init_exception; il2cpp_value_box_t il2cpp_value_box; il2cpp_object_unbox_t il2cpp_object_unbox; il2cpp_is_vm_thread_t il2cpp_is_vm_thread; @@ -133,6 +134,7 @@ namespace il2cpp_symbols RESOLVE_IMPORT(il2cpp_field_get_offset); RESOLVE_IMPORT(il2cpp_class_get_property_from_name); RESOLVE_IMPORT(il2cpp_runtime_object_init); + RESOLVE_IMPORT(il2cpp_runtime_object_init_exception); RESOLVE_IMPORT(il2cpp_value_box); RESOLVE_IMPORT(il2cpp_object_unbox); RESOLVE_IMPORT(il2cpp_is_vm_thread); diff --git a/src/il2cpp/il2cpp_symbols.hpp b/src/il2cpp/il2cpp_symbols.hpp index 31f5269..de15139 100644 --- a/src/il2cpp/il2cpp_symbols.hpp +++ b/src/il2cpp/il2cpp_symbols.hpp @@ -445,6 +445,15 @@ struct Il2CppArraySize_t static const size_t kIl2CppSizeOfArray = (offsetof(Il2CppArraySize, vector)); +template +struct Entry +{ + int hashCode; + int next; + K key; + V value; +}; + struct CourseBaseObjectContext { Il2CppObject* coursePrefab; @@ -482,6 +491,11 @@ struct RaceLoaderManagerCourceContext int CourseStartGateBaseId; }; +struct MoviePlayerHandle +{ + uint32_t id; +}; + struct CriAtomExPlayback { uint32_t id; @@ -639,6 +653,7 @@ typedef Il2CppClass* (*il2cpp_field_get_parent_t)(FieldInfo* field); typedef size_t (*il2cpp_field_get_offset_t)(FieldInfo* field); typedef const PropertyInfo* (*il2cpp_class_get_property_from_name_t)(Il2CppClass* klass, const char* name); typedef void (*il2cpp_runtime_object_init_t)(Il2CppObject* obj); +typedef void (*il2cpp_runtime_object_init_exception_t)(Il2CppObject* obj, void** exc); typedef Il2CppObject* (*il2cpp_value_box_t)(Il2CppClass* klass, void* data); typedef void* (*il2cpp_object_unbox_t)(Il2CppObject* obj); typedef bool (*il2cpp_is_vm_thread_t)(void* thread); @@ -705,6 +720,7 @@ extern il2cpp_field_get_parent_t il2cpp_field_get_parent; extern il2cpp_field_get_offset_t il2cpp_field_get_offset; extern il2cpp_class_get_property_from_name_t il2cpp_class_get_property_from_name; extern il2cpp_runtime_object_init_t il2cpp_runtime_object_init; +extern il2cpp_runtime_object_init_exception_t il2cpp_runtime_object_init_exception; extern il2cpp_value_box_t il2cpp_value_box; extern il2cpp_object_unbox_t il2cpp_object_unbox; extern il2cpp_is_vm_thread_t il2cpp_is_vm_thread; diff --git a/src/libcef.h b/src/libcef.h new file mode 100644 index 0000000..13db18e --- /dev/null +++ b/src/libcef.h @@ -0,0 +1,2784 @@ +#pragma once + +#include +#include + +#define CEF_CALLBACK __stdcall +#define cef_window_handle_t HWND + +// Build with the UTF8 string type as default. +// #define CEF_STRING_TYPE_UTF8 1 + +// Build with the UTF16 string type as default. +#define CEF_STRING_TYPE_UTF16 1 + +// Build with the wide string type as default. +// #define CEF_STRING_TYPE_WIDE 1 + +typedef struct _cef_string_wide_t { + wchar_t* str; + size_t length; + void (*dtor)(wchar_t* str); +} cef_string_wide_t; + +typedef struct _cef_string_utf8_t { + char* str; + size_t length; + void (*dtor)(char* str); +} cef_string_utf8_t; + +typedef struct _cef_string_utf16_t { + char16_t* str; + size_t length; + void (*dtor)(char16_t* str); +} cef_string_utf16_t; + +typedef cef_string_wide_t* cef_string_userfree_wide_t; +typedef cef_string_utf8_t* cef_string_userfree_utf8_t; +typedef cef_string_utf16_t* cef_string_userfree_utf16_t; + +#if defined(CEF_STRING_TYPE_UTF8) +typedef char cef_char_t; +typedef cef_string_utf8_t cef_string_t; +typedef cef_string_userfree_utf8_t cef_string_userfree_t; +#elif defined(CEF_STRING_TYPE_UTF16) +typedef char16_t cef_char_t; +typedef cef_string_utf16_t cef_string_t; +typedef cef_string_userfree_utf16_t cef_string_userfree_t; +#elif defined(CEF_STRING_TYPE_WIDE) +typedef wchar_t cef_char_t; +typedef cef_string_wide_t cef_string_t; +typedef cef_string_userfree_wide_t cef_string_userfree_t; +#endif + +/// +/// These functions set string values. If |copy| is true (1) the value will be +/// copied instead of referenced. It is up to the user to properly manage +/// the lifespan of references. +/// + +int (*cef_string_wide_set)(const wchar_t* src, + size_t src_len, + cef_string_wide_t* output, + BOOL copy); +int (*cef_string_utf8_set)(const char* src, + size_t src_len, + cef_string_utf8_t* output, + BOOL copy); +int (*cef_string_utf16_set)(const char16_t* src, + size_t src_len, + cef_string_utf16_t* output, + BOOL copy); + + +#if defined(CEF_STRING_TYPE_UTF8) +#define cef_string_set cef_string_utf8_set; +#elif defined(CEF_STRING_TYPE_UTF16) +#define cef_string_set cef_string_utf16_set; +#elif defined(CEF_STRING_TYPE_WIDE) +#define cef_string_set cef_string_wide_set; +#endif + +/// +/// CEF string maps are a set of key/value string pairs. +/// +typedef struct _cef_string_list_t* cef_string_list_t; + +/// +/// Allocate a new string map. +/// +cef_string_list_t(*cef_string_list_alloc)(void); + +/// +/// Return the number of elements in the string list. +/// +size_t(*cef_string_list_size)(cef_string_list_t list); + +/// +/// Retrieve the value at the specified zero-based string list index. Returns +/// true (1) if the value was successfully retrieved. +/// +int (*cef_string_list_value)(cef_string_list_t list, + size_t index, + cef_string_t* value); + +/// +/// Append a new value at the end of the string list. +/// +void (*cef_string_list_append)(cef_string_list_t list, + const cef_string_t* value); + +/// +/// Clear the string list. +/// +void (*cef_string_list_clear)(cef_string_list_t list); + +/// +/// Free the string list. +/// +void (*cef_string_list_free)(cef_string_list_t list); + +/// +/// Creates a copy of an existing string list. +/// +cef_string_list_t(*cef_string_list_copy)(cef_string_list_t list); + +// 32-bit ARGB color value, not premultiplied. The color components are always +// in a known order. Equivalent to the SkColor type. +typedef uint32_t cef_color_t; + +// Return the alpha byte from a cef_color_t value. +#define CefColorGetA(color) (((color) >> 24) & 0xFF) +// Return the red byte from a cef_color_t value. +#define CefColorGetR(color) (((color) >> 16) & 0xFF) +// Return the green byte from a cef_color_t value. +#define CefColorGetG(color) (((color) >> 8) & 0xFF) +// Return the blue byte from a cef_color_t value. +#define CefColorGetB(color) (((color) >> 0) & 0xFF) + +// Return an cef_color_t value with the specified byte component values. +#define CefColorSetARGB(a, r, g, b) \ + static_cast( \ + (static_cast(a) << 24) | (static_cast(r) << 16) | \ + (static_cast(g) << 8) | (static_cast(b) << 0)) + +// Return an int64_t value with the specified low and high int32_t component +// values. +#define CefInt64Set(int32_low, int32_high) \ + static_cast( \ + (static_cast(int32_low)) | \ + (static_cast(static_cast(int32_high))) << 32) + +// Return the low int32_t value from an int64_t value. +#define CefInt64GetLow(int64_val) static_cast(int64_val) +// Return the high int32_t value from an int64_t value. +#define CefInt64GetHigh(int64_val) \ + static_cast((static_cast(int64_val) >> 32) & 0xFFFFFFFFL) + +/// +/// Log severity levels. +/// +typedef enum { + /// + /// Default logging (currently INFO logging). + /// + LOGSEVERITY_DEFAULT, + + /// + /// Verbose logging. + /// + LOGSEVERITY_VERBOSE, + + /// + /// DEBUG logging. + /// + LOGSEVERITY_DEBUG = LOGSEVERITY_VERBOSE, + + /// + /// INFO logging. + /// + LOGSEVERITY_INFO, + + /// + /// WARNING logging. + /// + LOGSEVERITY_WARNING, + + /// + /// ERROR logging. + /// + LOGSEVERITY_ERROR, + + /// + /// FATAL logging. + /// + LOGSEVERITY_FATAL, + + /// + /// Disable logging to file for all messages, and to stderr for messages with + /// severity less than FATAL. + /// + LOGSEVERITY_DISABLE = 99 +} cef_log_severity_t; + +/// +/// Log items prepended to each log line. +/// +typedef enum { + /// + /// Prepend the default list of items. + /// + LOG_ITEMS_DEFAULT = 0, + + /// + /// Prepend no items. + /// + LOG_ITEMS_NONE = 1, + + /// + /// Prepend the process ID. + /// + LOG_ITEMS_FLAG_PROCESS_ID = 1 << 1, + + /// + /// Prepend the thread ID. + /// + LOG_ITEMS_FLAG_THREAD_ID = 1 << 2, + + /// + /// Prepend the timestamp. + /// + LOG_ITEMS_FLAG_TIME_STAMP = 1 << 3, + + /// + /// Prepend the tickcount. + /// + LOG_ITEMS_FLAG_TICK_COUNT = 1 << 4, + +} cef_log_items_t; + +/// +/// Represents the state of a setting. +/// +typedef enum { + /// + /// Use the default state for the setting. + /// + STATE_DEFAULT = 0, + + /// + /// Enable or allow the setting. + /// + STATE_ENABLED, + + /// + /// Disable or disallow the setting. + /// + STATE_DISABLED, +} cef_state_t; + +/// +/// Existing process IDs. +/// +typedef enum { + /// + /// Browser process. + /// + PID_BROWSER, + /// + /// Renderer process. + /// + PID_RENDERER, +} cef_process_id_t; + +/// +/// Supported value types. +/// +typedef enum { + VTYPE_INVALID = 0, + VTYPE_NULL, + VTYPE_BOOL, + VTYPE_INT, + VTYPE_DOUBLE, + VTYPE_STRING, + VTYPE_BINARY, + VTYPE_DICTIONARY, + VTYPE_LIST, +} cef_value_type_t; + +/// +/// Supported content setting types. Some types are platform-specific or only +/// supported with the Chrome runtime. Should be kept in sync with Chromium's +/// ContentSettingsType type. +/// +typedef enum { + CEF_CONTENT_SETTING_TYPE_COOKIES = 0, + CEF_CONTENT_SETTING_TYPE_IMAGES, + CEF_CONTENT_SETTING_TYPE_JAVASCRIPT, + + /// This setting governs both popups and unwanted redirects like tab-unders + /// and framebusting. + CEF_CONTENT_SETTING_TYPE_POPUPS, + + CEF_CONTENT_SETTING_TYPE_GEOLOCATION, + CEF_CONTENT_SETTING_TYPE_NOTIFICATIONS, + CEF_CONTENT_SETTING_TYPE_AUTO_SELECT_CERTIFICATE, + CEF_CONTENT_SETTING_TYPE_MIXEDSCRIPT, + CEF_CONTENT_SETTING_TYPE_MEDIASTREAM_MIC, + CEF_CONTENT_SETTING_TYPE_MEDIASTREAM_CAMERA, + CEF_CONTENT_SETTING_TYPE_PROTOCOL_HANDLERS, + CEF_CONTENT_SETTING_TYPE_DEPRECATED_PPAPI_BROKER, + CEF_CONTENT_SETTING_TYPE_AUTOMATIC_DOWNLOADS, + CEF_CONTENT_SETTING_TYPE_MIDI_SYSEX, + CEF_CONTENT_SETTING_TYPE_SSL_CERT_DECISIONS, + CEF_CONTENT_SETTING_TYPE_PROTECTED_MEDIA_IDENTIFIER, + CEF_CONTENT_SETTING_TYPE_APP_BANNER, + CEF_CONTENT_SETTING_TYPE_SITE_ENGAGEMENT, + CEF_CONTENT_SETTING_TYPE_DURABLE_STORAGE, + CEF_CONTENT_SETTING_TYPE_USB_CHOOSER_DATA, + CEF_CONTENT_SETTING_TYPE_BLUETOOTH_GUARD, + CEF_CONTENT_SETTING_TYPE_BACKGROUND_SYNC, + CEF_CONTENT_SETTING_TYPE_AUTOPLAY, + CEF_CONTENT_SETTING_TYPE_IMPORTANT_SITE_INFO, + CEF_CONTENT_SETTING_TYPE_PERMISSION_AUTOBLOCKER_DATA, + CEF_CONTENT_SETTING_TYPE_ADS, + + /// Website setting which stores metadata for the subresource filter to aid in + /// decisions for whether or not to show the UI. + CEF_CONTENT_SETTING_TYPE_ADS_DATA, + + /// This is special-cased in the permissions layer to always allow, and as + /// such doesn't have associated prefs data. + CEF_CONTENT_SETTING_TYPE_MIDI, + + /// This content setting type is for caching password protection service's + /// verdicts of each origin. + CEF_CONTENT_SETTING_TYPE_PASSWORD_PROTECTION, + + /// Website setting which stores engagement data for media related to a + /// specific origin. + CEF_CONTENT_SETTING_TYPE_MEDIA_ENGAGEMENT, + + /// Content setting which stores whether or not the site can play audible + /// sound. This will not block playback but instead the user will not hear it. + CEF_CONTENT_SETTING_TYPE_SOUND, + + /// Website setting which stores the list of client hints that the origin + /// requested the browser to remember. The browser is expected to send all + /// client hints in the HTTP request headers for every resource requested + /// from that origin. + CEF_CONTENT_SETTING_TYPE_CLIENT_HINTS, + + /// Generic Sensor API covering ambient-light-sensor, accelerometer, gyroscope + /// and magnetometer are all mapped to a single content_settings_type. + /// Setting for the Generic Sensor API covering ambient-light-sensor, + /// accelerometer, gyroscope and magnetometer. These are all mapped to a + /// single ContentSettingsType. + CEF_CONTENT_SETTING_TYPE_SENSORS, + + /// Content setting which stores whether or not the user has granted the site + /// permission to respond to accessibility events, which can be used to + /// provide a custom accessibility experience. Requires explicit user consent + /// because some users may not want sites to know they're using assistive + /// technology. + CEF_CONTENT_SETTING_TYPE_ACCESSIBILITY_EVENTS, + + /// Used to store whether to allow a website to install a payment handler. + CEF_CONTENT_SETTING_TYPE_PAYMENT_HANDLER, + + /// Content setting which stores whether to allow sites to ask for permission + /// to access USB devices. If this is allowed specific device permissions are + /// stored under USB_CHOOSER_DATA. + CEF_CONTENT_SETTING_TYPE_USB_GUARD, + + /// Nothing is stored in this setting at present. Please refer to + /// BackgroundFetchPermissionContext for details on how this permission + /// is ascertained. + CEF_CONTENT_SETTING_TYPE_BACKGROUND_FETCH, + + /// Website setting which stores the amount of times the user has dismissed + /// intent picker UI without explicitly choosing an option. + CEF_CONTENT_SETTING_TYPE_INTENT_PICKER_DISPLAY, + + /// Used to store whether to allow a website to detect user active/idle state. + CEF_CONTENT_SETTING_TYPE_IDLE_DETECTION, + + /// Setting for enabling auto-select of all screens for getDisplayMediaSet. + CEF_CONTENT_SETTING_TYPE_GET_DISPLAY_MEDIA_SET_SELECT_ALL_SCREENS, + + /// Content settings for access to serial ports. The "guard" content setting + /// stores whether to allow sites to ask for permission to access a port. The + /// permissions granted to access particular ports are stored in the "chooser + /// data" website setting. + CEF_CONTENT_SETTING_TYPE_SERIAL_GUARD, + CEF_CONTENT_SETTING_TYPE_SERIAL_CHOOSER_DATA, + + /// Nothing is stored in this setting at present. Please refer to + /// PeriodicBackgroundSyncPermissionContext for details on how this permission + /// is ascertained. + /// This content setting is not registered because it does not require access + /// to any existing providers. + CEF_CONTENT_SETTING_TYPE_PERIODIC_BACKGROUND_SYNC, + + /// Content setting which stores whether to allow sites to ask for permission + /// to do Bluetooth scanning. + CEF_CONTENT_SETTING_TYPE_BLUETOOTH_SCANNING, + + /// Content settings for access to HID devices. The "guard" content setting + /// stores whether to allow sites to ask for permission to access a device. + /// The permissions granted to access particular devices are stored in the + /// "chooser data" website setting. + CEF_CONTENT_SETTING_TYPE_HID_GUARD, + CEF_CONTENT_SETTING_TYPE_HID_CHOOSER_DATA, + + /// Wake Lock API, which has two lock types: screen and system locks. + /// Currently, screen locks do not need any additional permission, and system + /// locks are always denied while the right UI is worked out. + CEF_CONTENT_SETTING_TYPE_WAKE_LOCK_SCREEN, + CEF_CONTENT_SETTING_TYPE_WAKE_LOCK_SYSTEM, + + /// Legacy SameSite cookie behavior. This disables SameSite=Lax-by-default, + /// SameSite=None requires Secure, and Schemeful Same-Site, forcing the + /// legacy behavior wherein 1) cookies that don't specify SameSite are treated + /// as SameSite=None, 2) SameSite=None cookies are not required to be Secure, + /// and 3) schemeful same-site is not active. + /// + /// This will also be used to revert to legacy behavior when future changes + /// in cookie handling are introduced. + CEF_CONTENT_SETTING_TYPE_LEGACY_COOKIE_ACCESS, + + /// Content settings which stores whether to allow sites to ask for permission + /// to save changes to an original file selected by the user through the + /// File System Access API. + CEF_CONTENT_SETTING_TYPE_FILE_SYSTEM_WRITE_GUARD, + + /// Used to store whether to allow a website to exchange data with NFC + /// devices. + CEF_CONTENT_SETTING_TYPE_NFC, + + /// Website setting to store permissions granted to access particular + /// Bluetooth devices. + CEF_CONTENT_SETTING_TYPE_BLUETOOTH_CHOOSER_DATA, + + /// Full access to the system clipboard (sanitized read without user gesture, + /// and unsanitized read and write with user gesture). + CEF_CONTENT_SETTING_TYPE_CLIPBOARD_READ_WRITE, + + /// This is special-cased in the permissions layer to always allow, and as + /// such doesn't have associated prefs data. + CEF_CONTENT_SETTING_TYPE_CLIPBOARD_SANITIZED_WRITE, + + /// This content setting type is for caching safe browsing real time url + /// check's verdicts of each origin. + CEF_CONTENT_SETTING_TYPE_SAFE_BROWSING_URL_CHECK_DATA, + + /// Used to store whether a site is allowed to request AR or VR sessions with + /// the WebXr Device API. + CEF_CONTENT_SETTING_TYPE_VR, + CEF_CONTENT_SETTING_TYPE_AR, + + /// Content setting which stores whether to allow site to open and read files + /// and directories selected through the File System Access API. + CEF_CONTENT_SETTING_TYPE_FILE_SYSTEM_READ_GUARD, + + /// Access to first party storage in a third-party context. Exceptions are + /// scoped to the combination of requesting/top-level origin, and are managed + /// through the Storage Access API. For the time being, this content setting + /// exists in parallel to third-party cookie rules stored in COOKIES. + CEF_CONTENT_SETTING_TYPE_STORAGE_ACCESS, + + /// Content setting which stores whether to allow a site to control camera + /// movements. It does not give access to camera. + CEF_CONTENT_SETTING_TYPE_CAMERA_PAN_TILT_ZOOM, + + /// Content setting for Screen Enumeration and Screen Detail functionality. + /// Permits access to detailed multi-screen information, like size and + /// position. Permits placing fullscreen and windowed content on specific + /// screens. See also: https://w3c.github.io/window-placement + CEF_CONTENT_SETTING_TYPE_WINDOW_MANAGEMENT, + + /// Stores whether to allow insecure websites to make local network requests. + /// See also: https://wicg.github.io/local-network-access + /// Set through enterprise policies only. + CEF_CONTENT_SETTING_TYPE_INSECURE_LOCAL_NETWORK, + + /// Content setting which stores whether or not a site can access low-level + /// locally installed font data using the Local Fonts Access API. + CEF_CONTENT_SETTING_TYPE_LOCAL_FONTS, + + /// Stores per-origin state for permission auto-revocation (for all permission + /// types). + CEF_CONTENT_SETTING_TYPE_PERMISSION_AUTOREVOCATION_DATA, + + /// Stores per-origin state of the most recently selected directory for the + /// use by the File System Access API. + CEF_CONTENT_SETTING_TYPE_FILE_SYSTEM_LAST_PICKED_DIRECTORY, + + /// Controls access to the getDisplayMedia API when {preferCurrentTab: true} + /// is specified. + CEF_CONTENT_SETTING_TYPE_DISPLAY_CAPTURE, + + /// Website setting to store permissions metadata granted to paths on the + /// local file system via the File System Access API. + /// |FILE_SYSTEM_WRITE_GUARD| is the corresponding "guard" setting. + CEF_CONTENT_SETTING_TYPE_FILE_SYSTEM_ACCESS_CHOOSER_DATA, + + /// Stores a grant that allows a relying party to send a request for identity + /// information to specified identity providers, potentially through any + /// anti-tracking measures that would otherwise prevent it. This setting is + /// associated with the relying party's origin. + CEF_CONTENT_SETTING_TYPE_FEDERATED_IDENTITY_SHARING, + + /// Whether to use the v8 optimized JIT for running JavaScript on the page. + CEF_CONTENT_SETTING_TYPE_JAVASCRIPT_JIT, + + /// Content setting which stores user decisions to allow loading a site over + /// HTTP. Entries are added by hostname when a user bypasses the HTTPS-First + /// Mode interstitial warning when a site does not support HTTPS. Allowed + /// hosts are exact hostname matches -- subdomains of a host on the allowlist + /// must be separately allowlisted. + CEF_CONTENT_SETTING_TYPE_HTTP_ALLOWED, + + /// Stores metadata related to form fill, such as e.g. whether user data was + /// autofilled on a specific website. + CEF_CONTENT_SETTING_TYPE_FORMFILL_METADATA, + + /// Setting to indicate that there is an active federated sign-in session + /// between a specified relying party and a specified identity provider for + /// a specified account. When this is present it allows access to session + /// management capabilities between the sites. This setting is associated + /// with the relying party's origin. + CEF_CONTENT_SETTING_TYPE_FEDERATED_IDENTITY_ACTIVE_SESSION, + + /// Setting to indicate whether Chrome should automatically apply darkening to + /// web content. + CEF_CONTENT_SETTING_TYPE_AUTO_DARK_WEB_CONTENT, + + /// Setting to indicate whether Chrome should request the desktop view of a + /// site instead of the mobile one. + CEF_CONTENT_SETTING_TYPE_REQUEST_DESKTOP_SITE, + + /// Setting to indicate whether browser should allow signing into a website + /// via the browser FedCM API. + CEF_CONTENT_SETTING_TYPE_FEDERATED_IDENTITY_API, + + /// Stores notification interactions per origin for the past 90 days. + /// Interactions per origin are pre-aggregated over seven-day windows: A + /// notification interaction or display is assigned to the last Monday + /// midnight in local time. + CEF_CONTENT_SETTING_TYPE_NOTIFICATION_INTERACTIONS, + + /// Website setting which stores the last reduced accept language negotiated + /// for a given origin, to be used on future visits to the origin. + CEF_CONTENT_SETTING_TYPE_REDUCED_ACCEPT_LANGUAGE, + + /// Website setting which is used for NotificationPermissionReviewService to + /// store origin blocklist from review notification permissions feature. + CEF_CONTENT_SETTING_TYPE_NOTIFICATION_PERMISSION_REVIEW, + + /// Website setting to store permissions granted to access particular devices + /// in private network. + CEF_CONTENT_SETTING_TYPE_PRIVATE_NETWORK_GUARD, + CEF_CONTENT_SETTING_TYPE_PRIVATE_NETWORK_CHOOSER_DATA, + + /// Website setting which stores whether the browser has observed the user + /// signing into an identity-provider based on observing the IdP-SignIn-Status + /// HTTP header. + CEF_CONTENT_SETTING_TYPE_FEDERATED_IDENTITY_IDENTITY_PROVIDER_SIGNIN_STATUS, + + /// Website setting which is used for UnusedSitePermissionsService to + /// store revoked permissions of unused sites from unused site permissions + /// feature. + CEF_CONTENT_SETTING_TYPE_REVOKED_UNUSED_SITE_PERMISSIONS, + + /// Similar to STORAGE_ACCESS, but applicable at the page-level rather than + /// being specific to a frame. + CEF_CONTENT_SETTING_TYPE_TOP_LEVEL_STORAGE_ACCESS, + + /// Setting to indicate whether user has opted in to allowing auto re-authn + /// via the FedCM API. + CEF_CONTENT_SETTING_TYPE_FEDERATED_IDENTITY_AUTO_REAUTHN_PERMISSION, + + /// Website setting which stores whether the user has explicitly registered + /// a website as an identity-provider. + CEF_CONTENT_SETTING_TYPE_FEDERATED_IDENTITY_IDENTITY_PROVIDER_REGISTRATION, + + /// Content setting which is used to indicate whether anti-abuse functionality + /// should be enabled. + CEF_CONTENT_SETTING_TYPE_ANTI_ABUSE, + + /// Content setting used to indicate whether third-party storage partitioning + /// should be enabled. + CEF_CONTENT_SETTING_TYPE_THIRD_PARTY_STORAGE_PARTITIONING, + + /// Used to indicate whether HTTPS-First Mode is enabled on the hostname. + CEF_CONTENT_SETTING_TYPE_HTTPS_ENFORCED, + + CEF_CONTENT_SETTING_TYPE_NUM_TYPES, +} cef_content_setting_types_t; + +/// +/// Supported content setting values. Should be kept in sync with Chromium's +/// ContentSetting type. +/// +typedef enum { + CEF_CONTENT_SETTING_VALUE_DEFAULT = 0, + CEF_CONTENT_SETTING_VALUE_ALLOW, + CEF_CONTENT_SETTING_VALUE_BLOCK, + CEF_CONTENT_SETTING_VALUE_ASK, + CEF_CONTENT_SETTING_VALUE_SESSION_ONLY, + CEF_CONTENT_SETTING_VALUE_DETECT_IMPORTANT_CONTENT, + + CEF_CONTENT_SETTING_VALUE_NUM_VALUES +} cef_content_setting_values_t; + +/// +/// Chrome toolbar types. +/// +typedef enum { + CEF_CTT_NONE = 1, + CEF_CTT_NORMAL, + CEF_CTT_LOCATION, +} cef_chrome_toolbar_type_t; + +/// +/// Specifies the gesture commands. +/// +typedef enum { + CEF_GESTURE_COMMAND_BACK, + CEF_GESTURE_COMMAND_FORWARD, +} cef_gesture_command_t; + +/// +/// Structure representing a point. +/// +typedef struct _cef_point_t { + int x; + int y; +} cef_point_t; + +/// +/// Structure representing a rectangle. +/// +typedef struct _cef_rect_t { + int x; + int y; + int width; + int height; +} cef_rect_t; + +/// +/// Structure representing a size. +/// +typedef struct _cef_size_t { + int width; + int height; +} cef_size_t; + +/// +/// Structure representing insets. +/// +typedef struct _cef_insets_t { + int top; + int left; + int bottom; + int right; +} cef_insets_t; + +/// +/// Initialization settings. Specify NULL or 0 to get the recommended default +/// values. Many of these and other settings can also configured using command- +/// line switches. +/// +typedef struct _cef_settings_t { + /// + /// Size of this structure. + /// + size_t size; + + /// + /// Set to true (1) to disable the sandbox for sub-processes. See + /// cef_sandbox_win.h for requirements to enable the sandbox on Windows. Also + /// configurable using the "no-sandbox" command-line switch. + /// + int no_sandbox; + + /// + /// The path to a separate executable that will be launched for sub-processes. + /// If this value is empty on Windows or Linux then the main process + /// executable will be used. If this value is empty on macOS then a helper + /// executable must exist at "Contents/Frameworks/ + /// Helper.app/Contents/MacOS/ Helper" in the top-level app bundle. See + /// the comments on CefExecuteProcess() for details. If this value is + /// non-empty then it must be an absolute path. Also configurable using the + /// "browser-subprocess-path" command-line switch. + /// + cef_string_t browser_subprocess_path; + + /// + /// The path to the CEF framework directory on macOS. If this value is empty + /// then the framework must exist at "Contents/Frameworks/Chromium Embedded + /// Framework.framework" in the top-level app bundle. If this value is + /// non-empty then it must be an absolute path. Also configurable using the + /// "framework-dir-path" command-line switch. + /// + cef_string_t framework_dir_path; + + /// + /// The path to the main bundle on macOS. If this value is empty then it + /// defaults to the top-level app bundle. If this value is non-empty then it + /// must be an absolute path. Also configurable using the "main-bundle-path" + /// command-line switch. + /// + cef_string_t main_bundle_path; + + /// + /// Set to true (1) to enable use of the Chrome runtime in CEF. This feature + /// is considered experimental and is not recommended for most users at this + /// time. See issue #2969 for details. + /// + int chrome_runtime; + + /// + /// Set to true (1) to have the browser process message loop run in a separate + /// thread. If false (0) then the CefDoMessageLoopWork() function must be + /// called from your application message loop. This option is only supported + /// on Windows and Linux. + /// + int multi_threaded_message_loop; + + /// + /// Set to true (1) to control browser process main (UI) thread message pump + /// scheduling via the CefBrowserProcessHandler::OnScheduleMessagePumpWork() + /// callback. This option is recommended for use in combination with the + /// CefDoMessageLoopWork() function in cases where the CEF message loop must + /// be integrated into an existing application message loop (see additional + /// comments and warnings on CefDoMessageLoopWork). Enabling this option is + /// not recommended for most users; leave this option disabled and use either + /// the CefRunMessageLoop() function or multi_threaded_message_loop if + /// possible. + /// + int external_message_pump; + + /// + /// Set to true (1) to enable windowless (off-screen) rendering support. Do + /// not enable this value if the application does not use windowless rendering + /// as it may reduce rendering performance on some systems. + /// + int windowless_rendering_enabled; + + /// + /// Set to true (1) to disable configuration of browser process features using + /// standard CEF and Chromium command-line arguments. Configuration can still + /// be specified using CEF data structures or via the + /// CefApp::OnBeforeCommandLineProcessing() method. + /// + int command_line_args_disabled; + + /// + /// The location where data for the global browser cache will be stored on + /// disk. If this value is non-empty then it must be an absolute path that is + /// either equal to or a child directory of CefSettings.root_cache_path. If + /// this value is empty then browsers will be created in "incognito mode" + /// where in-memory caches are used for storage and no data is persisted to + /// disk. HTML5 databases such as localStorage will only persist across + /// sessions if a cache path is specified. Can be overridden for individual + /// CefRequestContext instances via the CefRequestContextSettings.cache_path + /// value. When using the Chrome runtime the "default" profile will be used if + /// |cache_path| and |root_cache_path| have the same value. + /// + cef_string_t cache_path; + + /// + /// The root directory that all CefSettings.cache_path and + /// CefRequestContextSettings.cache_path values must have in common. If this + /// value is empty and CefSettings.cache_path is non-empty then it will + /// default to the CefSettings.cache_path value. If both values are empty + /// then the default platform-specific directory will be used + /// ("~/.config/cef_user_data" directory on Linux, "~/Library/Application + /// Support/CEF/User Data" directory on MacOS, "AppData\Local\CEF\User Data" + /// directory under the user profile directory on Windows). If this value is + /// non-empty then it must be an absolute path. Failure to set this value + /// correctly may result in the sandbox blocking read/write access to certain + /// files. + /// + cef_string_t root_cache_path; + + /// + /// To persist session cookies (cookies without an expiry date or validity + /// interval) by default when using the global cookie manager set this value + /// to true (1). Session cookies are generally intended to be transient and + /// most Web browsers do not persist them. A |cache_path| value must also be + /// specified to enable this feature. Also configurable using the + /// "persist-session-cookies" command-line switch. Can be overridden for + /// individual CefRequestContext instances via the + /// CefRequestContextSettings.persist_session_cookies value. + /// + int persist_session_cookies; + + /// + /// To persist user preferences as a JSON file in the cache path directory set + /// this value to true (1). A |cache_path| value must also be specified + /// to enable this feature. Also configurable using the + /// "persist-user-preferences" command-line switch. Can be overridden for + /// individual CefRequestContext instances via the + /// CefRequestContextSettings.persist_user_preferences value. + /// + int persist_user_preferences; + + /// + /// Value that will be returned as the User-Agent HTTP header. If empty the + /// default User-Agent string will be used. Also configurable using the + /// "user-agent" command-line switch. + /// + cef_string_t user_agent; + + /// + /// Value that will be inserted as the product portion of the default + /// User-Agent string. If empty the Chromium product version will be used. If + /// |userAgent| is specified this value will be ignored. Also configurable + /// using the "user-agent-product" command-line switch. + /// + cef_string_t user_agent_product; + + /// + /// The locale string that will be passed to WebKit. If empty the default + /// locale of "en-US" will be used. This value is ignored on Linux where + /// locale is determined using environment variable parsing with the + /// precedence order: LANGUAGE, LC_ALL, LC_MESSAGES and LANG. Also + /// configurable using the "lang" command-line switch. + /// + cef_string_t locale; + + /// + /// The directory and file name to use for the debug log. If empty a default + /// log file name and location will be used. On Windows and Linux a + /// "debug.log" file will be written in the main executable directory. On + /// MacOS a "~/Library/Logs/[app name]_debug.log" file will be written where + /// [app name] is the name of the main app executable. Also configurable using + /// the "log-file" command-line switch. + /// + cef_string_t log_file; + + /// + /// The log severity. Only messages of this severity level or higher will be + /// logged. When set to DISABLE no messages will be written to the log file, + /// but FATAL messages will still be output to stderr. Also configurable using + /// the "log-severity" command-line switch with a value of "verbose", "info", + /// "warning", "error", "fatal" or "disable". + /// + cef_log_severity_t log_severity; + + /// + /// The log items prepended to each log line. If not set the default log items + /// will be used. Also configurable using the "log-items" command-line switch + /// with a value of "none" for no log items, or a comma-delimited list of + /// values "pid", "tid", "timestamp" or "tickcount" for custom log items. + /// + cef_log_items_t log_items; + + /// + /// Custom flags that will be used when initializing the V8 JavaScript engine. + /// The consequences of using custom flags may not be well tested. Also + /// configurable using the "js-flags" command-line switch. + /// + cef_string_t javascript_flags; + + /// + /// The fully qualified path for the resources directory. If this value is + /// empty the *.pak files must be located in the module directory on + /// Windows/Linux or the app bundle Resources directory on MacOS. If this + /// value is non-empty then it must be an absolute path. Also configurable + /// using the "resources-dir-path" command-line switch. + /// + cef_string_t resources_dir_path; + + /// + /// The fully qualified path for the locales directory. If this value is empty + /// the locales directory must be located in the module directory. If this + /// value is non-empty then it must be an absolute path. This value is ignored + /// on MacOS where pack files are always loaded from the app bundle Resources + /// directory. Also configurable using the "locales-dir-path" command-line + /// switch. + /// + cef_string_t locales_dir_path; + + /// + /// Set to true (1) to disable loading of pack files for resources and + /// locales. A resource bundle handler must be provided for the browser and + /// render processes via CefApp::GetResourceBundleHandler() if loading of pack + /// files is disabled. Also configurable using the "disable-pack-loading" + /// command- line switch. + /// + int pack_loading_disabled; + + /// + /// Set to a value between 1024 and 65535 to enable remote debugging on the + /// specified port. Also configurable using the "remote-debugging-port" + /// command-line switch. Remote debugging can be accessed by loading the + /// chrome://inspect page in Google Chrome. Port numbers 9222 and 9229 are + /// discoverable by default. Other port numbers may need to be configured via + /// "Discover network targets" on the Devices tab. + /// + int remote_debugging_port; + + /// + /// The number of stack trace frames to capture for uncaught exceptions. + /// Specify a positive value to enable the + /// CefRenderProcessHandler::OnUncaughtException() callback. Specify 0 + /// (default value) and OnUncaughtException() will not be called. Also + /// configurable using the "uncaught-exception-stack-size" command-line + /// switch. + /// + int uncaught_exception_stack_size; + + /// + /// Background color used for the browser before a document is loaded and when + /// no document color is specified. The alpha component must be either fully + /// opaque (0xFF) or fully transparent (0x00). If the alpha component is fully + /// opaque then the RGB components will be used as the background color. If + /// the alpha component is fully transparent for a windowed browser then the + /// default value of opaque white be used. If the alpha component is fully + /// transparent for a windowless (off-screen) browser then transparent + /// painting will be enabled. + /// + cef_color_t background_color; + + /// + /// Comma delimited ordered list of language codes without any whitespace that + /// will be used in the "Accept-Language" HTTP header. May be overridden on a + /// per-browser basis using the CefBrowserSettings.accept_language_list value. + /// If both values are empty then "en-US,en" will be used. Can be overridden + /// for individual CefRequestContext instances via the + /// CefRequestContextSettings.accept_language_list value. + /// + cef_string_t accept_language_list; + + /// + /// Comma delimited list of schemes supported by the associated + /// CefCookieManager. If |cookieable_schemes_exclude_defaults| is false (0) + /// the default schemes ("http", "https", "ws" and "wss") will also be + /// supported. Not specifying a |cookieable_schemes_list| value and setting + /// |cookieable_schemes_exclude_defaults| to true (1) will disable all loading + /// and saving of cookies. These settings will only impact the global + /// CefRequestContext. Individual CefRequestContext instances can be + /// configured via the CefRequestContextSettings.cookieable_schemes_list and + /// CefRequestContextSettings.cookieable_schemes_exclude_defaults values. + /// + cef_string_t cookieable_schemes_list; + int cookieable_schemes_exclude_defaults; +} cef_settings_t; + +/// +/// Browser initialization settings. Specify NULL or 0 to get the recommended +/// default values. The consequences of using custom values may not be well +/// tested. Many of these and other settings can also configured using command- +/// line switches. +/// +typedef struct _cef_browser_settings_t { + /// + /// Size of this structure. + /// + size_t size; + + /// + /// The maximum rate in frames per second (fps) that CefRenderHandler::OnPaint + /// will be called for a windowless browser. The actual fps may be lower if + /// the browser cannot generate frames at the requested rate. The minimum + /// value is 1 and the maximum value is 60 (default 30). This value can also + /// be changed dynamically via CefBrowserHost::SetWindowlessFrameRate. + /// + int windowless_frame_rate; + + /// BEGIN values that map to WebPreferences settings. + + /// + /// Font settings. + /// + cef_string_t standard_font_family; + cef_string_t fixed_font_family; + cef_string_t serif_font_family; + cef_string_t sans_serif_font_family; + cef_string_t cursive_font_family; + cef_string_t fantasy_font_family; + int default_font_size; + int default_fixed_font_size; + int minimum_font_size; + int minimum_logical_font_size; + + /// + /// Default encoding for Web content. If empty "ISO-8859-1" will be used. Also + /// configurable using the "default-encoding" command-line switch. + /// + cef_string_t default_encoding; + + /// + /// Controls the loading of fonts from remote sources. Also configurable using + /// the "disable-remote-fonts" command-line switch. + /// + cef_state_t remote_fonts; + + /// + /// Controls whether JavaScript can be executed. Also configurable using the + /// "disable-javascript" command-line switch. + /// + cef_state_t javascript; + + /// + /// Controls whether JavaScript can be used to close windows that were not + /// opened via JavaScript. JavaScript can still be used to close windows that + /// were opened via JavaScript or that have no back/forward history. Also + /// configurable using the "disable-javascript-close-windows" command-line + /// switch. + /// + cef_state_t javascript_close_windows; + + /// + /// Controls whether JavaScript can access the clipboard. Also configurable + /// using the "disable-javascript-access-clipboard" command-line switch. + /// + cef_state_t javascript_access_clipboard; + + /// + /// Controls whether DOM pasting is supported in the editor via + /// execCommand("paste"). The |javascript_access_clipboard| setting must also + /// be enabled. Also configurable using the "disable-javascript-dom-paste" + /// command-line switch. + /// + cef_state_t javascript_dom_paste; + + /// + /// Controls whether image URLs will be loaded from the network. A cached + /// image will still be rendered if requested. Also configurable using the + /// "disable-image-loading" command-line switch. + /// + cef_state_t image_loading; + + /// + /// Controls whether standalone images will be shrunk to fit the page. Also + /// configurable using the "image-shrink-standalone-to-fit" command-line + /// switch. + /// + cef_state_t image_shrink_standalone_to_fit; + + /// + /// Controls whether text areas can be resized. Also configurable using the + /// "disable-text-area-resize" command-line switch. + /// + cef_state_t text_area_resize; + + /// + /// Controls whether the tab key can advance focus to links. Also configurable + /// using the "disable-tab-to-links" command-line switch. + /// + cef_state_t tab_to_links; + + /// + /// Controls whether local storage can be used. Also configurable using the + /// "disable-local-storage" command-line switch. + /// + cef_state_t local_storage; + + /// + /// Controls whether databases can be used. Also configurable using the + /// "disable-databases" command-line switch. + /// + cef_state_t databases; + + /// + /// Controls whether WebGL can be used. Note that WebGL requires hardware + /// support and may not work on all systems even when enabled. Also + /// configurable using the "disable-webgl" command-line switch. + /// + cef_state_t webgl; + + /// END values that map to WebPreferences settings. + + /// + /// Background color used for the browser before a document is loaded and when + /// no document color is specified. The alpha component must be either fully + /// opaque (0xFF) or fully transparent (0x00). If the alpha component is fully + /// opaque then the RGB components will be used as the background color. If + /// the alpha component is fully transparent for a windowed browser then the + /// CefSettings.background_color value will be used. If the alpha component is + /// fully transparent for a windowless (off-screen) browser then transparent + /// painting will be enabled. + /// + cef_color_t background_color; + + /// + /// Comma delimited ordered list of language codes without any whitespace that + /// will be used in the "Accept-Language" HTTP header. May be set globally + /// using the CefSettings.accept_language_list value. If both values are + /// empty then "en-US,en" will be used. + /// + cef_string_t accept_language_list; + + /// + /// Controls whether the Chrome status bubble will be used. Only supported + /// with the Chrome runtime. For details about the status bubble see + /// https://www.chromium.org/user-experience/status-bubble/ + /// + cef_state_t chrome_status_bubble; +} cef_browser_settings_t; + +/// +// All ref-counted framework structures must include this structure first. +/// +typedef struct _cef_base_ref_counted_t { + /// + // Size of the data structure. + /// + size_t size; + + /// + // Called to increment the reference count for the object. Should be called + // for every new copy of a pointer to a given object. + /// + void(CEF_CALLBACK* add_ref)(struct _cef_base_ref_counted_t* self); + + /// + // Called to decrement the reference count for the object. If the reference + // count falls to 0 the object should self-delete. Returns true (1) if the + // resulting reference count is 0. + /// + int(CEF_CALLBACK* release)(struct _cef_base_ref_counted_t* self); + + /// + // Returns true (1) if the current reference count is 1. + /// + int(CEF_CALLBACK* has_one_ref)(struct _cef_base_ref_counted_t* self); + + /// + // Returns true (1) if the current reference count is at least 1. + /// + int(CEF_CALLBACK* has_at_least_one_ref)(struct _cef_base_ref_counted_t* self); +} cef_base_ref_counted_t; + +/// +/// Implement this structure to provide handler implementations. Methods will be +/// called by the process and/or thread indicated. +/// +typedef struct _cef_app_t { + /// + /// Base structure. + /// + cef_base_ref_counted_t base; + + /// + /// Provides an opportunity to view and/or modify command-line arguments + /// before processing by CEF and Chromium. The |process_type| value will be + /// NULL for the browser process. Do not keep a reference to the + /// cef_command_line_t object passed to this function. The + /// cef_settings_t.command_line_args_disabled value can be used to start with + /// an NULL command-line object. Any values specified in CefSettings that + /// equate to command-line arguments will be set before this function is + /// called. Be cautious when using this function to modify command-line + /// arguments for non-browser processes as this may result in undefined + /// behavior including crashes. + /// + void(CEF_CALLBACK* on_before_command_line_processing)( + struct _cef_app_t* self, + const cef_string_t* process_type, + struct _cef_command_line_t* command_line); + + /// + /// Provides an opportunity to register custom schemes. Do not keep a + /// reference to the |registrar| object. This function is called on the main + /// thread for each process and the registered schemes should be the same + /// across all processes. + /// + void(CEF_CALLBACK* on_register_custom_schemes)( + struct _cef_app_t* self, + struct _cef_scheme_registrar_t* registrar); + + /// + /// Return the handler for resource bundle events. If + /// cef_settings_t.pack_loading_disabled is true (1) a handler must be + /// returned. If no handler is returned resources will be loaded from pack + /// files. This function is called by the browser and render processes on + /// multiple threads. + /// + struct _cef_resource_bundle_handler_t* ( + CEF_CALLBACK* get_resource_bundle_handler)(struct _cef_app_t* self); + + /// + /// Return the handler for functionality specific to the browser process. This + /// function is called on multiple threads in the browser process. + /// + struct _cef_browser_process_handler_t* ( + CEF_CALLBACK* get_browser_process_handler)(struct _cef_app_t* self); + + /// + /// Return the handler for functionality specific to the render process. This + /// function is called on the render process main thread. + /// + struct _cef_render_process_handler_t* ( + CEF_CALLBACK* get_render_process_handler)(struct _cef_app_t* self); +} cef_app_t; + +typedef struct _cef_main_args_t { + HINSTANCE instance; +} cef_main_args_t; + +/// +/// Structure representing window information. +/// +typedef struct _cef_window_info_t { + // Standard parameters required by CreateWindowEx() + DWORD ex_style; + cef_string_t window_name; + DWORD style; + cef_rect_t bounds; + cef_window_handle_t parent_window; + HMENU menu; + + /// + /// Set to true (1) to create the browser using windowless (off-screen) + /// rendering. No window will be created for the browser and all rendering + /// will occur via the CefRenderHandler interface. The |parent_window| value + /// will be used to identify monitor info and to act as the parent window for + /// dialogs, context menus, etc. If |parent_window| is not provided then the + /// main screen monitor will be used and some functionality that requires a + /// parent window may not function correctly. In order to create windowless + /// browsers the CefSettings.windowless_rendering_enabled value must be set to + /// true. Transparent painting is enabled by default but can be disabled by + /// setting CefBrowserSettings.background_color to an opaque value. + /// + int windowless_rendering_enabled; + + /// + /// Set to true (1) to enable shared textures for windowless rendering. Only + /// valid if windowless_rendering_enabled above is also set to true. Currently + /// only supported on Windows (D3D11). + /// + int shared_texture_enabled; + + /// + /// Set to true (1) to enable the ability to issue BeginFrame requests from + /// the client application by calling CefBrowserHost::SendExternalBeginFrame. + /// + int external_begin_frame_enabled; + + /// + /// Handle for the new browser window. Only used with windowed rendering. + /// + cef_window_handle_t window; +} cef_window_info_t; + +int (*cef_initialize)(const cef_main_args_t* args, + const struct _cef_settings_t* settings, + struct _cef_app_t* application, + void* windows_sandbox_info); + +/// +/// Implement this structure to provide handler implementations. +/// +typedef struct _cef_client_t { + /// + /// Base structure. + /// + cef_base_ref_counted_t base; + + /// + /// Return the handler for audio rendering events. + /// + struct _cef_audio_handler_t* (CEF_CALLBACK* get_audio_handler)( + struct _cef_client_t* self); + + /// + /// Return the handler for commands. If no handler is provided the default + /// implementation will be used. + /// + struct _cef_command_handler_t* (CEF_CALLBACK* get_command_handler)( + struct _cef_client_t* self); + + /// + /// Return the handler for context menus. If no handler is provided the + /// default implementation will be used. + /// + struct _cef_context_menu_handler_t* (CEF_CALLBACK* get_context_menu_handler)( + struct _cef_client_t* self); + + /// + /// Return the handler for dialogs. If no handler is provided the default + /// implementation will be used. + /// + struct _cef_dialog_handler_t* (CEF_CALLBACK* get_dialog_handler)( + struct _cef_client_t* self); + + /// + /// Return the handler for browser display state events. + /// + struct _cef_display_handler_t* (CEF_CALLBACK* get_display_handler)( + struct _cef_client_t* self); + + /// + /// Return the handler for download events. If no handler is returned + /// downloads will not be allowed. + /// + struct _cef_download_handler_t* (CEF_CALLBACK* get_download_handler)( + struct _cef_client_t* self); + + /// + /// Return the handler for drag events. + /// + struct _cef_drag_handler_t* (CEF_CALLBACK* get_drag_handler)( + struct _cef_client_t* self); + + /// + /// Return the handler for find result events. + /// + struct _cef_find_handler_t* (CEF_CALLBACK* get_find_handler)( + struct _cef_client_t* self); + + /// + /// Return the handler for focus events. + /// + struct _cef_focus_handler_t* (CEF_CALLBACK* get_focus_handler)( + struct _cef_client_t* self); + + /// + /// Return the handler for events related to cef_frame_t lifespan. This + /// function will be called once during cef_browser_t creation and the result + /// will be cached for performance reasons. + /// + struct _cef_frame_handler_t* (CEF_CALLBACK* get_frame_handler)( + struct _cef_client_t* self); + + /// + /// Return the handler for permission requests. + /// + struct _cef_permission_handler_t* (CEF_CALLBACK* get_permission_handler)( + struct _cef_client_t* self); + + /// + /// Return the handler for JavaScript dialogs. If no handler is provided the + /// default implementation will be used. + /// + struct _cef_jsdialog_handler_t* (CEF_CALLBACK* get_jsdialog_handler)( + struct _cef_client_t* self); + + /// + /// Return the handler for keyboard events. + /// + struct _cef_keyboard_handler_t* (CEF_CALLBACK* get_keyboard_handler)( + struct _cef_client_t* self); + + /// + /// Return the handler for browser life span events. + /// + struct _cef_life_span_handler_t* (CEF_CALLBACK* get_life_span_handler)( + struct _cef_client_t* self); + + /// + /// Return the handler for browser load status events. + /// + struct _cef_load_handler_t* (CEF_CALLBACK* get_load_handler)( + struct _cef_client_t* self); + + /// + /// Return the handler for printing on Linux. If a print handler is not + /// provided then printing will not be supported on the Linux platform. + /// + struct _cef_print_handler_t* (CEF_CALLBACK* get_print_handler)( + struct _cef_client_t* self); + + /// + /// Return the handler for off-screen rendering events. + /// + struct _cef_render_handler_t* (CEF_CALLBACK* get_render_handler)( + struct _cef_client_t* self); + + /// + /// Return the handler for browser request events. + /// + struct _cef_request_handler_t* (CEF_CALLBACK* get_request_handler)( + struct _cef_client_t* self); + + /// + /// Called when a new message is received from a different process. Return + /// true (1) if the message was handled or false (0) otherwise. It is safe to + /// keep a reference to |message| outside of this callback. + /// + int(CEF_CALLBACK* on_process_message_received)( + struct _cef_client_t* self, + struct _cef_browser_t* browser, + struct _cef_frame_t* frame, + cef_process_id_t source_process, + struct _cef_process_message_t* message); +} cef_client_t; + +/// +/// Structure representing a dictionary value. Can be used on any process and +/// thread. +/// +typedef struct _cef_dictionary_value_t { + /// + /// Base structure. + /// + cef_base_ref_counted_t base; + + /// + /// Returns true (1) if this object is valid. This object may become invalid + /// if the underlying data is owned by another object (e.g. list or + /// dictionary) and that other object is then modified or destroyed. Do not + /// call any other functions if this function returns false (0). + /// + int(CEF_CALLBACK* is_valid)(struct _cef_dictionary_value_t* self); + + /// + /// Returns true (1) if this object is currently owned by another object. + /// + int(CEF_CALLBACK* is_owned)(struct _cef_dictionary_value_t* self); + + /// + /// Returns true (1) if the values of this object are read-only. Some APIs may + /// expose read-only objects. + /// + int(CEF_CALLBACK* is_read_only)(struct _cef_dictionary_value_t* self); + + /// + /// Returns true (1) if this object and |that| object have the same underlying + /// data. If true (1) modifications to this object will also affect |that| + /// object and vice-versa. + /// + int(CEF_CALLBACK* is_same)(struct _cef_dictionary_value_t* self, + struct _cef_dictionary_value_t* that); + + /// + /// Returns true (1) if this object and |that| object have an equivalent + /// underlying value but are not necessarily the same object. + /// + int(CEF_CALLBACK* is_equal)(struct _cef_dictionary_value_t* self, + struct _cef_dictionary_value_t* that); + + /// + /// Returns a writable copy of this object. If |exclude_NULL_children| is true + /// (1) any NULL dictionaries or lists will be excluded from the copy. + /// + struct _cef_dictionary_value_t* (CEF_CALLBACK* copy)( + struct _cef_dictionary_value_t* self, + int exclude_empty_children); + + /// + /// Returns the number of values. + /// + size_t(CEF_CALLBACK* get_size)(struct _cef_dictionary_value_t* self); + + /// + /// Removes all values. Returns true (1) on success. + /// + int(CEF_CALLBACK* clear)(struct _cef_dictionary_value_t* self); + + /// + /// Returns true (1) if the current dictionary has a value for the given key. + /// + int(CEF_CALLBACK* has_key)(struct _cef_dictionary_value_t* self, + const cef_string_t* key); + + /// + /// Reads all keys for this dictionary into the specified vector. + /// + int(CEF_CALLBACK* get_keys)(struct _cef_dictionary_value_t* self, + cef_string_list_t keys); + + /// + /// Removes the value at the specified key. Returns true (1) is the value was + /// removed successfully. + /// + int(CEF_CALLBACK* remove)(struct _cef_dictionary_value_t* self, + const cef_string_t* key); + + /// + /// Returns the value type for the specified key. + /// + cef_value_type_t(CEF_CALLBACK* get_type)(struct _cef_dictionary_value_t* self, + const cef_string_t* key); + + /// + /// Returns the value at the specified key. For simple types the returned + /// value will copy existing data and modifications to the value will not + /// modify this object. For complex types (binary, dictionary and list) the + /// returned value will reference existing data and modifications to the value + /// will modify this object. + /// + struct _cef_value_t* (CEF_CALLBACK* get_value)( + struct _cef_dictionary_value_t* self, + const cef_string_t* key); + + /// + /// Returns the value at the specified key as type bool. + /// + int(CEF_CALLBACK* get_bool)(struct _cef_dictionary_value_t* self, + const cef_string_t* key); + + /// + /// Returns the value at the specified key as type int. + /// + int(CEF_CALLBACK* get_int)(struct _cef_dictionary_value_t* self, + const cef_string_t* key); + + /// + /// Returns the value at the specified key as type double. + /// + double(CEF_CALLBACK* get_double)(struct _cef_dictionary_value_t* self, + const cef_string_t* key); + + /// + /// Returns the value at the specified key as type string. + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t(CEF_CALLBACK* get_string)( + struct _cef_dictionary_value_t* self, + const cef_string_t* key); + + /// + /// Returns the value at the specified key as type binary. The returned value + /// will reference existing data. + /// + struct _cef_binary_value_t* (CEF_CALLBACK* get_binary)( + struct _cef_dictionary_value_t* self, + const cef_string_t* key); + + /// + /// Returns the value at the specified key as type dictionary. The returned + /// value will reference existing data and modifications to the value will + /// modify this object. + /// + struct _cef_dictionary_value_t* (CEF_CALLBACK* get_dictionary)( + struct _cef_dictionary_value_t* self, + const cef_string_t* key); + + /// + /// Returns the value at the specified key as type list. The returned value + /// will reference existing data and modifications to the value will modify + /// this object. + /// + struct _cef_list_value_t* (CEF_CALLBACK* get_list)( + struct _cef_dictionary_value_t* self, + const cef_string_t* key); + + /// + /// Sets the value at the specified key. Returns true (1) if the value was set + /// successfully. If |value| represents simple data then the underlying data + /// will be copied and modifications to |value| will not modify this object. + /// If |value| represents complex data (binary, dictionary or list) then the + /// underlying data will be referenced and modifications to |value| will + /// modify this object. + /// + int(CEF_CALLBACK* set_value)(struct _cef_dictionary_value_t* self, + const cef_string_t* key, + struct _cef_value_t* value); + + /// + /// Sets the value at the specified key as type null. Returns true (1) if the + /// value was set successfully. + /// + int(CEF_CALLBACK* set_null)(struct _cef_dictionary_value_t* self, + const cef_string_t* key); + + /// + /// Sets the value at the specified key as type bool. Returns true (1) if the + /// value was set successfully. + /// + int(CEF_CALLBACK* set_bool)(struct _cef_dictionary_value_t* self, + const cef_string_t* key, + int value); + + /// + /// Sets the value at the specified key as type int. Returns true (1) if the + /// value was set successfully. + /// + int(CEF_CALLBACK* set_int)(struct _cef_dictionary_value_t* self, + const cef_string_t* key, + int value); + + /// + /// Sets the value at the specified key as type double. Returns true (1) if + /// the value was set successfully. + /// + int(CEF_CALLBACK* set_double)(struct _cef_dictionary_value_t* self, + const cef_string_t* key, + double value); + + /// + /// Sets the value at the specified key as type string. Returns true (1) if + /// the value was set successfully. + /// + int(CEF_CALLBACK* set_string)(struct _cef_dictionary_value_t* self, + const cef_string_t* key, + const cef_string_t* value); + + /// + /// Sets the value at the specified key as type binary. Returns true (1) if + /// the value was set successfully. If |value| is currently owned by another + /// object then the value will be copied and the |value| reference will not + /// change. Otherwise, ownership will be transferred to this object and the + /// |value| reference will be invalidated. + /// + int(CEF_CALLBACK* set_binary)(struct _cef_dictionary_value_t* self, + const cef_string_t* key, + struct _cef_binary_value_t* value); + + /// + /// Sets the value at the specified key as type dict. Returns true (1) if the + /// value was set successfully. If |value| is currently owned by another + /// object then the value will be copied and the |value| reference will not + /// change. Otherwise, ownership will be transferred to this object and the + /// |value| reference will be invalidated. + /// + int(CEF_CALLBACK* set_dictionary)(struct _cef_dictionary_value_t* self, + const cef_string_t* key, + struct _cef_dictionary_value_t* value); + + /// + /// Sets the value at the specified key as type list. Returns true (1) if the + /// value was set successfully. If |value| is currently owned by another + /// object then the value will be copied and the |value| reference will not + /// change. Otherwise, ownership will be transferred to this object and the + /// |value| reference will be invalidated. + /// + int(CEF_CALLBACK* set_list)(struct _cef_dictionary_value_t* self, + const cef_string_t* key, + struct _cef_list_value_t* value); +} cef_dictionary_value_t; + +/// +/// Manage access to preferences. +/// +typedef struct _cef_preference_manager_t { + /// + /// Base structure. + /// + cef_base_ref_counted_t base; + + /// + /// Returns true (1) if a preference with the specified |name| exists. This + /// function must be called on the browser process UI thread. + /// + int(CEF_CALLBACK* has_preference)(struct _cef_preference_manager_t* self, + const cef_string_t* name); + + /// + /// Returns the value for the preference with the specified |name|. Returns + /// NULL if the preference does not exist. The returned object contains a copy + /// of the underlying preference value and modifications to the returned + /// object will not modify the underlying preference value. This function must + /// be called on the browser process UI thread. + /// + struct _cef_value_t* (CEF_CALLBACK* get_preference)( + struct _cef_preference_manager_t* self, + const cef_string_t* name); + + /// + /// Returns all preferences as a dictionary. If |include_defaults| is true (1) + /// then preferences currently at their default value will be included. The + /// returned object contains a copy of the underlying preference values and + /// modifications to the returned object will not modify the underlying + /// preference values. This function must be called on the browser process UI + /// thread. + /// + struct _cef_dictionary_value_t* (CEF_CALLBACK* get_all_preferences)( + struct _cef_preference_manager_t* self, + int include_defaults); + + /// + /// Returns true (1) if the preference with the specified |name| can be + /// modified using SetPreference. As one example preferences set via the + /// command-line usually cannot be modified. This function must be called on + /// the browser process UI thread. + /// + int(CEF_CALLBACK* can_set_preference)(struct _cef_preference_manager_t* self, + const cef_string_t* name); + + /// + /// Set the |value| associated with preference |name|. Returns true (1) if the + /// value is set successfully and false (0) otherwise. If |value| is NULL the + /// preference will be restored to its default value. If setting the + /// preference fails then |error| will be populated with a detailed + /// description of the problem. This function must be called on the browser + /// process UI thread. + /// + int(CEF_CALLBACK* set_preference)(struct _cef_preference_manager_t* self, + const cef_string_t* name, + struct _cef_value_t* value, + cef_string_t* error); +} cef_preference_manager_t; + +/// +/// Generic callback structure used for asynchronous completion. +/// +typedef struct _cef_completion_callback_t { + /// + /// Base structure. + /// + cef_base_ref_counted_t base; + + /// + /// Method that will be called once the task is complete. + /// + void(CEF_CALLBACK* on_complete)(struct _cef_completion_callback_t* self); +} cef_completion_callback_t; + +/// +/// Represents a wall clock time in UTC. Values are not guaranteed to be +/// monotonically non-decreasing and are subject to large amounts of skew. +/// Time is stored internally as microseconds since the Windows epoch (1601). +/// +/// This is equivalent of Chromium `base::Time` (see base/time/time.h). +/// +typedef struct _cef_basetime_t { + int64_t val; +} cef_basetime_t; + +/// +/// Cookie priority values. +/// +typedef enum { + CEF_COOKIE_PRIORITY_LOW = -1, + CEF_COOKIE_PRIORITY_MEDIUM = 0, + CEF_COOKIE_PRIORITY_HIGH = 1, +} cef_cookie_priority_t; + +/// +/// Cookie same site values. +/// +typedef enum { + CEF_COOKIE_SAME_SITE_UNSPECIFIED, + CEF_COOKIE_SAME_SITE_NO_RESTRICTION, + CEF_COOKIE_SAME_SITE_LAX_MODE, + CEF_COOKIE_SAME_SITE_STRICT_MODE, +} cef_cookie_same_site_t; + +/// +/// Cookie information. +/// +typedef struct _cef_cookie_t { + /// + /// The cookie name. + /// + cef_string_t name; + + /// + /// The cookie value. + /// + cef_string_t value; + + /// + /// If |domain| is empty a host cookie will be created instead of a domain + /// cookie. Domain cookies are stored with a leading "." and are visible to + /// sub-domains whereas host cookies are not. + /// + cef_string_t domain; + + /// + /// If |path| is non-empty only URLs at or below the path will get the cookie + /// value. + /// + cef_string_t path; + + /// + /// If |secure| is true the cookie will only be sent for HTTPS requests. + /// + int secure; + + /// + /// If |httponly| is true the cookie will only be sent for HTTP requests. + /// + int httponly; + + /// + /// The cookie creation date. This is automatically populated by the system on + /// cookie creation. + /// + cef_basetime_t creation; + + /// + /// The cookie last access date. This is automatically populated by the system + /// on access. + /// + cef_basetime_t last_access; + + /// + /// The cookie expiration date is only valid if |has_expires| is true. + /// + int has_expires; + cef_basetime_t expires; + + /// + /// Same site. + /// + cef_cookie_same_site_t same_site; + + /// + /// Priority. + /// + cef_cookie_priority_t priority; +} cef_cookie_t; + +/// +/// Structure used for managing cookies. The functions of this structure may be +/// called on any thread unless otherwise indicated. +/// +typedef struct _cef_cookie_manager_t { + /// + /// Base structure. + /// + cef_base_ref_counted_t base; + + /// + /// Visit all cookies on the UI thread. The returned cookies are ordered by + /// longest path, then by earliest creation date. Returns false (0) if cookies + /// cannot be accessed. + /// + int(CEF_CALLBACK* visit_all_cookies)(struct _cef_cookie_manager_t* self, + struct _cef_cookie_visitor_t* visitor); + + /// + /// Visit a subset of cookies on the UI thread. The results are filtered by + /// the given url scheme, host, domain and path. If |includeHttpOnly| is true + /// (1) HTTP-only cookies will also be included in the results. The returned + /// cookies are ordered by longest path, then by earliest creation date. + /// Returns false (0) if cookies cannot be accessed. + /// + int(CEF_CALLBACK* visit_url_cookies)(struct _cef_cookie_manager_t* self, + const cef_string_t* url, + int includeHttpOnly, + struct _cef_cookie_visitor_t* visitor); + + /// + /// Sets a cookie given a valid URL and explicit user-provided cookie + /// attributes. This function expects each attribute to be well-formed. It + /// will check for disallowed characters (e.g. the ';' character is disallowed + /// within the cookie value attribute) and fail without setting the cookie if + /// such characters are found. If |callback| is non-NULL it will be executed + /// asnychronously on the UI thread after the cookie has been set. Returns + /// false (0) if an invalid URL is specified or if cookies cannot be accessed. + /// + int(CEF_CALLBACK* set_cookie)(struct _cef_cookie_manager_t* self, + const cef_string_t* url, + const struct _cef_cookie_t* cookie, + struct _cef_set_cookie_callback_t* callback); + + /// + /// Delete all cookies that match the specified parameters. If both |url| and + /// |cookie_name| values are specified all host and domain cookies matching + /// both will be deleted. If only |url| is specified all host cookies (but not + /// domain cookies) irrespective of path will be deleted. If |url| is NULL all + /// cookies for all hosts and domains will be deleted. If |callback| is non- + /// NULL it will be executed asnychronously on the UI thread after the cookies + /// have been deleted. Returns false (0) if a non-NULL invalid URL is + /// specified or if cookies cannot be accessed. Cookies can alternately be + /// deleted using the Visit*Cookies() functions. + /// + int(CEF_CALLBACK* delete_cookies)( + struct _cef_cookie_manager_t* self, + const cef_string_t* url, + const cef_string_t* cookie_name, + struct _cef_delete_cookies_callback_t* callback); + + /// + /// Flush the backing store (if any) to disk. If |callback| is non-NULL it + /// will be executed asnychronously on the UI thread after the flush is + /// complete. Returns false (0) if cookies cannot be accessed. + /// + int(CEF_CALLBACK* flush_store)(struct _cef_cookie_manager_t* self, + struct _cef_completion_callback_t* callback); +} cef_cookie_manager_t; + +/// +/// Returns the global cookie manager. By default data will be stored at +/// cef_settings_t.cache_path if specified or in memory otherwise. If |callback| +/// is non-NULL it will be executed asnychronously on the UI thread after the +/// manager's storage has been initialized. Using this function is equivalent to +/// calling cef_request_context_t::cef_request_context_get_global_context()->Get +/// DefaultCookieManager(). +/// +cef_cookie_manager_t* (*cef_cookie_manager_get_global_manager)( + struct _cef_completion_callback_t* callback); + +/// +/// Structure to implement for visiting cookie values. The functions of this +/// structure will always be called on the UI thread. +/// +typedef struct _cef_cookie_visitor_t { + /// + /// Base structure. + /// + cef_base_ref_counted_t base; + + /// + /// Method that will be called once for each cookie. |count| is the 0-based + /// index for the current cookie. |total| is the total number of cookies. Set + /// |deleteCookie| to true (1) to delete the cookie currently being visited. + /// Return false (0) to stop visiting cookies. This function may never be + /// called if no cookies are found. + /// + int(CEF_CALLBACK* visit)(struct _cef_cookie_visitor_t* self, + const struct _cef_cookie_t* cookie, + int count, + int total, + int* deleteCookie); +} cef_cookie_visitor_t; + +/// +/// Structure to implement to be notified of asynchronous completion via +/// cef_cookie_manager_t::set_cookie(). +/// +typedef struct _cef_set_cookie_callback_t { + /// + /// Base structure. + /// + cef_base_ref_counted_t base; + + /// + /// Method that will be called upon completion. |success| will be true (1) if + /// the cookie was set successfully. + /// + void(CEF_CALLBACK* on_complete)(struct _cef_set_cookie_callback_t* self, + int success); +} cef_set_cookie_callback_t; + +/// +/// Structure to implement to be notified of asynchronous completion via +/// cef_cookie_manager_t::delete_cookies(). +/// +typedef struct _cef_delete_cookies_callback_t { + /// + /// Base structure. + /// + cef_base_ref_counted_t base; + + /// + /// Method that will be called upon completion. |num_deleted| will be the + /// number of cookies that were deleted. + /// + void(CEF_CALLBACK* on_complete)(struct _cef_delete_cookies_callback_t* self, + int num_deleted); +} cef_delete_cookies_callback_t; + +/// +/// A request context provides request handling for a set of related browser or +/// URL request objects. A request context can be specified when creating a new +/// browser via the cef_browser_host_t static factory functions or when creating +/// a new URL request via the cef_urlrequest_t static factory functions. Browser +/// objects with different request contexts will never be hosted in the same +/// render process. Browser objects with the same request context may or may not +/// be hosted in the same render process depending on the process model. Browser +/// objects created indirectly via the JavaScript window.open function or +/// targeted links will share the same render process and the same request +/// context as the source browser. When running in single-process mode there is +/// only a single render process (the main process) and so all browsers created +/// in single-process mode will share the same request context. This will be the +/// first request context passed into a cef_browser_host_t static factory +/// function and all other request context objects will be ignored. +/// +typedef struct _cef_request_context_t { + /// + /// Base structure. + /// + cef_preference_manager_t base; + + /// + /// Returns true (1) if this object is pointing to the same context as |that| + /// object. + /// + int(CEF_CALLBACK* is_same)(struct _cef_request_context_t* self, + struct _cef_request_context_t* other); + + /// + /// Returns true (1) if this object is sharing the same storage as |that| + /// object. + /// + int(CEF_CALLBACK* is_sharing_with)(struct _cef_request_context_t* self, + struct _cef_request_context_t* other); + + /// + /// Returns true (1) if this object is the global context. The global context + /// is used by default when creating a browser or URL request with a NULL + /// context argument. + /// + int(CEF_CALLBACK* is_global)(struct _cef_request_context_t* self); + + /// + /// Returns the handler for this context if any. + /// + struct _cef_request_context_handler_t* (CEF_CALLBACK* get_handler)( + struct _cef_request_context_t* self); + + /// + /// Returns the cache path for this object. If NULL an "incognito mode" in- + /// memory cache is being used. + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t(CEF_CALLBACK* get_cache_path)( + struct _cef_request_context_t* self); + + /// + /// Returns the cookie manager for this object. If |callback| is non-NULL it + /// will be executed asnychronously on the UI thread after the manager's + /// storage has been initialized. + /// + struct _cef_cookie_manager_t* (CEF_CALLBACK* get_cookie_manager)( + struct _cef_request_context_t* self, + struct _cef_completion_callback_t* callback); + + /// + /// Register a scheme handler factory for the specified |scheme_name| and + /// optional |domain_name|. An NULL |domain_name| value for a standard scheme + /// will cause the factory to match all domain names. The |domain_name| value + /// will be ignored for non-standard schemes. If |scheme_name| is a built-in + /// scheme and no handler is returned by |factory| then the built-in scheme + /// handler factory will be called. If |scheme_name| is a custom scheme then + /// you must also implement the cef_app_t::on_register_custom_schemes() + /// function in all processes. This function may be called multiple times to + /// change or remove the factory that matches the specified |scheme_name| and + /// optional |domain_name|. Returns false (0) if an error occurs. This + /// function may be called on any thread in the browser process. + /// + int(CEF_CALLBACK* register_scheme_handler_factory)( + struct _cef_request_context_t* self, + const cef_string_t* scheme_name, + const cef_string_t* domain_name, + struct _cef_scheme_handler_factory_t* factory); + + /// + /// Clear all registered scheme handler factories. Returns false (0) on error. + /// This function may be called on any thread in the browser process. + /// + int(CEF_CALLBACK* clear_scheme_handler_factories)( + struct _cef_request_context_t* self); + + /// + /// Clears all certificate exceptions that were added as part of handling + /// cef_request_handler_t::on_certificate_error(). If you call this it is + /// recommended that you also call close_all_connections() or you risk not + /// being prompted again for server certificates if you reconnect quickly. If + /// |callback| is non-NULL it will be executed on the UI thread after + /// completion. + /// + void(CEF_CALLBACK* clear_certificate_exceptions)( + struct _cef_request_context_t* self, + struct _cef_completion_callback_t* callback); + + /// + /// Clears all HTTP authentication credentials that were added as part of + /// handling GetAuthCredentials. If |callback| is non-NULL it will be executed + /// on the UI thread after completion. + /// + void(CEF_CALLBACK* clear_http_auth_credentials)( + struct _cef_request_context_t* self, + struct _cef_completion_callback_t* callback); + + /// + /// Clears all active and idle connections that Chromium currently has. This + /// is only recommended if you have released all other CEF objects but don't + /// yet want to call cef_shutdown(). If |callback| is non-NULL it will be + /// executed on the UI thread after completion. + /// + void(CEF_CALLBACK* close_all_connections)( + struct _cef_request_context_t* self, + struct _cef_completion_callback_t* callback); + + /// + /// Attempts to resolve |origin| to a list of associated IP addresses. + /// |callback| will be executed on the UI thread after completion. + /// + void(CEF_CALLBACK* resolve_host)(struct _cef_request_context_t* self, + const cef_string_t* origin, + struct _cef_resolve_callback_t* callback); + + /// + /// Load an extension. + /// + /// If extension resources will be read from disk using the default load + /// implementation then |root_directory| should be the absolute path to the + /// extension resources directory and |manifest| should be NULL. If extension + /// resources will be provided by the client (e.g. via cef_request_handler_t + /// and/or cef_extension_handler_t) then |root_directory| should be a path + /// component unique to the extension (if not absolute this will be internally + /// prefixed with the PK_DIR_RESOURCES path) and |manifest| should contain the + /// contents that would otherwise be read from the "manifest.json" file on + /// disk. + /// + /// The loaded extension will be accessible in all contexts sharing the same + /// storage (HasExtension returns true (1)). However, only the context on + /// which this function was called is considered the loader (DidLoadExtension + /// returns true (1)) and only the loader will receive + /// cef_request_context_handler_t callbacks for the extension. + /// + /// cef_extension_handler_t::OnExtensionLoaded will be called on load success + /// or cef_extension_handler_t::OnExtensionLoadFailed will be called on load + /// failure. + /// + /// If the extension specifies a background script via the "background" + /// manifest key then cef_extension_handler_t::OnBeforeBackgroundBrowser will + /// be called to create the background browser. See that function for + /// additional information about background scripts. + /// + /// For visible extension views the client application should evaluate the + /// manifest to determine the correct extension URL to load and then pass that + /// URL to the cef_browser_host_t::CreateBrowser* function after the extension + /// has loaded. For example, the client can look for the "browser_action" + /// manifest key as documented at + /// https://developer.chrome.com/extensions/browserAction. Extension URLs take + /// the form "chrome-extension:///". + /// + /// Browsers that host extensions differ from normal browsers as follows: + /// - Can access chrome.* JavaScript APIs if allowed by the manifest. Visit + /// chrome://extensions-support for the list of extension APIs currently + /// supported by CEF. + /// - Main frame navigation to non-extension content is blocked. + /// - Pinch-zooming is disabled. + /// - CefBrowserHost::GetExtension returns the hosted extension. + /// - CefBrowserHost::IsBackgroundHost returns true for background hosts. + /// + /// See https://developer.chrome.com/extensions for extension implementation + /// and usage documentation. + /// + void(CEF_CALLBACK* load_extension)(struct _cef_request_context_t* self, + const cef_string_t* root_directory, + struct _cef_dictionary_value_t* manifest, + struct _cef_extension_handler_t* handler); + + /// + /// Returns true (1) if this context was used to load the extension identified + /// by |extension_id|. Other contexts sharing the same storage will also have + /// access to the extension (see HasExtension). This function must be called + /// on the browser process UI thread. + /// + int(CEF_CALLBACK* did_load_extension)(struct _cef_request_context_t* self, + const cef_string_t* extension_id); + + /// + /// Returns true (1) if this context has access to the extension identified by + /// |extension_id|. This may not be the context that was used to load the + /// extension (see DidLoadExtension). This function must be called on the + /// browser process UI thread. + /// + int(CEF_CALLBACK* has_extension)(struct _cef_request_context_t* self, + const cef_string_t* extension_id); + + /// + /// Retrieve the list of all extensions that this context has access to (see + /// HasExtension). |extension_ids| will be populated with the list of + /// extension ID values. Returns true (1) on success. This function must be + /// called on the browser process UI thread. + /// + int(CEF_CALLBACK* get_extensions)(struct _cef_request_context_t* self, + cef_string_list_t extension_ids); + + /// + /// Returns the extension matching |extension_id| or NULL if no matching + /// extension is accessible in this context (see HasExtension). This function + /// must be called on the browser process UI thread. + /// + struct _cef_extension_t* (CEF_CALLBACK* get_extension)( + struct _cef_request_context_t* self, + const cef_string_t* extension_id); + + /// + /// Returns the MediaRouter object associated with this context. If + /// |callback| is non-NULL it will be executed asnychronously on the UI thread + /// after the manager's context has been initialized. + /// + struct _cef_media_router_t* (CEF_CALLBACK* get_media_router)( + struct _cef_request_context_t* self, + struct _cef_completion_callback_t* callback); + + /// + /// Returns the current value for |content_type| that applies for the + /// specified URLs. If both URLs are NULL the default value will be returned. + /// Returns nullptr if no value is configured. Must be called on the browser + /// process UI thread. + /// + struct _cef_value_t* (CEF_CALLBACK* get_website_setting)( + struct _cef_request_context_t* self, + const cef_string_t* requesting_url, + const cef_string_t* top_level_url, + cef_content_setting_types_t content_type); + + /// + /// Sets the current value for |content_type| for the specified URLs in the + /// default scope. If both URLs are NULL, and the context is not incognito, + /// the default value will be set. Pass nullptr for |value| to remove the + /// default value for this content type. + /// + /// WARNING: Incorrect usage of this function may cause instability or + /// security issues in Chromium. Make sure that you first understand the + /// potential impact of any changes to |content_type| by reviewing the related + /// source code in Chromium. For example, if you plan to modify + /// CEF_CONTENT_SETTING_TYPE_POPUPS, first review and understand the usage of + /// ContentSettingsType::POPUPS in Chromium: + /// https://source.chromium.org/search?q=ContentSettingsType::POPUPS + /// + void(CEF_CALLBACK* set_website_setting)( + struct _cef_request_context_t* self, + const cef_string_t* requesting_url, + const cef_string_t* top_level_url, + cef_content_setting_types_t content_type, + struct _cef_value_t* value); + + /// + /// Returns the current value for |content_type| that applies for the + /// specified URLs. If both URLs are NULL the default value will be returned. + /// Returns CEF_CONTENT_SETTING_VALUE_DEFAULT if no value is configured. Must + /// be called on the browser process UI thread. + /// + cef_content_setting_values_t(CEF_CALLBACK* get_content_setting)( + struct _cef_request_context_t* self, + const cef_string_t* requesting_url, + const cef_string_t* top_level_url, + cef_content_setting_types_t content_type); + + /// + /// Sets the current value for |content_type| for the specified URLs in the + /// default scope. If both URLs are NULL, and the context is not incognito, + /// the default value will be set. Pass CEF_CONTENT_SETTING_VALUE_DEFAULT for + /// |value| to use the default value for this content type. + /// + /// WARNING: Incorrect usage of this function may cause instability or + /// security issues in Chromium. Make sure that you first understand the + /// potential impact of any changes to |content_type| by reviewing the related + /// source code in Chromium. For example, if you plan to modify + /// CEF_CONTENT_SETTING_TYPE_POPUPS, first review and understand the usage of + /// ContentSettingsType::POPUPS in Chromium: + /// https://source.chromium.org/search?q=ContentSettingsType::POPUPS + /// + void(CEF_CALLBACK* set_content_setting)( + struct _cef_request_context_t* self, + const cef_string_t* requesting_url, + const cef_string_t* top_level_url, + cef_content_setting_types_t content_type, + cef_content_setting_values_t value); +} cef_request_context_t; + +/// +/// Implement this structure to handle view events. All size and position values +/// are in density independent pixels (DIP) unless otherwise indicated. The +/// functions of this structure will be called on the browser process UI thread +/// unless otherwise indicated. +/// +typedef struct _cef_view_delegate_t { + /// + /// Base structure. + /// + cef_base_ref_counted_t base; + + /// + /// Return the preferred size for |view|. The Layout will use this information + /// to determine the display size. + /// + cef_size_t(CEF_CALLBACK* get_preferred_size)( + struct _cef_view_delegate_t* self, + struct _cef_view_t* view); + + /// + /// Return the minimum size for |view|. + /// + cef_size_t(CEF_CALLBACK* get_minimum_size)(struct _cef_view_delegate_t* self, + struct _cef_view_t* view); + + /// + /// Return the maximum size for |view|. + /// + cef_size_t(CEF_CALLBACK* get_maximum_size)(struct _cef_view_delegate_t* self, + struct _cef_view_t* view); + + /// + /// Return the height necessary to display |view| with the provided |width|. + /// If not specified the result of get_preferred_size().height will be used by + /// default. Override if |view|'s preferred height depends upon the width (for + /// example, with Labels). + /// + int(CEF_CALLBACK* get_height_for_width)(struct _cef_view_delegate_t* self, + struct _cef_view_t* view, + int width); + + /// + /// Called when the parent of |view| has changed. If |view| is being added to + /// |parent| then |added| will be true (1). If |view| is being removed from + /// |parent| then |added| will be false (0). If |view| is being reparented the + /// remove notification will be sent before the add notification. Do not + /// modify the view hierarchy in this callback. + /// + void(CEF_CALLBACK* on_parent_view_changed)(struct _cef_view_delegate_t* self, + struct _cef_view_t* view, + int added, + struct _cef_view_t* parent); + + /// + /// Called when a child of |view| has changed. If |child| is being added to + /// |view| then |added| will be true (1). If |child| is being removed from + /// |view| then |added| will be false (0). If |child| is being reparented the + /// remove notification will be sent to the old parent before the add + /// notification is sent to the new parent. Do not modify the view hierarchy + /// in this callback. + /// + void(CEF_CALLBACK* on_child_view_changed)(struct _cef_view_delegate_t* self, + struct _cef_view_t* view, + int added, + struct _cef_view_t* child); + + /// + /// Called when |view| is added or removed from the cef_window_t. + /// + void(CEF_CALLBACK* on_window_changed)(struct _cef_view_delegate_t* self, + struct _cef_view_t* view, + int added); + + /// + /// Called when the layout of |view| has changed. + /// + void(CEF_CALLBACK* on_layout_changed)(struct _cef_view_delegate_t* self, + struct _cef_view_t* view, + const cef_rect_t* new_bounds); + + /// + /// Called when |view| gains focus. + /// + void(CEF_CALLBACK* on_focus)(struct _cef_view_delegate_t* self, + struct _cef_view_t* view); + + /// + /// Called when |view| loses focus. + /// + void(CEF_CALLBACK* on_blur)(struct _cef_view_delegate_t* self, + struct _cef_view_t* view); +} cef_view_delegate_t; + +/// +/// Implement this structure to handle BrowserView events. The functions of this +/// structure will be called on the browser process UI thread unless otherwise +/// indicated. +/// +typedef struct _cef_browser_view_delegate_t { + /// + /// Base structure. + /// + cef_view_delegate_t base; + + /// + /// Called when |browser| associated with |browser_view| is created. This + /// function will be called after cef_life_span_handler_t::on_after_created() + /// is called for |browser| and before on_popup_browser_view_created() is + /// called for |browser|'s parent delegate if |browser| is a popup. + /// + void(CEF_CALLBACK* on_browser_created)( + struct _cef_browser_view_delegate_t* self, + struct _cef_browser_view_t* browser_view, + struct _cef_browser_t* browser); + + /// + /// Called when |browser| associated with |browser_view| is destroyed. Release + /// all references to |browser| and do not attempt to execute any functions on + /// |browser| after this callback returns. This function will be called before + /// cef_life_span_handler_t::on_before_close() is called for |browser|. + /// + void(CEF_CALLBACK* on_browser_destroyed)( + struct _cef_browser_view_delegate_t* self, + struct _cef_browser_view_t* browser_view, + struct _cef_browser_t* browser); + + /// + /// Called before a new popup BrowserView is created. The popup originated + /// from |browser_view|. |settings| and |client| are the values returned from + /// cef_life_span_handler_t::on_before_popup(). |is_devtools| will be true (1) + /// if the popup will be a DevTools browser. Return the delegate that will be + /// used for the new popup BrowserView. + /// + struct _cef_browser_view_delegate_t* ( + CEF_CALLBACK* get_delegate_for_popup_browser_view)( + struct _cef_browser_view_delegate_t* self, + struct _cef_browser_view_t* browser_view, + const struct _cef_browser_settings_t* settings, + struct _cef_client_t* client, + int is_devtools); + + /// + /// Called after |popup_browser_view| is created. This function will be called + /// after cef_life_span_handler_t::on_after_created() and on_browser_created() + /// are called for the new popup browser. The popup originated from + /// |browser_view|. |is_devtools| will be true (1) if the popup is a DevTools + /// browser. Optionally add |popup_browser_view| to the views hierarchy + /// yourself and return true (1). Otherwise return false (0) and a default + /// cef_window_t will be created for the popup. + /// + int(CEF_CALLBACK* on_popup_browser_view_created)( + struct _cef_browser_view_delegate_t* self, + struct _cef_browser_view_t* browser_view, + struct _cef_browser_view_t* popup_browser_view, + int is_devtools); + + /// + /// Returns the Chrome toolbar type that will be available via + /// cef_browser_view_t::get_chrome_toolbar(). See that function for related + /// documentation. + /// + cef_chrome_toolbar_type_t(CEF_CALLBACK* get_chrome_toolbar_type)( + struct _cef_browser_view_delegate_t* self); + + /// + /// Called when |browser_view| receives a gesture command. Return true (1) to + /// handle (or disable) a |gesture_command| or false (0) to propagate the + /// gesture to the browser for default handling. This function will only be + /// called with the Alloy runtime. To handle these commands with the Chrome + /// runtime implement cef_command_handler_t::OnChromeCommand instead. + /// + int(CEF_CALLBACK* on_gesture_command)( + struct _cef_browser_view_delegate_t* self, + struct _cef_browser_view_t* browser_view, + cef_gesture_command_t gesture_command); +} cef_browser_view_delegate_t; + +/// +/// A View is a rectangle within the views View hierarchy. It is the base +/// structure for all Views. All size and position values are in density +/// independent pixels (DIP) unless otherwise indicated. Methods must be called +/// on the browser process UI thread unless otherwise indicated. +/// +typedef struct _cef_view_t { + /// + /// Base structure. + /// + cef_base_ref_counted_t base; + + /// + /// Returns this View as a BrowserView or NULL if this is not a BrowserView. + /// + struct _cef_browser_view_t* (CEF_CALLBACK* as_browser_view)( + struct _cef_view_t* self); + + /// + /// Returns this View as a Button or NULL if this is not a Button. + /// + struct _cef_button_t* (CEF_CALLBACK* as_button)(struct _cef_view_t* self); + + /// + /// Returns this View as a Panel or NULL if this is not a Panel. + /// + struct _cef_panel_t* (CEF_CALLBACK* as_panel)(struct _cef_view_t* self); + + /// + /// Returns this View as a ScrollView or NULL if this is not a ScrollView. + /// + struct _cef_scroll_view_t* (CEF_CALLBACK* as_scroll_view)( + struct _cef_view_t* self); + + /// + /// Returns this View as a Textfield or NULL if this is not a Textfield. + /// + struct _cef_textfield_t* (CEF_CALLBACK* as_textfield)( + struct _cef_view_t* self); + + /// + /// Returns the type of this View as a string. Used primarily for testing + /// purposes. + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t(CEF_CALLBACK* get_type_string)( + struct _cef_view_t* self); + + /// + /// Returns a string representation of this View which includes the type and + /// various type-specific identifying attributes. If |include_children| is + /// true (1) any child Views will also be included. Used primarily for testing + /// purposes. + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t(CEF_CALLBACK* to_string)(struct _cef_view_t* self, + int include_children); + + /// + /// Returns true (1) if this View is valid. + /// + int(CEF_CALLBACK* is_valid)(struct _cef_view_t* self); + + /// + /// Returns true (1) if this View is currently attached to another View. A + /// View can only be attached to one View at a time. + /// + int(CEF_CALLBACK* is_attached)(struct _cef_view_t* self); + + /// + /// Returns true (1) if this View is the same as |that| View. + /// + int(CEF_CALLBACK* is_same)(struct _cef_view_t* self, + struct _cef_view_t* that); + + /// + /// Returns the delegate associated with this View, if any. + /// + struct _cef_view_delegate_t* (CEF_CALLBACK* get_delegate)( + struct _cef_view_t* self); + + /// + /// Returns the top-level Window hosting this View, if any. + /// + struct _cef_window_t* (CEF_CALLBACK* get_window)(struct _cef_view_t* self); + + /// + /// Returns the ID for this View. + /// + int(CEF_CALLBACK* get_id)(struct _cef_view_t* self); + + /// + /// Sets the ID for this View. ID should be unique within the subtree that you + /// intend to search for it. 0 is the default ID for views. + /// + void(CEF_CALLBACK* set_id)(struct _cef_view_t* self, int id); + + /// + /// Returns the group id of this View, or -1 if not set. + /// + int(CEF_CALLBACK* get_group_id)(struct _cef_view_t* self); + + /// + /// A group id is used to tag Views which are part of the same logical group. + /// Focus can be moved between views with the same group using the arrow keys. + /// The group id is immutable once it's set. + /// + void(CEF_CALLBACK* set_group_id)(struct _cef_view_t* self, int group_id); + + /// + /// Returns the View that contains this View, if any. + /// + struct _cef_view_t* (CEF_CALLBACK* get_parent_view)(struct _cef_view_t* self); + + /// + /// Recursively descends the view tree starting at this View, and returns the + /// first child that it encounters with the given ID. Returns NULL if no + /// matching child view is found. + /// + struct _cef_view_t* (CEF_CALLBACK* get_view_for_id)(struct _cef_view_t* self, + int id); + + /// + /// Sets the bounds (size and position) of this View. |bounds| is in parent + /// coordinates, or DIP screen coordinates if there is no parent. + /// + void(CEF_CALLBACK* set_bounds)(struct _cef_view_t* self, + const cef_rect_t* bounds); + + /// + /// Returns the bounds (size and position) of this View in parent coordinates, + /// or DIP screen coordinates if there is no parent. + /// + cef_rect_t(CEF_CALLBACK* get_bounds)(struct _cef_view_t* self); + + /// + /// Returns the bounds (size and position) of this View in DIP screen + /// coordinates. + /// + cef_rect_t(CEF_CALLBACK* get_bounds_in_screen)(struct _cef_view_t* self); + + /// + /// Sets the size of this View without changing the position. |size| in parent + /// coordinates, or DIP screen coordinates if there is no parent. + /// + void(CEF_CALLBACK* set_size)(struct _cef_view_t* self, + const cef_size_t* size); + + /// + /// Returns the size of this View in parent coordinates, or DIP screen + /// coordinates if there is no parent. + /// + cef_size_t(CEF_CALLBACK* get_size)(struct _cef_view_t* self); + + /// + /// Sets the position of this View without changing the size. |position| is in + /// parent coordinates, or DIP screen coordinates if there is no parent. + /// + void(CEF_CALLBACK* set_position)(struct _cef_view_t* self, + const cef_point_t* position); + + /// + /// Returns the position of this View. Position is in parent coordinates, or + /// DIP screen coordinates if there is no parent. + /// + cef_point_t(CEF_CALLBACK* get_position)(struct _cef_view_t* self); + + /// + /// Sets the insets for this View. |insets| is in parent coordinates, or DIP + /// screen coordinates if there is no parent. + /// + void(CEF_CALLBACK* set_insets)(struct _cef_view_t* self, + const cef_insets_t* insets); + + /// + /// Returns the insets for this View in parent coordinates, or DIP screen + /// coordinates if there is no parent. + /// + cef_insets_t(CEF_CALLBACK* get_insets)(struct _cef_view_t* self); + + /// + /// Returns the size this View would like to be if enough space is available. + /// Size is in parent coordinates, or DIP screen coordinates if there is no + /// parent. + /// + cef_size_t(CEF_CALLBACK* get_preferred_size)(struct _cef_view_t* self); + + /// + /// Size this View to its preferred size. Size is in parent coordinates, or + /// DIP screen coordinates if there is no parent. + /// + void(CEF_CALLBACK* size_to_preferred_size)(struct _cef_view_t* self); + + /// + /// Returns the minimum size for this View. Size is in parent coordinates, or + /// DIP screen coordinates if there is no parent. + /// + cef_size_t(CEF_CALLBACK* get_minimum_size)(struct _cef_view_t* self); + + /// + /// Returns the maximum size for this View. Size is in parent coordinates, or + /// DIP screen coordinates if there is no parent. + /// + cef_size_t(CEF_CALLBACK* get_maximum_size)(struct _cef_view_t* self); + + /// + /// Returns the height necessary to display this View with the provided width. + /// + int(CEF_CALLBACK* get_height_for_width)(struct _cef_view_t* self, int width); + + /// + /// Indicate that this View and all parent Views require a re-layout. This + /// ensures the next call to layout() will propagate to this View even if the + /// bounds of parent Views do not change. + /// + void(CEF_CALLBACK* invalidate_layout)(struct _cef_view_t* self); + + /// + /// Sets whether this View is visible. Windows are hidden by default and other + /// views are visible by default. This View and any parent views must be set + /// as visible for this View to be drawn in a Window. If this View is set as + /// hidden then it and any child views will not be drawn and, if any of those + /// views currently have focus, then focus will also be cleared. Painting is + /// scheduled as needed. If this View is a Window then calling this function + /// is equivalent to calling the Window show() and hide() functions. + /// + void(CEF_CALLBACK* set_visible)(struct _cef_view_t* self, int visible); + + /// + /// Returns whether this View is visible. A view may be visible but still not + /// drawn in a Window if any parent views are hidden. If this View is a Window + /// then a return value of true (1) indicates that this Window is currently + /// visible to the user on-screen. If this View is not a Window then call + /// is_drawn() to determine whether this View and all parent views are visible + /// and will be drawn. + /// + int(CEF_CALLBACK* is_visible)(struct _cef_view_t* self); + + /// + /// Returns whether this View is visible and drawn in a Window. A view is + /// drawn if it and all parent views are visible. If this View is a Window + /// then calling this function is equivalent to calling is_visible(). + /// Otherwise, to determine if the containing Window is visible to the user + /// on-screen call is_visible() on the Window. + /// + int(CEF_CALLBACK* is_drawn)(struct _cef_view_t* self); + + /// + /// Set whether this View is enabled. A disabled View does not receive + /// keyboard or mouse inputs. If |enabled| differs from the current value the + /// View will be repainted. Also, clears focus if the focused View is + /// disabled. + /// + void(CEF_CALLBACK* set_enabled)(struct _cef_view_t* self, int enabled); + + /// + /// Returns whether this View is enabled. + /// + int(CEF_CALLBACK* is_enabled)(struct _cef_view_t* self); + + /// + /// Sets whether this View is capable of taking focus. It will clear focus if + /// the focused View is set to be non-focusable. This is false (0) by default + /// so that a View used as a container does not get the focus. + /// + void(CEF_CALLBACK* set_focusable)(struct _cef_view_t* self, int focusable); + + /// + /// Returns true (1) if this View is focusable, enabled and drawn. + /// + int(CEF_CALLBACK* is_focusable)(struct _cef_view_t* self); + + /// + /// Return whether this View is focusable when the user requires full keyboard + /// access, even though it may not be normally focusable. + /// + int(CEF_CALLBACK* is_accessibility_focusable)(struct _cef_view_t* self); + + /// + /// Request keyboard focus. If this View is focusable it will become the + /// focused View. + /// + void(CEF_CALLBACK* request_focus)(struct _cef_view_t* self); + + /// + /// Sets the background color for this View. + /// + void(CEF_CALLBACK* set_background_color)(struct _cef_view_t* self, + cef_color_t color); + + /// + /// Returns the background color for this View. + /// + cef_color_t(CEF_CALLBACK* get_background_color)(struct _cef_view_t* self); + + /// + /// Convert |point| from this View's coordinate system to DIP screen + /// coordinates. This View must belong to a Window when calling this function. + /// Returns true (1) if the conversion is successful or false (0) otherwise. + /// Use cef_display_t::convert_point_to_pixels() after calling this function + /// if further conversion to display-specific pixel coordinates is desired. + /// + int(CEF_CALLBACK* convert_point_to_screen)(struct _cef_view_t* self, + cef_point_t* point); + + /// + /// Convert |point| to this View's coordinate system from DIP screen + /// coordinates. This View must belong to a Window when calling this function. + /// Returns true (1) if the conversion is successful or false (0) otherwise. + /// Use cef_display_t::convert_point_from_pixels() before calling this + /// function if conversion from display-specific pixel coordinates is + /// necessary. + /// + int(CEF_CALLBACK* convert_point_from_screen)(struct _cef_view_t* self, + cef_point_t* point); + + /// + /// Convert |point| from this View's coordinate system to that of the Window. + /// This View must belong to a Window when calling this function. Returns true + /// (1) if the conversion is successful or false (0) otherwise. + /// + int(CEF_CALLBACK* convert_point_to_window)(struct _cef_view_t* self, + cef_point_t* point); + + /// + /// Convert |point| to this View's coordinate system from that of the Window. + /// This View must belong to a Window when calling this function. Returns true + /// (1) if the conversion is successful or false (0) otherwise. + /// + int(CEF_CALLBACK* convert_point_from_window)(struct _cef_view_t* self, + cef_point_t* point); + + /// + /// Convert |point| from this View's coordinate system to that of |view|. + /// |view| needs to be in the same Window but not necessarily the same view + /// hierarchy. Returns true (1) if the conversion is successful or false (0) + /// otherwise. + /// + int(CEF_CALLBACK* convert_point_to_view)(struct _cef_view_t* self, + struct _cef_view_t* view, + cef_point_t* point); + + /// + /// Convert |point| to this View's coordinate system from that |view|. |view| + /// needs to be in the same Window but not necessarily the same view + /// hierarchy. Returns true (1) if the conversion is successful or false (0) + /// otherwise. + /// + int(CEF_CALLBACK* convert_point_from_view)(struct _cef_view_t* self, + struct _cef_view_t* view, + cef_point_t* point); +} cef_view_t; + +/// +/// Create a new browser using the window parameters specified by |windowInfo|. +/// All values will be copied internally and the actual window (if any) will be +/// created on the UI thread. If |request_context| is NULL the global request +/// context will be used. This function can be called on any browser process +/// thread and will not block. The optional |extra_info| parameter provides an +/// opportunity to specify extra information specific to the created browser +/// that will be passed to cef_render_process_handler_t::on_browser_created() in +/// the render process. +/// +int (*cef_browser_host_create_browser)( + const cef_window_info_t* windowInfo, + struct _cef_client_t* client, + const cef_string_t* url, + const struct _cef_browser_settings_t* settings, + struct _cef_dictionary_value_t* extra_info, + struct _cef_request_context_t* request_context); diff --git a/src/local/local.cpp b/src/local/local.cpp index 2f440ad..8b1b552 100644 --- a/src/local/local.cpp +++ b/src/local/local.cpp @@ -1,4 +1,5 @@ #include +#include using namespace std; @@ -23,6 +24,12 @@ namespace local return result; } + string u16_u8(const u16string& str) + { + std::wstring_convert, char16_t> utf16conv; + return utf16conv.to_bytes(str); + } + wstring u8_wide(const string& str) { wstring result; diff --git a/src/local/local.hpp b/src/local/local.hpp index 56aa2c0..0f25e32 100644 --- a/src/local/local.hpp +++ b/src/local/local.hpp @@ -3,6 +3,7 @@ namespace local { std::string wide_u8(const std::wstring& str); + std::string u16_u8(const std::u16string& str); std::wstring u8_wide(const std::string& str); std::string wide_acp(const std::wstring& str); std::wstring acp_wide(const std::string& str); diff --git a/src/main.cpp b/src/main.cpp index d5cc7bd..0b9df58 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,6 +1,7 @@ #include #include +extern bool init_hook_base(); extern bool init_hook(); extern void uninit_hook(); extern void start_console(); @@ -38,6 +39,7 @@ std::string g_replace_assetbundle_file_path; std::vector g_replace_assetbundle_file_paths; std::string g_replace_text_db_path; bool g_character_system_text_caption = false; +int g_character_system_text_caption_line_char_count = 26; int g_character_system_text_caption_font_size = 50; string g_character_system_text_caption_font_color = "White"; string g_character_system_text_caption_outline_size = "L"; @@ -280,6 +282,11 @@ namespace g_character_system_text_caption = document["characterSystemTextCaption"].GetBool(); } + if (document.HasMember("characterSystemTextCaptionLineCharCount")) + { + g_character_system_text_caption_line_char_count = document["characterSystemTextCaptionLineCharCount"].GetInt(); + } + if (document.HasMember("characterSystemTextCaptionFontSize")) { g_character_system_text_caption_font_size = document["characterSystemTextCaptionFontSize"].GetInt(); @@ -389,6 +396,152 @@ extern "C" __declspec(dllexport) int __stdcall UnityMain(HINSTANCE hInstance, HI return reinterpret_cast(GetProcAddress(player, "UnityMain"))(hInstance, hPrevInstance, lpCmdLine, nShowCmd); } +void DoStopSvc() +{ + SC_HANDLE schSCManager; + SC_HANDLE schService; + + SERVICE_STATUS_PROCESS ssp; + DWORD dwStartTime = GetTickCount(); + DWORD dwBytesNeeded; + DWORD dwTimeout = 30000; // 30-second time-out + DWORD dwWaitTime; + + // Get a handle to the SCM database. + + schSCManager = OpenSCManager( + NULL, // local computer + NULL, // ServicesActive database + SC_MANAGER_ALL_ACCESS); // full access rights + + if (NULL == schSCManager) + { + cout << "OpenSCManager failed (" << GetLastError() << ")" << endl; + return; + } + + // Get a handle to the service. + + schService = OpenService( + schSCManager, // SCM database + "ucldr_Umamusume_KR", // name of service + SERVICE_STOP | + SERVICE_QUERY_STATUS | + SERVICE_ENUMERATE_DEPENDENTS); + + if (schService == NULL) + { + cout << "OpenService failed (" << GetLastError() << ")" << endl; + CloseServiceHandle(schSCManager); + return; + } + + // Make sure the service is not already stopped. + + if (!QueryServiceStatusEx( + schService, + SC_STATUS_PROCESS_INFO, + (LPBYTE)&ssp, + sizeof(SERVICE_STATUS_PROCESS), + &dwBytesNeeded)) + { + cout << "QueryServiceStatusEx failed (" << GetLastError() << ")" << endl;; + goto stop_cleanup; + } + + if (ssp.dwCurrentState == SERVICE_STOPPED) + { + cout << "Service is already stopped." << endl; + goto stop_cleanup; + } + + // If a stop is pending, wait for it. + + while (ssp.dwCurrentState == SERVICE_STOP_PENDING) + { + cout << "Service stop pending..." << endl;; + + // Do not wait longer than the wait hint. A good interval is + // one-tenth of the wait hint but not less than 1 second + // and not more than 10 seconds. + + dwWaitTime = ssp.dwWaitHint / 10; + + if (dwWaitTime < 1000) + dwWaitTime = 1000; + else if (dwWaitTime > 10000) + dwWaitTime = 10000; + + Sleep(dwWaitTime); + + if (!QueryServiceStatusEx( + schService, + SC_STATUS_PROCESS_INFO, + (LPBYTE)&ssp, + sizeof(SERVICE_STATUS_PROCESS), + &dwBytesNeeded)) + { + cout << "QueryServiceStatusEx failed (" << GetLastError() << ")" << endl; + goto stop_cleanup; + } + + if (ssp.dwCurrentState == SERVICE_STOPPED) + { + cout << "Service stopped successfully." << endl; + goto stop_cleanup; + } + + if (GetTickCount() - dwStartTime > dwTimeout) + { + cout << "Service stop timed out." << endl; + goto stop_cleanup; + } + } + + // Send a stop code to the service. + + if (!ControlService( + schService, + SERVICE_CONTROL_STOP, + (LPSERVICE_STATUS)&ssp)) + { + cout << "ControlService failed (" << GetLastError() << ")" << endl; + goto stop_cleanup; + } + + // Wait for the service to stop. + + while (ssp.dwCurrentState != SERVICE_STOPPED) + { + Sleep(ssp.dwWaitHint); + if (!QueryServiceStatusEx( + schService, + SC_STATUS_PROCESS_INFO, + (LPBYTE)&ssp, + sizeof(SERVICE_STATUS_PROCESS), + &dwBytesNeeded)) + { + cout << "QueryServiceStatusEx failed (" << GetLastError() << ")" << endl; + goto stop_cleanup; + } + + if (ssp.dwCurrentState == SERVICE_STOPPED) + break; + + if (GetTickCount() - dwStartTime > dwTimeout) + { + cout << "Wait timed out" << endl; + goto stop_cleanup; + } + } + cout << "Service stopped successfully" << endl; + +stop_cleanup: + CloseServiceHandle(schService); + CloseServiceHandle(schSCManager); +} + + int __stdcall DllMain(HINSTANCE, DWORD reason, LPVOID) { if (reason == DLL_PROCESS_ATTACH) @@ -408,19 +561,67 @@ int __stdcall DllMain(HINSTANCE, DWORD reason, LPVOID) module_path.parent_path() ); + auto dicts = read_config(); + + if (g_enable_console) + create_debug_console(); + if (filesystem::exists(module_path.parent_path().append(module_path.filename().replace_extension().string().append("_Data\\Plugins\\x86_64\\KakaoGameWin.dll"s).data()))) { Game::CurrentGameRegion = Game::Region::KOR; + + if (IsElevated()) + { + DoStopSvc(); + } + + auto uncheater_path = module_path.parent_path().append(module_path.filename().replace_extension().string().append("_Data\\StreamingAssets\\Uncheater"s).data()); + auto uncheater_path_new = module_path.parent_path().append(module_path.filename().replace_extension().string().append("_Data\\StreamingAssets\\_Uncheater"s).data()); + + if (filesystem::exists(uncheater_path_new)) + { + try + { + filesystem::remove_all(uncheater_path_new); + } + catch (exception& e) + { + cout << "_Uncheater remove error: " << e.what() << endl; + } + } + + if (filesystem::exists(uncheater_path)) + { + try + { + filesystem::rename(uncheater_path, uncheater_path_new); + } + catch (exception& e) + { + cout << "Uncheater rename error: " << e.what() << endl; + + auto xnina_path = module_path.parent_path().append(module_path.filename().replace_extension().string().append("_Data\\StreamingAssets\\Uncheater\\xnina_x64.xem"s).data()); + if (filesystem::exists(xnina_path)) + { + try + { + filesystem::remove(xnina_path); + } + catch (exception& e) + { + cout << "xnina_x64.xem remove error: " << e.what() << endl; + } + } + } + } + } else { Game::CurrentGameRegion = Game::Region::JAP; } - auto dicts = read_config(); - - if (g_enable_console) - create_debug_console(); + init_hook_base(); std::thread init_thread([dicts]() { logger::init_logger(); diff --git a/src/rich_presence.hpp b/src/rich_presence.hpp index d3f31ac..e85282e 100644 --- a/src/rich_presence.hpp +++ b/src/rich_presence.hpp @@ -709,7 +709,7 @@ namespace } if (sceneId == "SingleMode") { - textId = "Outgame213036"; + textId = "Common0273"; } if (sceneId == "OutGame") { diff --git a/src/stdinclude.hpp b/src/stdinclude.hpp index 760de42..ab1f16e 100644 --- a/src/stdinclude.hpp +++ b/src/stdinclude.hpp @@ -4,6 +4,8 @@ #include #include +#include + #include #include @@ -67,6 +69,7 @@ extern std::string g_replace_assetbundle_file_path; extern std::vector g_replace_assetbundle_file_paths; extern std::string g_replace_text_db_path; extern bool g_character_system_text_caption; +extern int g_character_system_text_caption_line_char_count; extern int g_character_system_text_caption_font_size; extern string g_character_system_text_caption_font_color; extern string g_character_system_text_caption_outline_size; @@ -102,4 +105,43 @@ namespace { start_pos += to.length(); // In case 'to' contains 'from', like replacing 'x' with 'yx' } } + + BOOL IsElevated() { + BOOL fRet = FALSE; + HANDLE hToken = NULL; + if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) { + TOKEN_ELEVATION Elevation{}; + DWORD cbSize = sizeof(TOKEN_ELEVATION); + if (GetTokenInformation(hToken, TokenElevation, &Elevation, sizeof(Elevation), &cbSize)) { + fRet = Elevation.TokenIsElevated; + } + } + if (hToken) { + CloseHandle(hToken); + } + return fRet; + } + + void KillProcessByName(const char* filename) + { + HANDLE hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPALL, NULL); + PROCESSENTRY32 pEntry; + pEntry.dwSize = sizeof(pEntry); + BOOL hRes = Process32First(hSnapShot, &pEntry); + while (hRes) + { + if (strcmp(pEntry.szExeFile, filename) == 0) + { + HANDLE hProcess = OpenProcess(PROCESS_TERMINATE, 0, + (DWORD)pEntry.th32ProcessID); + if (hProcess != NULL) + { + TerminateProcess(hProcess, 9); + CloseHandle(hProcess); + } + } + hRes = Process32Next(hSnapShot, &pEntry); + } + CloseHandle(hSnapShot); + } } \ No newline at end of file