From 182ebb7b4b76c95547ca214628cf9803fdf450f8 Mon Sep 17 00:00:00 2001 From: ThirteenAG Date: Sat, 21 Oct 2023 19:53:35 +0800 Subject: [PATCH] re2gc softlock fix --- .github/docs/re4.md | 2 + includes/dolphin/dolphin.h | 47 ++++--- .../dllmain.cpp | 130 +++++++++++++++--- 3 files changed, 142 insertions(+), 37 deletions(-) diff --git a/.github/docs/re4.md b/.github/docs/re4.md index de0c24446..7ff6b3f3b 100644 --- a/.github/docs/re4.md +++ b/.github/docs/re4.md @@ -2,6 +2,8 @@ ![](https://habrastorage.org/webt/ow/yy/mg/owyymgpibfqzfbwyf_iqoiqrede.png) Added an option to enable [Logitech G LIGHTSYNC RGB Lighting](https://www.logitechg.com/innovation/lightsync-rgb.html) +https://github.com/ThirteenAG/WidescreenFixesPack/assets/4904157/92ea000b-4646-40d6-9133-05e57e517e18 + Installation: Download and extract the archive to the game directory, where the exe is located. diff --git a/includes/dolphin/dolphin.h b/includes/dolphin/dolphin.h index 6eee2159b..f28d752b6 100644 --- a/includes/dolphin/dolphin.h +++ b/includes/dolphin/dolphin.h @@ -18,7 +18,7 @@ class Dolphin return hook::pattern("0F B6 C8 E8 ? ? ? ? 33 D2"); } - static void SetIsThrottlerTempDisabled(bool disable) + static inline void SetIsThrottlerTempDisabled(bool disable) { if (!_SetIsThrottlerTempDisabled) { @@ -30,33 +30,42 @@ class Dolphin return _SetIsThrottlerTempDisabled(disable); } - static void MenuBarClearCache() + static inline void MenuBarClearCache() { - if (!_MenuBarClearCache) + __try { - auto pattern = hook::pattern("45 33 C9 45 33 C0 33 D2"); - if (!pattern.empty()) + []() { - for (size_t i = 0; i < pattern.size(); i++) + if (!_MenuBarClearCache) { - auto range_pattern = hook::pattern((uintptr_t)pattern.get(i).get(0), (uintptr_t)pattern.get(i).get(200), "45 ? ? ? 8D"); - if (!range_pattern.empty()) + auto pattern = hook::pattern("45 33 C9 45 33 C0 33 D2"); + if (!pattern.empty()) { - auto str = injector::ReadRelativeOffset(range_pattern.get(0).get(6)).get_raw(); - if (MemoryValid(str) && std::string_view(str) == "Clear Cache") + for (size_t i = 0; i < pattern.size(); i++) { - _MenuBarClearCache = (void(__fastcall*)())(injector::ReadRelativeOffset(pattern.get(i).get(22)).as_int()); - break; + auto range_pattern = hook::pattern((uintptr_t)pattern.get(i).get(0), (uintptr_t)pattern.get(i).get(200), "45 ? ? ? 8D"); + if (!range_pattern.empty()) + { + auto str = injector::ReadRelativeOffset(range_pattern.get(0).get(6)).get_raw(); + if (MemoryValid(str) && std::string_view(str) == "Clear Cache") + { + _MenuBarClearCache = (void(__fastcall*)())(injector::ReadRelativeOffset(pattern.get(i).get(22)).as_int()); + break; + } + } } } } - } + else + return _MenuBarClearCache(); + }(); + } + __except ((GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION) ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) + { } - else - return _MenuBarClearCache(); } - static void FindEmulatorMemory() + static inline void FindEmulatorMemory() { while (GameMemoryStart == 0) { @@ -81,7 +90,7 @@ class Dolphin } } - static bool MemoryValid() + static inline bool MemoryValid() { static MEMORY_BASIC_INFORMATION MemoryInf; if (GameMemoryStart == 0 || VirtualQuery((LPCVOID)GameMemoryStart, &MemoryInf, sizeof(MemoryInf)) == 0 || MemoryInf.AllocationProtect != PAGE_READWRITE) @@ -94,7 +103,7 @@ class Dolphin } template - static bool MemoryValid(T addr) + static inline bool MemoryValid(T addr) { static MEMORY_BASIC_INFORMATION MemoryInf; if (addr == 0 || VirtualQuery((LPCVOID)addr, &MemoryInf, sizeof(MemoryInf)) == 0 || MemoryInf.AllocationProtect != PAGE_READWRITE) @@ -102,7 +111,7 @@ class Dolphin return true; } - static std::string_view GameID() + static inline std::string_view GameID() { static auto default_id = ""; if (MemoryValid(GameMemoryStart)) diff --git a/source/ResidentEvil2.Dolphin.FusionMod/dllmain.cpp b/source/ResidentEvil2.Dolphin.FusionMod/dllmain.cpp index d02212b02..d3636999b 100644 --- a/source/ResidentEvil2.Dolphin.FusionMod/dllmain.cpp +++ b/source/ResidentEvil2.Dolphin.FusionMod/dllmain.cpp @@ -1,42 +1,68 @@ #include "stdafx.h" #include #include +#include + +static bool bLogiLedInitialized = false; void Init() { CIniReader iniReader(""); static bool bEnableDoorSkip = iniReader.ReadInteger("MAIN", "EnableDoorSkip", 1) != 0; static bool bUnthrottleEmuDuringDoorSkip = iniReader.ReadInteger("MAIN", "UnthrottleEmuDuringDoorSkip", 1) != 0; + static bool bLightSyncRGB = iniReader.ReadInteger("MAIN", "LightSyncRGB", 1) != 0; - if (!bEnableDoorSkip && !bUnthrottleEmuDuringDoorSkip) + if (!bEnableDoorSkip && !bUnthrottleEmuDuringDoorSkip && !bLightSyncRGB) return; + if (bLightSyncRGB && !bLogiLedInitialized && false) + { + bLogiLedInitialized = LogiLedInit(); + if (bLogiLedInitialized) { + LogiLedStopEffects(); + LEDEffects::SetLighting(52, 0, 0); //logo red + + IATHook::Replace(GetModuleHandleA(NULL), "KERNEL32.DLL", + std::forward_as_tuple("ExitProcessImplementation", static_cast([](UINT uExitCode) { + if (bLogiLedInitialized) { + LogiLedShutdown(); + bLogiLedInitialized = false; + } + ExitProcess(uExitCode); + })) + ); + } + } + std::thread([]() { using namespace powerpc; using namespace std::chrono_literals; + static auto swap16 = [](uint16_t n) -> uint16_t + { + return (n >> 8) | (n << 8); + }; + + static auto convert = [](uint32_t n) -> uint32_t + { + auto ptr = (unsigned char*)&n; + return (ptr[1] << 24) | (ptr[0] << 16) | 0 | 0; + }; + static uint32_t* data = nullptr; + static int16_t* sPlayerHealth = nullptr; while (true) { - std::this_thread::yield(); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); if (Dolphin::MemoryValid()) { if (Dolphin::GameID() == "GHAE08" || Dolphin::GameID() == "GHAP08") { static uint32_t* memcheck = nullptr; static uint32_t bytes = 0; - if (data == nullptr || (memcheck && *memcheck != bytes)) + if (data == nullptr || (Dolphin::MemoryValid(memcheck) && *memcheck != bytes)) { - auto swap16 = [](uint16_t n) -> uint16_t - { - return (n >> 8) | (n << 8); - }; - auto convert = [](uint32_t n) -> uint32_t - { - auto ptr = (unsigned char*)&n; - return (ptr[1] << 24) | (ptr[0] << 16) | 0 | 0; - }; auto pattern = hook::pattern(Dolphin::GameMemoryStart, Dolphin::GameMemoryEnd, "38 a0 00 01 3c 60 ? ? 38 83 ? ? 90 a4 00 00 3c 60"); if (pattern.size() >= 1) { @@ -48,19 +74,29 @@ void Init() if (a != 0 && b != 0) data = (uint32_t*)((convert(a) - int16_t(0 - b) + c) - Dolphin::ImageBase + Dolphin::GameMemoryStart); } - if (bEnableDoorSkip) + + if (bLogiLedInitialized) { - pattern = hook::pattern(Dolphin::GameMemoryStart, Dolphin::GameMemoryEnd, "7f a0 22 14 ? ? ? ? ? ? ? ? 38 00 00 00 ? ? ? ? 38 00 00 00"); + LogiLedStopEffects(); + LEDEffects::SetLighting(52, 0, 0); //logo red + + auto pattern = hook::pattern(Dolphin::GameMemoryStart, Dolphin::GameMemoryEnd, "3c 60 ? ? 38 63 ? ? ? ? ? ? 2c 00 00 00 ? ? ? ? 38 00 ? ? 3c 60 ? ? 38 63 ? ? ? ? ? ? 3c 60 ? ? 38 63 ? ? ? ? ? ? 54 00 02 94"); if (pattern.size() >= 1) { - injector::WriteMemory(pattern.get(0).get(4), li(r0, 10), true); - Dolphin::MenuBarClearCache(); + uint16_t a = swap16(*pattern.get(0).get(2)); + uint16_t b = swap16(*pattern.get(0).get(6)); + uint16_t c = swap16(*pattern.get(0).get(10)); + if (a != 0 && b != 0) + sPlayerHealth = (int16_t*)((convert(a) + b + c) - Dolphin::ImageBase + Dolphin::GameMemoryStart); } + } - pattern = hook::pattern(Dolphin::GameMemoryStart, Dolphin::GameMemoryEnd, "54 7d 04 3e 38 00 00 01 98 1f 00 01 38 00 00 00"); + if (bEnableDoorSkip) + { + auto pattern = hook::pattern(Dolphin::GameMemoryStart, Dolphin::GameMemoryEnd, "28 00 00 00 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 54 00 03 9c 28 00 00 00 ? ? ? ? 38 00 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 48 00 ? ? 48 00"); if (pattern.size() >= 1) { - injector::WriteMemory(pattern.get(0).get(4), li(r0, 0), true); + injector::WriteMemory(pattern.get(0).get(4), 0x0048, true); // bne -> b Dolphin::MenuBarClearCache(); } } @@ -71,12 +107,63 @@ void Init() { Dolphin::SetIsThrottlerTempDisabled(true); } + + if (bLogiLedInitialized) + { + if (Dolphin::MemoryValid(sPlayerHealth)) + { + int16_t health1 = (int16_t)swap16(*sPlayerHealth); + auto poisoned = *(int8_t*)((uintptr_t)sPlayerHealth + 0xC2); + if (health1 > 1) + { + if (health1 <= 20) { + if (!poisoned) + LEDEffects::SetLighting(26, 4, 4, true, false); //red + else + LEDEffects::SetLighting(51, 4, 53, true, false); //purple + LEDEffects::DrawCardiogram(100, 0, 0, 0, 0, 0); //red + } + else if (health1 <= 40) { + if (!poisoned) + LEDEffects::SetLighting(100, 39, 13, true, false); //orange + else + LEDEffects::SetLighting(51, 4, 53, true, false); //purple + LEDEffects::DrawCardiogram(100, 0, 0, 0, 0, 0); //red + } + else if (health1 <= 100) { + if (!poisoned) + LEDEffects::SetLighting(52, 48, 0, true, false); //orange + else + LEDEffects::SetLighting(51, 4, 53, true, false); //purple + LEDEffects::DrawCardiogram(67, 0, 0, 0, 0, 0); //orange + } + else { + if (!poisoned) + LEDEffects::SetLighting(0, 48, 0, true, false); //green + else + LEDEffects::SetLighting(51, 4, 53, true, false); //purple + LEDEffects::DrawCardiogram(0, 100, 0, 0, 0, 0); //green + } + } + else + { + LEDEffects::SetLighting(26, 4, 4, false); //red + LEDEffects::DrawCardiogram(100, 0, 0, 0, 0, 0); + } + } + else + { + LogiLedStopEffects(); + LEDEffects::SetLighting(52, 0, 0); //logo red + } + } } } } else { data = nullptr; + sPlayerHealth = nullptr; } } } @@ -97,5 +184,12 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD reason, LPVOID lpReserved) { if (!IsUALPresent()) { InitializeASI(); } } + else if (reason == DLL_PROCESS_DETACH) + { + if (bLogiLedInitialized) { + LogiLedShutdown(); + bLogiLedInitialized = false; + } + } return TRUE; }