From 2571be01f987868eb3b4418151d214167115c263 Mon Sep 17 00:00:00 2001 From: FakeMichau <49685661+FakeMichau@users.noreply.github.com> Date: Sun, 3 Aug 2025 18:30:49 +0200 Subject: [PATCH] Refactor pattern matching --- OptiPatcher/dllmain.cpp | 660 +++++++++++++--------------------------- OptiPatcher/framework.h | 2 +- 2 files changed, 216 insertions(+), 446 deletions(-) diff --git a/OptiPatcher/dllmain.cpp b/OptiPatcher/dllmain.cpp index c0419b0..3b0da6d 100644 --- a/OptiPatcher/dllmain.cpp +++ b/OptiPatcher/dllmain.cpp @@ -5,524 +5,294 @@ #include "Patcher.h" #include "Scanner.h" -static bool _patchResult = false; +static std::optional _patchResult = false; -extern "C" __declspec(dllexport) bool PatchResult() { return _patchResult; } +extern "C" __declspec(dllexport) bool PatchResult() { return _patchResult.has_value() && _patchResult.value(); } extern "C" __declspec(dllexport) void InitializeASI() { return; } -static void CheckForPatch() -{ - auto exeName = Util::ExePath().filename().string(); - auto exeNameLower = std::transform(exeName.begin(), exeName.end(), exeName.begin(), ::tolower); - auto exeModule = GetModuleHandle(nullptr); +// Common patch for common UE patterns is { 0x0C, 0x01 } - // Deep Rock Galactic - if (exeName == "fsd-win64-shipping.exe") - { - std::string_view pattern("4C 8B 6D E0 33 C0 48 8B 4D 40 " - "4C 89 6D C0 48 89 45 E0 48 89 " - "45 E8 48 85 C9 74 05 E8 ? ? " - "? ? E8 ? ? ? ? 84 C0 75"); // aiming at 84 C0 - auto patchAddress = (void*) scanner::GetAddress(exeModule, pattern, 37); - - // Old pattern - if (patchAddress == nullptr) - { - std::string_view oldPattern("4C 8B 75 00 33 C0 48 8B 4D 50 " - "4C 89 75 D0 48 89 45 00 48 89 " - "45 08 48 85 C9 74 05 E8 ? ? " - "? ? E8 ? ? ? ? 84 C0 75"); - patchAddress = (void*) scanner::GetAddress(exeModule, oldPattern, 37); - } +// offset 34 +std::string_view commonUEpattern1("B8 04 00 00 00 74 03 49 8B C7 " + "8B 34 30 4C 89 A4 24 78 02 00 " + "00 4C 89 B4 24 38 02 00 00 E8 " + "? ? ? ? 84 C0 75"); - if (patchAddress != nullptr) - { - std::vector patch = { 0x0C, 0x01 }; - patcher::PatchAddress(patchAddress, &patch); - _patchResult = true; - } - } +// offset 17 +std::string_view commonUEpattern2("49 8B C7 74 03 49 8B C5 46 8B 34 30 E8 ? ? ? ? 84 C0 75"); - // Forgive Me Father 2, The Midnight Walk, The Elder Scrolls IV: Oblivion Remastered - else if (exeName == "fmf2-win64-shipping.exe" || exeName == "fmf2-wingdk-shipping.exe" || - exeName == "themidnightwalk-win64-shipping.exe" || exeName == "themidnightwalk-wingdk-shipping.exe" || - exeName == "oblivionremastered-win64-shipping.exe" || exeName == "oblivionremastered-wingdk-shipping.exe") - { - std::string_view pattern("B8 04 00 00 00 74 03 49 8B C7 " - "8B 34 30 4C 89 A4 24 78 02 00 " - "00 4C 89 B4 24 38 02 00 00 E8 " - "? ? ? ? 84 C0 75"); - auto patchAddress = (void*) scanner::GetAddress(exeModule, pattern, 34); +// offset 15 +std::string_view commonUEpattern3("48 85 C9 74 05 E8 ? ? ? ? E8 ? ? ? ? 84 C0 75"); - if (patchAddress != nullptr) - { - std::vector patch = { 0x0C, 0x01 }; - patcher::PatchAddress(patchAddress, &patch); - _patchResult = true; - } - } +// offset 37, aiming at 84 C0 +std::string_view commonUEpattern4( + "4C 8B 6D E0 33 C0 48 8B 4D 40 4C 89 6D C0 48 89 45 E0 48 89 45 E8 48 85 C9 74 05 E8 ? ? ? ? E8 ? ? ? ? 84 C0 75"); - // 171, Clair Obscur: Expedition 33, Ranch Simulator - else if (exeName == "bgg-win64-shipping.exe" || exeName == "bgg-wingdk-shipping.exe" || - exeName == "sandfall-win64-shipping.exe" || exeName == "sandFall-wingdk-shipping.exe" || - exeName == "ranch_simulator-win64-shipping.exe" || exeName == "ranch_simulator-wingdk-shipping.exe") - { - std::string_view pattern("49 8B C7 74 03 49 8B C5 46 8B " - "34 30 E8 ? ? ? ? 84 C0 75"); - auto patchAddress = (void*) scanner::GetAddress(exeModule, pattern, 17); +// offset 17 +std::string_view commonUEpattern5("49 8B C6 74 03 49 8B C5 46 8B 3C 38 E8 ? ? ? ? 84 C0 75"); - if (patchAddress != nullptr) - { - std::vector patch = { 0x0C, 0x01 }; - patcher::PatchAddress(patchAddress, &patch); - _patchResult = true; - } - } +enum class StringCompareType +{ + exactMatch, + startsWith +}; - // The Talos Principle 2 - else if (exeName == "talos2-win64-shipping.exe" || exeName == "talos2-wingdk-shipping.exe") - { - std::string_view pattern("49 8B F4 EB 02 33 F6 42 8B 34 " - "36 E8 ? ? ? ? 84 C0 75"); - auto patchAddress = (void*) scanner::GetAddress(exeModule, pattern, 16); +struct ApplicationPatch +{ + StringCompareType compareType; + std::string_view nameToMatch; + std::string_view pattern; + ptrdiff_t offset; + std::vector patch; + bool lastPattern = true; // set to false if this is not the last required pattern to match for this game +}; + +#define NOT_LAST_REQUIRED_PATTERN false + +static const ApplicationPatch applicationPatches[] = { + // Deep Rock Galactic, old pattern + { StringCompareType::startsWith, + "fsd-win", + "4C 8B 75 00 33 C0 48 8B 4D 50 4C 89 75 D0 48 89 45 00 48 89 45 08 48 85 C9 74 05 E8 ? ? ? ? E8 ? ? ? ? 84 C0 75", + 37, + { 0x0C, 0x01 } }, - if (patchAddress != nullptr) - { - std::vector patch = { 0x0C, 0x01 }; - patcher::PatchAddress(patchAddress, &patch); - _patchResult = true; - } - } + // Deep Rock Galactic + { StringCompareType::startsWith, "fsd-win", commonUEpattern4, 37, { 0x0C, 0x01 } }, - // Witchfire - else if (exeName == "witchfire-win64-shipping.exe" || exeName == "witchfire-wingdk-shipping.exe") - { - std::string_view pattern("4C 8B 6D E0 33 C0 48 8B 4D 40 " - "4C 89 6D C0 48 89 45 E0 48 89 " - "45 E8 48 85 C9 74 05 E8 ? ? " - "? ? E8 ? ? ? ? 84 C0 75"); - auto patchAddress = (void*) scanner::GetAddress(exeModule, pattern, 37); + // Black Myth: Wukong benchmark + { StringCompareType::startsWith, "b1-win", commonUEpattern5, 17, { 0x0C, 0x01 } }, - if (patchAddress != nullptr) - { - std::vector patch = { 0x0C, 0x01 }; - patcher::PatchAddress(patchAddress, &patch); - _patchResult = true; - } - } + // Black Myth: Wukong + { StringCompareType::startsWith, + "b1-win", + "E8 ? ? ? ? 84 C0 49 8B C4 74 03 49 8B C6 8B 34 30 89 75 80 E8 ? ? ? ? 84 C0 75", + 26, + { 0x0C, 0x01 } }, - // The Persistence - else if (exeName == "persistence-win64-shipping.exe" || exeName == "persistence-wingdk-shipping.exe") - { - std::string_view pattern("33 C9 3B ? ? ? ? ? 0F 95 " - "C1 EB 02 33 C9 8B 1C 8B E8 ? " - "? ? ? 84 C0 75"); - auto patchAddress = (void*) scanner::GetAddress(exeModule, pattern, 23); + // Forgive Me Father 2 + { StringCompareType::startsWith, "fmf2-win", commonUEpattern1, 34, { 0x0C, 0x01 } }, - if (patchAddress != nullptr) - { - std::vector patch = { 0x0C, 0x01 }; - patcher::PatchAddress(patchAddress, &patch); - _patchResult = true; - } - } + // The Midnight Walk + { StringCompareType::startsWith, "themidnightwalk-win", commonUEpattern1, 34, { 0x0C, 0x01 } }, - // Lost Records: Bloom & Rage - else if (exeName == "bloom&rage.exe") - { - std::string_view pattern("49 8B C6 74 03 49 8B C5 46 8B " - "3C 38 E8 ? ? ? ? 84 C0 75"); - auto patchAddress = (void*) scanner::GetAddress(exeModule, pattern, 17); + // The Elder Scrolls IV: Oblivion Remastered + { StringCompareType::startsWith, "oblivionremastered-win", commonUEpattern1, 34, { 0x0C, 0x01 } }, - if (patchAddress != nullptr) - { - std::vector patch = { 0x0C, 0x01 }; - patcher::PatchAddress(patchAddress, &patch); - _patchResult = true; - } - } + // 171 + { StringCompareType::startsWith, "bgg-win", commonUEpattern2, 17, { 0x0C, 0x01 } }, - // Black Myth: Wukong - else if (exeName == "b1-win64-shipping.exe" || exeName == "b1-wingdk-shipping.exe") - { - std::string_view pattern("E8 ? ? ? ? 84 C0 49 8B C4 " - "74 03 49 8B C6 8B 34 30 89 75 " - "80 E8 ? ? ? ? 84 C0 75"); - auto patchAddress = (void*) scanner::GetAddress(exeModule, pattern, 26); + // Clair Obscur: Expedition 33 + { StringCompareType::startsWith, "sandfall-win", commonUEpattern2, 17, { 0x0C, 0x01 } }, - // Check for benchmark - if (patchAddress == nullptr) - { - std::string_view pattern2("49 8B C6 74 03 49 8B C5 46 8B " - "3C 38 E8 ? ? ? ? 84 C0 75"); - patchAddress = (void*) scanner::GetAddress(exeModule, pattern2, 17); - } + // Ranch Simulator + { StringCompareType::startsWith, "ranch_simulator-win", commonUEpattern2, 17, { 0x0C, 0x01 } }, - if (patchAddress != nullptr) - { - std::vector patch = { 0x0C, 0x01 }; - patcher::PatchAddress(patchAddress, &patch); - _patchResult = true; - } - } + // The Talos Principle 2 + { StringCompareType::startsWith, + "talos2-win", + "49 8B F4 EB 02 33 F6 42 8B 34 36 E8 ? ? ? ? 84 C0 75", + 16, + { 0x0C, 0x01 } }, + + // Witchfire + { StringCompareType::startsWith, "witchfire-win", commonUEpattern4, 37, { 0x0C, 0x01 } }, + + // The Persistence + { StringCompareType::startsWith, + "persistence-win", + "33 C9 3B ? ? ? ? ? 0F 95 C1 EB 02 33 C9 8B 1C 8B E8 ? ? ? ? 84 C0 75", + 23, + { 0x0C, 0x01 } }, + + // Lost Records: Bloom & Rage + { StringCompareType::exactMatch, "bloom&rage.exe", commonUEpattern5, 17, { 0x0C, 0x01 } }, // Banishers: Ghosts of New Eden // inline patch - else if (exeName == "banishers-win64-shipping.exe" || exeName == "banishers-wingdk-shipping.exe") - { - std::string_view pattern("45 33 C9 C7 44 24 20 03 00 00 " - "00 48 8D ? ? ? ? ? 48 8D " - "8D B0 00 00 00 45 8D 41 05 E8 " - "? ? ? ? 48 8B 4D 30 48 85 " - "C9 74 05 E8 ? ? ? ? 81 3D " // aiming at 81 3D - "? ? ? ? DE 10 00 00 74"); - auto patchAddress = (void*) scanner::GetAddress(exeModule, pattern, 48); - - if (patchAddress != nullptr) - { - std::vector patch = { 0x39, 0xC0, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90 }; - patcher::PatchAddress(patchAddress, &patch); - _patchResult = true; - } - } + { StringCompareType::startsWith, + "banishers-win", + "45 33 C9 C7 44 24 20 03 00 00 00 48 8D ? ? ? ? ? 48 8D 8D B0 00 00 00 45 8D 41 05 E8 ? ? ? ? 48 8B 4D 30 48 85 " + "C9 74 05 E8 ? ? ? ? 81 3D ? ? ? ? DE 10 00 00 74", // aiming at 81 3D + 48, + { 0x39, 0xC0, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90 } }, // Lies of P // inline patch - else if (exeName == "lop-win64-shipping.exe" || exeName == "lop-wingdk-shipping.exe") - { - std::string_view pattern("41 B9 1B 00 00 00 C7 44 24 20 " - "02 00 00 00 48 8D ? ? ? ? " - "? 48 8D 4D 68 45 8D 41 E9 E8 " - "? ? ? ? 48 8B 4D 10 48 85 " - "C9 74 05 E8 ? ? ? ? 81 3D " - "? ? ? ? ? ? ? ? 74 0D"); - auto patchAddress = (void*) scanner::GetAddress(exeModule, pattern, 48); - - if (patchAddress != nullptr) - { - std::vector patch = { 0x39, 0xC0, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90 }; - patcher::PatchAddress(patchAddress, &patch); - _patchResult = true; - } - } + { StringCompareType::startsWith, + "lop-win", + "41 B9 1B 00 00 00 C7 44 24 20 02 00 00 00 48 8D ? ? ? ? ? 48 8D 4D 68 45 8D 41 E9 E8 ? ? ? ? 48 8B 4D 10 48 85 " + "C9 74 05 E8 ? ? ? ? 81 3D ? ? ? ? ? ? ? ? 74 0D", + 48, + { 0x39, 0xC0, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90 } }, // ARK: Survival Ascended // inline patch - else if (exeName == "arkascended.exe") - { - std::string_view pattern("E8 ? ? ? ? 84 C0 74 02 B0 " - "01 84 C0 49 8B C5 74 03 49 8B " - "C4 81 3D ? ? ? ? ? ? ? " - "? 44 8B 04 30"); - auto patchAddress = (void*) scanner::GetAddress(exeModule, pattern, 21); - - if (patchAddress != nullptr) - { - std::vector patch = { 0x39, 0xC0, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90 }; - patcher::PatchAddress(patchAddress, &patch); - _patchResult = true; - } - } + { StringCompareType::exactMatch, + "arkascended.exe", + "E8 ? ? ? ? 84 C0 74 02 B0 01 84 C0 49 8B C5 74 03 49 8B C4 81 3D ? ? ? ? ? ? ? ? 44 8B 04 30", + 21, + { 0x39, 0xC0, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90 } }, // Alone in the Dark 2024 - else if (exeName == "aloneinthedark-win64-shipping.exe" || exeName == "aloneinthedark-wingdk-shipping.exe") - { - std::string_view pattern("4C 8B 65 F0 33 C0 48 8B 4D 48 " - "4C 89 65 C0 48 89 45 F0 48 89 " - "45 F8 48 85 C9 74 05 E8 ? ? " - "? ? E8 ? ? ? ? 84 C0 75"); - auto patchAddress = (void*) scanner::GetAddress(exeModule, pattern, 37); - - if (patchAddress != nullptr) - { - std::vector patch = { 0x0C, 0x01 }; - patcher::PatchAddress(patchAddress, &patch); - _patchResult = true; - } - } + { StringCompareType::startsWith, + "aloneinthedark-win", + "4C 8B 65 F0 33 C0 48 8B 4D 48 4C 89 65 C0 48 89 45 F0 48 89 45 F8 48 85 C9 74 05 E8 ? ? ? ? E8 ? ? ? ? 84 C0 75", + 37, + { 0x0C, 0x01 } }, // Atomic Heart - else if (exeName == "atomicheart-win64-shipping.exe" || exeName == "atomicheart-wingdk-shipping.exe") - { - std::string_view pattern("4C 8B 7D F0 33 C0 48 8B 4D 40 " - "4C 89 7D C0 48 89 45 F0 48 89 " - "45 F8 48 85 C9 74 05 E8 ? ? " - "? ? E8 ? ? ? ? 84 C0 75"); - - auto patchAddress = (void*) scanner::GetAddress(exeModule, pattern, 37); - - if (patchAddress != nullptr) - { - std::vector patch = { 0x0C, 0x01 }; - patcher::PatchAddress(patchAddress, &patch); - _patchResult = true; - } - } + { StringCompareType::startsWith, + "atomicheart-win", + "4C 8B 7D F0 33 C0 48 8B 4D 40 4C 89 7D C0 48 89 45 F0 48 89 45 F8 48 85 C9 74 05 E8 ? ? ? ? E8 ? ? ? ? 84 C0 75", + 37, + { 0x0C, 0x01 } }, // The Alters - else if (exeName == "thealters-win64-shipping.exe" || exeName == "thealters-wingdk-shipping.exe") - { - std::string_view pattern("E8 ? ? ? ? 84 C0 75 0C E8 " - "? ? ? ? 84 C0 49 8B C7 74 " - "03 49 8B C6 8B 34 30 E8 ? ? " - "? ? 84 C0 75"); - - auto patchAddress = (void*) scanner::GetAddress(exeModule, pattern, 32); - - if (patchAddress != nullptr) - { - std::vector patch = { 0x0C, 0x01 }; - patcher::PatchAddress(patchAddress, &patch); - _patchResult = true; - } - } + { StringCompareType::startsWith, + "thealters-win", + "E8 ? ? ? ? 84 C0 75 0C E8 ? ? ? ? 84 C0 49 8B C7 74 03 49 8B C6 8B 34 30 E8 ? ? ? ? 84 C0 75", + 32, + { 0x0C, 0x01 } }, // WUCHANG: Fallen Feathers - else if (exeName == "project_plague-win64-shipping.exe" || exeName == "project_plague-wingdk-shipping.exe") - { - std::string_view pattern("75 0C E8 ? ? ? ? 84 C0 49 " - "8B C7 74 03 49 8B C6 8B 34 30 " - "89 75 80 E8 ? ? ? ? 84 C0 " - "75"); - - auto patchAddress = (void*) scanner::GetAddress(exeModule, pattern, 28); - - if (patchAddress != nullptr) - { - std::vector patch = { 0x0C, 0x01 }; - patcher::PatchAddress(patchAddress, &patch); - _patchResult = true; - } - } + { StringCompareType::startsWith, + "project_plague-win", + "75 0C E8 ? ? ? ? 84 C0 49 8B C7 74 03 49 8B C6 8B 34 30 89 75 80 E8 ? ? ? ? 84 C0 75", + 28, + { 0x0C, 0x01 } }, // Enotria: The Last Song - else if (exeName == "enotria-win64-shipping.exe" || exeName == "enotria-wingdk-shipping.exe") - { - std::string_view pattern("84 C0 49 8B C7 74 03 49 8B C5 " - "46 8B 34 30 E8 ? ? ? ? 84 " - "C0 75"); - auto patchAddress = (void*) scanner::GetAddress(exeModule, pattern, 19); - if (patchAddress != nullptr) - { - std::vector patch = { 0x0C, 0x01 }; - patcher::PatchAddress(patchAddress, &patch); - _patchResult = true; - } - } + { StringCompareType::startsWith, + "enotria-win", + "84 C0 49 8B C7 74 03 49 8B C5 46 8B 34 30 E8 ? ? ? ? 84 C0 75", + 19, + { 0x0C, 0x01 } }, // The Ascent - else if (exeName == "theascent-win64-shipping.exe" || exeName == "theascent-wingdk-shipping.exe") - { - std::string_view pattern("48 85 C9 74 05 E8 ? ? ? ? " - "45 33 ED E9 ? ? ? ? E8 ? " - "? ? ? 84 C0"); - auto patchAddress = (void*) scanner::GetAddress(exeModule, pattern, 23); - if (patchAddress != nullptr) - { - std::vector patch = { 0x0C, 0x01 }; - patcher::PatchAddress(patchAddress, &patch); - _patchResult = true; - } - } + { StringCompareType::startsWith, + "theascent-win", + "48 85 C9 74 05 E8 ? ? ? ? 45 33 ED E9 ? ? ? ? E8 ? ? ? ? 84 C0", + 23, + { 0x0C, 0x01 } }, // Ghostrunner - else if (exeName == "ghostrunner-win64-shipping.exe" || exeName == "ghostrunner-wingdk-shipping.exe") - { - std::string_view pattern("75 14 44 88 6F 30"); - auto patchAddress = (void*) scanner::GetAddress(exeModule, pattern, 0); - if (patchAddress != nullptr) - { - std::vector patch = { 0xEB }; - patcher::PatchAddress(patchAddress, &patch); - _patchResult = true; - } - } + { StringCompareType::startsWith, "ghostrunner-win", "75 14 44 88 6F 30", 0, { 0xEB } }, // Ghostrunner 2 - else if (exeName == "ghostrunner2-win64-shipping.exe" || exeName == "ghostrunner2-wingdk-shipping.exe") - { - std::string_view pattern("48 85 C9 74 05 E8 ? ? ? ? " - "E8 ? ? ? ? 84 C0 75 "); - auto patchAddress = (void*) scanner::GetAddress(exeModule, pattern, 15); - if (patchAddress != nullptr) - { - std::vector patch = { 0x0C, 0x01 }; - patcher::PatchAddress(patchAddress, &patch); - _patchResult = true; - } - } + { StringCompareType::startsWith, "ghostrunner2-win", commonUEpattern3, 15, { 0x0C, 0x01 } }, // Deadlink - else if (exeName == "deadlink-win64-shipping.exe" || exeName == "deadlink-wingdk-shipping.exe") - { - std::string_view pattern("48 85 C9 74 05 E8 ? ? ? ? " - "E8 ? ? ? ? 84 C0 75"); - auto patchAddress = (void*) scanner::GetAddress(exeModule, pattern, 15); - if (patchAddress != nullptr) - { - std::vector patch = { 0x0C, 0x01 }; - patcher::PatchAddress(patchAddress, &patch); - _patchResult = true; - } - } + { StringCompareType::startsWith, "deadlink-win", commonUEpattern3, 15, { 0x0C, 0x01 } }, // Amid Evil - else if (exeName == "amidevil-win64-shipping.exe" || exeName == "amidevil-wingdk-shipping.exe") - { - std::string_view pattern("48 85 DB 74 08 48 8B CB E8 ? " - "? ? ? E8 ? ? ? ? 84 C0 75"); - auto patchAddress = (void*) scanner::GetAddress(exeModule, pattern, 18); - if (patchAddress != nullptr) - { - std::vector patch = { 0x0C, 0x01 }; - patcher::PatchAddress(patchAddress, &patch); - _patchResult = true; - } - } + { StringCompareType::startsWith, + "amidevil-win", + "48 85 DB 74 08 48 8B CB E8 ? ? ? ? E8 ? ? ? ? 84 C0 75", + 18, + { 0x0C, 0x01 } }, // Severed Steel - else if (exeName == "thankyouverycool-win64-shipping.exe" || exeName == "thankyouverycool-wingdk-shipping.exe") - { - std::string_view pattern("48 85 C9 74 05 E8 ? ? ? ? E8 ? ? ? ? 84 C0 75 "); - auto patchAddress = (void*) scanner::GetAddress(exeModule, pattern, 15); - if (patchAddress != nullptr) - { - std::vector patch = { 0x0C, 0x01 }; - patcher::PatchAddress(patchAddress, &patch); - _patchResult = true; - } - } + { StringCompareType::startsWith, "thankyouverycool-win", commonUEpattern3, 15, { 0x0C, 0x01 } }, // Achilles: Legends Untold - else if (exeName == "achilles-win64-shipping.exe" || exeName == "achilles-wingdk-shipping.exe") - { - std::string_view pattern("48 85 C9 74 05 E8 ? ? ? ? E8 ? ? ? ? 84 C0 75"); - auto patchAddress = (void*) scanner::GetAddress(exeModule, pattern, 15); - if (patchAddress != nullptr) - { - std::vector patch = { 0x0C, 0x01 }; - patcher::PatchAddress(patchAddress, &patch); - _patchResult = true; - } - } + { StringCompareType::startsWith, "achilles-win", commonUEpattern3, 15, { 0x0C, 0x01 } }, // LEGO® Builder's Journey - else if (exeName == "unityplayer.exe") - { - std::string_view pattern("48 8D 15 ? ? ? ? 48 89 D9 E8 ? ? ? ? 48 83 F8 FF"); - auto patchAddress = (void*) scanner::GetAddress(exeModule, pattern, 15); - if (patchAddress != nullptr) - { - std::vector patch = { 0xB8, 0x00, 0x00, 0x00, 0x00 }; - patcher::PatchAddress(patchAddress, &patch); - _patchResult = true; - } - } + { StringCompareType::exactMatch, + "unityplayer.exe", + "48 8D 15 ? ? ? ? 48 89 D9 E8 ? ? ? ? 48 83 F8 FF", + 15, + { 0xB8, 0x00, 0x00, 0x00, 0x00 } }, // Titan Quest II - else if (exeName == "tq2-win64-shipping.exe" || exeName == "tq2-wingdk-shipping.exe") - { - std::string_view pattern("84 C0 49 8B C6 74 03 49 8B C4 " - "8B 34 30 E8 ? ? ? ? 84 C0 " - "75 25"); - auto patchAddress = (void*) scanner::GetAddress(exeModule, pattern, 18); - if (patchAddress != nullptr) - { - std::vector patch = { 0x0C, 0x01 }; - patcher::PatchAddress(patchAddress, &patch); - _patchResult = true; - } - } + { StringCompareType::startsWith, + "tq2-win", + "84 C0 49 8B C6 74 03 49 8B C4 8B 34 30 E8 ? ? ? ? 84 C0 75 25", + 18, + { 0x0C, 0x01 } }, // RoboCop: Rogue City - else if (exeName == "robocop-win64-shipping.exe" || exeName == "robocop-wingdk-shipping.exe") - { - std::string_view patternDLSSCheck("74 03 49 8B C5 46 8B 3C 38 E8 " - "? ? ? ? 84 C0 75"); - auto patchAddressDLSSCheck = (void*) scanner::GetAddress(exeModule, patternDLSSCheck, 14); - - if (patchAddressDLSSCheck != nullptr) - { - std::vector patch = { 0x0C, 0x01 }; - patcher::PatchAddress(patchAddressDLSSCheck, &patch); - } - - std::string_view patternXeFGCheck("83 F8 03 0F 85 ? ? ? ? E8 " - "? ? ? ? 84 C0 0F 84"); - auto patchAddressXeFGCheck = (void*) scanner::GetAddress(exeModule, patternXeFGCheck, 14); - - if (patchAddressXeFGCheck != nullptr) - { - std::vector patch = { 0x0C, 0x01 }; - patcher::PatchAddress(patchAddressXeFGCheck, &patch); - } - - _patchResult = patchAddressDLSSCheck != nullptr; - } + { StringCompareType::startsWith, + "robocop-win", + "83 F8 03 0F 85 ? ? ? ? E8 ? ? ? ? 84 C0 0F 84", // XeFG + 14, + { 0x0C, 0x01 }, + NOT_LAST_REQUIRED_PATTERN }, // match DLSS as well + { StringCompareType::startsWith, + "robocop-win", + "74 03 49 8B C5 46 8B 3C 38 E8 ? ? ? ? 84 C0 75", // DLSS + 14, + { 0x0C, 0x01 } }, // DOOM Eternal // just nops a line for main game exe - else if (exeName == "doometernalx64vk.exe") - { - std::string_view pattern("80 3D ? ? ? ? ? 66 C7 05 " - "? ? ? ? ? ? 48 C7 05 ? " - "? ? ? ? ? ? ? 0F 84 ? " - "? ? ? 80 3D ? ? ? ? ? " - "0F 84 ? ? ? ? 48 8B ? ? " // aiming at 0F 84 - "? ? ? 48 8D"); - auto patchAddress = (void*) scanner::GetAddress(exeModule, pattern, 40); - - if (patchAddress != nullptr) - { - std::vector patch = { 0x90, 0x90, 0x90, 0x90, 0x90, 0x90 }; - patcher::PatchAddress(patchAddress, &patch); - _patchResult = true; - } - } + { StringCompareType::exactMatch, + "doometernalx64vk.exe", + "80 3D ? ? ? ? ? 66 C7 05 ? ? ? ? ? ? 48 C7 05 ? ? ? ? ? ? ? ? 0F 84 ? ? ? ? 80 3D ? ? ? ? ? 0F 84 ? ? ? ? 48 8B " + "? ? ? ? ? 48 8D", // aiming at the second 0F 84 + 40, + { 0x90, 0x90, 0x90, 0x90, 0x90, 0x90 } }, // DOOM Eternal - Sandbox // nops a line for sandbox exe - else if (exeName == "doomsandbox64vk.exe") - { - std::string_view pattern("48 C7 05 ? ? ? ? ? ? ? " - "? 0F 84 ? ? ? ? 80 3D ? " - "? ? ? ? 0F 84 ? ? ? ? " - "48 8B ? ? ? ? ? 48 8D"); - auto patchAddress = (void*) scanner::GetAddress(exeModule, pattern, 24); - - if (patchAddress != nullptr) - { - std::vector patch = { 0x90, 0x90, 0x90, 0x90, 0x90, 0x90 }; - patcher::PatchAddress(patchAddress, &patch); - _patchResult = true; - } - } + { StringCompareType::exactMatch, + "doomsandbox64vk.exe", + "48 C7 05 ? ? ? ? ? ? ? ? 0F 84 ? ? ? ? 80 3D ? ? ? ? ? 0F 84 ? ? ? ? 48 8B ? ? ? ? ? 48 8D", + 24, + { 0x90, 0x90, 0x90, 0x90, 0x90, 0x90 } }, // Red Dead Redemption 2 // Thanks to 0x-FADED // https://github.com/0x-FADED/RDR2-NVNGX-Loader - else if (exeName == "rdr2.exe") - { - std::string_view patternGPUCheck("E8 ? ? ? ? 4C 8B CB 48 8D 54 24 60"); - auto patchAddressGPU = (void*) scanner::GetAddress(exeModule, patternGPUCheck, -13); - - if (patchAddressGPU != nullptr) - { - std::vector patch = { 0x90, 0x90, 0x90, 0x90, 0x90, 0x90 }; - patcher::PatchAddress(patchAddressGPU, &patch); - } + { StringCompareType::exactMatch, + "rdr2.exe", + "E8 ? ? ? ? 4C 8B CB 48 8D 54 24 60", + -13, + { 0x90, 0x90, 0x90, 0x90, 0x90, 0x90 }, + NOT_LAST_REQUIRED_PATTERN }, + { StringCompareType::exactMatch, "rdr2.exe", "80 3D ? ? ? ? ? 75 ? 41 8B CF", 6, { 0x01 } }, +}; - std::string_view patternSigCheck("80 3D ? ? ? ? ? 75 ? 41 8B CF"); - auto patchAddressSigCheck = (void*) scanner::GetAddress(exeModule, patternSigCheck, 6); +static void CheckForPatch() +{ + auto exeName = Util::ExePath().filename().string(); + std::transform(exeName.begin(), exeName.end(), exeName.begin(), ::tolower); + auto exeModule = GetModuleHandle(nullptr); - if (patchAddressSigCheck != nullptr) - { - std::vector patch = { 0x01 }; - patcher::PatchAddress(patchAddressSigCheck, &patch); + // First successful matched patten with lastPattern == true will end matching + for (auto const& applicationPatch : applicationPatches) + { + if ((applicationPatch.compareType == StringCompareType::exactMatch && + exeName == applicationPatch.nameToMatch) || + (applicationPatch.compareType == StringCompareType::startsWith && + exeName.starts_with(applicationPatch.nameToMatch))) + { + auto patchAddress = + (void*) scanner::GetAddress(exeModule, applicationPatch.pattern, applicationPatch.offset); + if (patchAddress != nullptr) + { + patcher::PatchAddress(patchAddress, &applicationPatch.patch); + + if (applicationPatch.lastPattern) + { + if (_patchResult.has_value() && !_patchResult.value()) // last patch was not successful + _patchResult = false; + else // first patch or previous patch was successful + _patchResult = true; + + return; + } + } + else + { + _patchResult = false; + } } - - _patchResult = patchAddressGPU != nullptr && patchAddressSigCheck != nullptr; } + + if (!_patchResult.has_value()) + _patchResult = false; } BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) diff --git a/OptiPatcher/framework.h b/OptiPatcher/framework.h index 54b83e9..5a3602b 100644 --- a/OptiPatcher/framework.h +++ b/OptiPatcher/framework.h @@ -1,5 +1,5 @@ #pragma once -#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers // Windows Header Files #include