diff --git a/shared/sdk/REGlobals.cpp b/shared/sdk/REGlobals.cpp index 030db4c18..17fe285d2 100644 --- a/shared/sdk/REGlobals.cpp +++ b/shared/sdk/REGlobals.cpp @@ -27,11 +27,16 @@ REGlobals::REGlobals() { auto start = (uintptr_t)mod; auto end = (uintptr_t)start + *utility::get_module_size(mod); + end -= 0x1000; + + spdlog::info("start: {:x}", start); + spdlog::info("end: {:x}", end); + // generic pattern used for all these globals auto pat = std::string{ "48 8D ? ? ? ? ? 48 B8 00 00 00 00 00 00 00 80" }; // find all the globals - for (auto i = utility::scan(start, end - start, pat); i.has_value(); i = utility::scan(*i + 1, end - (*i + 1), pat)) { + for (auto i = utility::scan(start, end - start, pat); i.has_value(); i = utility::scan(*i + 1, end - (*i + 1), pat)) try { auto ptr = utility::calculate_absolute(*i + 3); // Make sure the global is within the module boundaries @@ -56,6 +61,8 @@ REGlobals::REGlobals() { m_objects.insert(obj_ptr); m_object_list.push_back(obj_ptr); + } catch(...) { + } // Create a list of getter functions instead diff --git a/src/Mods.cpp b/src/Mods.cpp index 01dbd4080..3dfe54ee2 100644 --- a/src/Mods.cpp +++ b/src/Mods.cpp @@ -21,7 +21,7 @@ Mods::Mods() { m_mods.emplace_back(REFrameworkConfig::get()); -#if defined(RE3) || defined(RE8) || defined(MHRISE) +#if defined(REENGINE_AT) m_mods.emplace_back(std::make_unique()); #endif diff --git a/src/REFramework.cpp b/src/REFramework.cpp index b6f4049e4..ba341f7cb 100644 --- a/src/REFramework.cpp +++ b/src/REFramework.cpp @@ -245,7 +245,7 @@ REFramework::REFramework(HMODULE reframework_module) spdlog::info("D3D12 loaded"); #endif -#if defined(MHRISE) +#if defined(MHRISE) || defined(DD2) utility::load_module_from_current_directory(L"openvr_api.dll"); utility::load_module_from_current_directory(L"openxr_loader.dll"); LoadLibraryA("dxgi.dll"); @@ -305,6 +305,12 @@ REFramework::REFramework(HMODULE reframework_module) // Fixes new code added in RE4 only. IntegrityCheckBypass::immediate_patch_re4(); #endif + +#if defined(DD2) + // Fixes new code added in DD2 only. Maybe >= TDB73 too. Probably will change. + IntegrityCheckBypass::immediate_patch_dd2(); +#endif + // Seen in SF6 IntegrityCheckBypass::remove_stack_destroyer(); suspender.resume(); diff --git a/src/mods/IntegrityCheckBypass.cpp b/src/mods/IntegrityCheckBypass.cpp index ff51a1ede..34ec26ccd 100644 --- a/src/mods/IntegrityCheckBypass.cpp +++ b/src/mods/IntegrityCheckBypass.cpp @@ -501,6 +501,47 @@ void IntegrityCheckBypass::immediate_patch_re4() { spdlog::info("[IntegrityCheckBypass]: Patched conditional_jmp!"); } +void IntegrityCheckBypass::immediate_patch_dd2() { + // Just like RE4, this deals with the scans that are done every frame on the game's memory. + // The scans are still performed, but the crash will be avoided. + // This time, the obfuscation is much worse, and the way the crash is caused is much more indirect. + // They corrupt something that has something to do with the renderer, + // possibly with how it updates constant buffers and/or pipeline state + // this makes the crash look like it comes from DXGI present, due to a GPU error. + // The place this is happening is very simple, but it was not an easy find due to + // how indirect it was + all the obfuscation. + spdlog::info("[IntegrityCheckBypass]: Scanning DD2..."); + + const auto game = utility::get_executable(); + const auto conditional_jmp_block = utility::scan(game, "41 8B ? ? 78 83 ? 07 ? ? 75 ?"); + + if (conditional_jmp_block) { + // Jnz->Jmp + const auto conditional_jmp = *conditional_jmp_block + 10; + + // Create a patch that always jumps. + static auto dd2patch = Patch::create(conditional_jmp, { 0xEB }, true); + + spdlog::info("[IntegrityCheckBypass]: Patched conditional_jmp! (DD2)"); + } else { + spdlog::error("[IntegrityCheckBypass]: Could not find conditional_jmp for DD2."); + } + + const auto second_conditional_jmp_block = utility::scan(game, "49 3B D0 75 ? ? 8B ? ? ? ? ? ? 8B ? ? ? ? ? ? 8B ? ? 8B ? ? ? ? ?"); + + if (second_conditional_jmp_block) { + // Jnz->Jmp + const auto second_conditional_jmp = *second_conditional_jmp_block + 3; + + // Create a patch that always jumps. + static auto dd2patch2 = Patch::create(second_conditional_jmp, { 0xEB }, true); + + spdlog::info("[IntegrityCheckBypass]: Patched second_conditional_jmp! (DD2)"); + } else { + spdlog::error("[IntegrityCheckBypass]: Could not find second_conditional_jmp for DD2."); + } +} + void IntegrityCheckBypass::remove_stack_destroyer() { spdlog::info("[IntegrityCheckBypass]: Searching for stack destroyer..."); diff --git a/src/mods/IntegrityCheckBypass.hpp b/src/mods/IntegrityCheckBypass.hpp index 760feac6c..c9ac76ec7 100644 --- a/src/mods/IntegrityCheckBypass.hpp +++ b/src/mods/IntegrityCheckBypass.hpp @@ -20,6 +20,7 @@ class IntegrityCheckBypass : public Mod { static void ignore_application_entries(); static void immediate_patch_re8(); static void immediate_patch_re4(); + static void immediate_patch_dd2(); static void remove_stack_destroyer(); static void setup_pristine_syscall();