diff --git a/shared/sdk/Application.cpp b/shared/sdk/Application.cpp index e6f6e54ea..c25e4b8d9 100644 --- a/shared/sdk/Application.cpp +++ b/shared/sdk/Application.cpp @@ -23,7 +23,7 @@ Application* Application::get() { } Application::Function* Application::get_functions() { - static auto functions_offset = []() -> std::optional { + static auto functions_offset = [this]() -> std::optional { spdlog::info("Searching for Application::functions offset..."); const auto mod = utility::get_executable(); @@ -72,6 +72,90 @@ Application::Function* Application::get_functions() { spdlog::info("Skipping invalid Application::functions offset: {:x}", candidate); } + bool found_wait_rendering = false; + bool found_begin_rendering = false; + bool found_end_rendering = false; + + const auto module_entry_enum = sdk::find_type_definition("via.ModuleEntry"); + + // screw that lets just bruteforce through the Application object looking for huge + // list of valid pointers within the current module + for (auto i = 0x100; i < 0x1000; i += sizeof(void*)) try { + const auto ptr = (Application::Function*)((uintptr_t)this + i); + + if (ptr == nullptr || IsBadReadPtr(ptr, sizeof(Application::Function) * 50)) { + continue; + } + + for (auto j = 0; j < 1024; ++j) try { + const auto& func = ptr[j]; + + if (func.description == nullptr || IsBadReadPtr(func.description, 32)) { + break; + } + + if (j == 0 && func.entry == nullptr || IsBadReadPtr(func.entry, sizeof(void*))) { + break; // the first one should always be valid. + } + + const auto name = std::string_view{func.description}; + + if (j == 0) { + if (module_entry_enum != nullptr) { + if (auto f = sdk::get_native_field(nullptr, module_entry_enum, name, true); f != nullptr) { + if (*f != func.priority) { + break; // the first one should always be valid. + } + } + } else if (func.priority != 1) { + break; // the first one should always be valid. + } + } + + if (name == "WaitRendering") { + if (module_entry_enum != nullptr) { + if (auto f = sdk::get_native_field(nullptr, module_entry_enum, "WaitRendering", true); f != nullptr) { + if (*f == func.priority) { + found_wait_rendering = true; + } + } + } else { + found_wait_rendering = true; + } + } else if (name == "BeginRendering") { + if (module_entry_enum != nullptr) { + if (auto f = sdk::get_native_field(nullptr, module_entry_enum, "BeginRendering", true); f != nullptr) { + if (*f == func.priority) { + found_begin_rendering = true; + } + } + } else { + found_begin_rendering = true; + } + } else if (name == "EndRendering") { + if (module_entry_enum != nullptr) { + if (auto f = sdk::get_native_field(nullptr, module_entry_enum, "EndRendering", true); f != nullptr) { + if (*f == func.priority) { + found_end_rendering = true; + } + } + } else { + found_end_rendering = true; + } + } + + if (found_wait_rendering && found_begin_rendering && found_end_rendering) { + spdlog::info("Application::functions offset: {:x}", i); + return i; + } + } catch (...) { + continue; + } + } catch(...) { + continue; + } + + spdlog::error("Cannot find Application::functions offset."); return std::nullopt;