|
49 | 49 | #include <version_check.h> |
50 | 50 |
|
51 | 51 | static std::vector<HMODULE> _asiHandles; |
| 52 | +static std::vector<std::filesystem::directory_entry> _lateLoadingEntries; |
52 | 53 | static bool _passThruMode = false; |
53 | 54 |
|
54 | 55 | typedef const char*(CDECL* PFN_wine_get_version)(void); |
@@ -226,7 +227,16 @@ void LoadAsiPlugins() |
226 | 227 |
|
227 | 228 | if (ext == L".asi") |
228 | 229 | { |
229 | | - HMODULE hMod = NtdllProxy::LoadLibraryExW_Ldr(entry.path().c_str(), NULL, 0); |
| 230 | + std::wstring fileName = entry.path().filename().wstring(); |
| 231 | + std::transform(fileName.begin(), fileName.end(), fileName.begin(), |
| 232 | + [](wchar_t c) { return std::towlower(c); }); |
| 233 | + |
| 234 | + HMODULE hMod = nullptr; |
| 235 | + |
| 236 | + if (fileName.rfind(L"-loadlate") != std::wstring::npos) |
| 237 | + _lateLoadingEntries.push_back(entry); |
| 238 | + else |
| 239 | + hMod = NtdllProxy::LoadLibraryExW_Ldr(entry.path().c_str(), NULL, 0); |
230 | 240 |
|
231 | 241 | if (hMod != nullptr) |
232 | 242 | { |
@@ -266,6 +276,63 @@ void LoadAsiPlugins() |
266 | 276 | DWORD err = GetLastError(); |
267 | 277 | LOG_ERROR(L"Failed to load: {}, error {:X}", entry.path().wstring(), err); |
268 | 278 | } |
| 279 | + |
| 280 | + if (_lateLoadingEntries.size() > 0) |
| 281 | + { |
| 282 | + std::thread( |
| 283 | + []() |
| 284 | + { |
| 285 | + auto delay = Config::Instance()->LateAsiPluginsDelay.value_or_default(); |
| 286 | + LOG_INFO("Waiting {} seconds before loading late-load plugins...", delay); |
| 287 | + std::this_thread::sleep_for(std::chrono::seconds(delay)); |
| 288 | + |
| 289 | + for (const auto& entry : _lateLoadingEntries) |
| 290 | + { |
| 291 | + HMODULE hMod = NtdllProxy::LoadLibraryExW_Ldr(entry.path().c_str(), NULL, 0); |
| 292 | + |
| 293 | + if (hMod != nullptr) |
| 294 | + { |
| 295 | + LOG_INFO(L"Loaded late: {}", entry.path().wstring()); |
| 296 | + _asiHandles.push_back(hMod); |
| 297 | + |
| 298 | + auto init = |
| 299 | + (PFN_InitializeASI) KernelBaseProxy::GetProcAddress_()(hMod, "InitializeASI"); |
| 300 | + |
| 301 | + auto patchResult = |
| 302 | + (PFN_PatchResult) KernelBaseProxy::GetProcAddress_()(hMod, "PatchResult"); |
| 303 | + |
| 304 | + if (init != nullptr) |
| 305 | + init(); |
| 306 | + |
| 307 | + if (patchResult != nullptr) |
| 308 | + { |
| 309 | + auto pr = patchResult(); |
| 310 | + if (pr) |
| 311 | + { |
| 312 | + LOG_INFO("Game patching is successful"); |
| 313 | + State::Instance().isOptiPatcherSucceed = true; |
| 314 | + LOG_INFO("Disabling spoofing"); |
| 315 | + |
| 316 | + if (!Config::Instance()->DxgiSpoofing.has_value()) |
| 317 | + Config::Instance()->DxgiSpoofing.set_volatile_value(false); |
| 318 | + |
| 319 | + if (!Config::Instance()->VulkanSpoofing.has_value()) |
| 320 | + Config::Instance()->VulkanSpoofing.set_volatile_value(false); |
| 321 | + |
| 322 | + if (!Config::Instance()->VulkanExtensionSpoofing.has_value()) |
| 323 | + Config::Instance()->VulkanExtensionSpoofing.set_volatile_value(false); |
| 324 | + } |
| 325 | + } |
| 326 | + } |
| 327 | + else |
| 328 | + { |
| 329 | + DWORD err = GetLastError(); |
| 330 | + LOG_ERROR(L"Failed to load: {}, error {:X}", entry.path().wstring(), err); |
| 331 | + } |
| 332 | + } |
| 333 | + }) |
| 334 | + .detach(); |
| 335 | + } |
269 | 336 | } |
270 | 337 | } |
271 | 338 | } |
|
0 commit comments