From 30f9675b540a0d3a8edafcf3c8fbd0486e4385ee Mon Sep 17 00:00:00 2001 From: Kamil Marciniak Date: Sun, 10 Nov 2024 01:02:52 +0100 Subject: [PATCH 01/13] Fix some small problems with Device Selection Dialog - Show the dialog in task bar - Show the icon on dialog - Display actual monitor names instead of GPU name --- Client/multiplayer_sa/CMultiplayerSA.cpp | 1 + Client/multiplayer_sa/CMultiplayerSA.h | 1 + .../CMultiplayerSA_DeviceSelection.cpp | 157 ++++++++++++++++++ 3 files changed, 159 insertions(+) create mode 100644 Client/multiplayer_sa/CMultiplayerSA_DeviceSelection.cpp diff --git a/Client/multiplayer_sa/CMultiplayerSA.cpp b/Client/multiplayer_sa/CMultiplayerSA.cpp index 1b21f79a238..cf16ef7e46b 100644 --- a/Client/multiplayer_sa/CMultiplayerSA.cpp +++ b/Client/multiplayer_sa/CMultiplayerSA.cpp @@ -1574,6 +1574,7 @@ void CMultiplayerSA::InitHooks() MemSet((void*)0x6C4453, 0x90, 0x68); InitHooks_CrashFixHacks(); + InitHooks_DeviceSelection(); // Init our 1.3 hooks. Init_13(); diff --git a/Client/multiplayer_sa/CMultiplayerSA.h b/Client/multiplayer_sa/CMultiplayerSA.h index 802b9b56eac..d97300e6a12 100644 --- a/Client/multiplayer_sa/CMultiplayerSA.h +++ b/Client/multiplayer_sa/CMultiplayerSA.h @@ -80,6 +80,7 @@ class CMultiplayerSA : public CMultiplayer void InitHooks_ProjectileCollisionFix(); void InitHooks_ObjectStreamerOptimization(); void InitHooks_Postprocess(); + void InitHooks_DeviceSelection(); CRemoteDataStorage* CreateRemoteDataStorage(); void DestroyRemoteDataStorage(CRemoteDataStorage* pData); void AddRemoteDataStorage(CPlayerPed* pPed, CRemoteDataStorage* pData); diff --git a/Client/multiplayer_sa/CMultiplayerSA_DeviceSelection.cpp b/Client/multiplayer_sa/CMultiplayerSA_DeviceSelection.cpp new file mode 100644 index 00000000000..58f232d3323 --- /dev/null +++ b/Client/multiplayer_sa/CMultiplayerSA_DeviceSelection.cpp @@ -0,0 +1,157 @@ +/***************************************************************************** + * + * PROJECT: Multi Theft Auto v1.0 + * LICENSE: See LICENSE in the top level directory + * FILE: multiplayer_sa/CMultiplayerSA_Weapons.cpp + * + * Multi Theft Auto is available from http://www.multitheftauto.com/ + * + *****************************************************************************/ + +#include "StdInc.h" + +#ifdef _WIN32 + #ifndef NOMINMAX + #define NOMINMAX + #endif +#endif + +// This is copied from SilentPatch: +// https://github.com/CookiePLMonster/SilentPatch/blob/dev/SilentPatch/FriendlyMonitorNames.cpp +std::map> GetFriendlyMonitorNamesForDevicePaths() +{ + std::map> monitorNames; + +#if WINVER < _WIN32_WINNT_WIN7 + return monitorNames; +#else + HMODULE user32Lib = LoadLibrary(TEXT("user32")); + if (user32Lib != nullptr) + { + auto getDisplayConfigBufferSizes = (decltype(GetDisplayConfigBufferSizes)*)GetProcAddress(user32Lib, "GetDisplayConfigBufferSizes"); + auto queryDisplayConfig = (decltype(QueryDisplayConfig)*)GetProcAddress(user32Lib, "QueryDisplayConfig"); + auto displayConfigGetDeviceInfo = (decltype(DisplayConfigGetDeviceInfo)*)GetProcAddress(user32Lib, "DisplayConfigGetDeviceInfo"); + if (getDisplayConfigBufferSizes != nullptr && queryDisplayConfig != nullptr && displayConfigGetDeviceInfo != nullptr) + { + UINT32 pathCount, modeCount; + std::unique_ptr paths; + std::unique_ptr modes; + + LONG result = ERROR_SUCCESS; + do + { + result = getDisplayConfigBufferSizes(QDC_ONLY_ACTIVE_PATHS, &pathCount, &modeCount); + if (result != ERROR_SUCCESS) + { + break; + } + paths = std::make_unique(pathCount); + modes = std::make_unique(modeCount); + result = queryDisplayConfig(QDC_ONLY_ACTIVE_PATHS, &pathCount, paths.get(), &modeCount, modes.get(), nullptr); + } while (result == ERROR_INSUFFICIENT_BUFFER); + + if (result == ERROR_SUCCESS) + { + for (size_t i = 0; i < pathCount; i++) + { + DISPLAYCONFIG_TARGET_DEVICE_NAME targetName = {}; + targetName.header.adapterId = paths[i].targetInfo.adapterId; + targetName.header.id = paths[i].targetInfo.id; + targetName.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME; + targetName.header.size = sizeof(targetName); + const LONG targetNameResult = DisplayConfigGetDeviceInfo(&targetName.header); + + DISPLAYCONFIG_SOURCE_DEVICE_NAME sourceName = {}; + sourceName.header.adapterId = paths[i].sourceInfo.adapterId; + sourceName.header.id = paths[i].sourceInfo.id; + sourceName.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME; + sourceName.header.size = sizeof(sourceName); + const LONG sourceNameResult = DisplayConfigGetDeviceInfo(&sourceName.header); + if (targetNameResult == ERROR_SUCCESS && sourceNameResult == ERROR_SUCCESS && targetName.monitorFriendlyDeviceName[0] != '\0') + { + char gdiDeviceName[std::size(sourceName.viewGdiDeviceName)]; + char monitorFriendlyDeviceName[std::size(targetName.monitorFriendlyDeviceName)]; + WideCharToMultiByte(CP_ACP, 0, sourceName.viewGdiDeviceName, -1, gdiDeviceName, static_cast(std::size(gdiDeviceName)), nullptr, + nullptr); + WideCharToMultiByte(CP_ACP, 0, targetName.monitorFriendlyDeviceName, -1, monitorFriendlyDeviceName, + static_cast(std::size(monitorFriendlyDeviceName)), nullptr, nullptr); + + monitorNames.try_emplace(gdiDeviceName, monitorFriendlyDeviceName); + } + } + } + } + FreeLibrary(user32Lib); + } + + return monitorNames; +#endif +} + +struct RwSubSystemInfo +{ + char name[80]; +}; + +#define FUNC_rwDeviceSystemRequest 0x7F2AB0 +using rwDeviceSystemRequest = RwSubSystemInfo*(__cdecl*)(void* device, uint32_t requestId, RwSubSystemInfo* pOut, void* pInOut, uint32_t numIn); +static RwSubSystemInfo* RwEngineGetSubSystemInfo_Hooked(RwSubSystemInfo* subSystemInfo, int32_t subSystemIndex) +{ + static auto rwDeviceSystemRequestFunc = (rwDeviceSystemRequest)(FUNC_rwDeviceSystemRequest); + auto devicePointer = *(uint32_t*)(0xC97B24); + auto result = rwDeviceSystemRequestFunc((void*)(devicePointer + 0x10), 14, subSystemInfo, nullptr, subSystemIndex); + if (result == nullptr) + return nullptr; + + auto pDxDevice = *(IDirect3D9**)0xC97C20; + if (pDxDevice == nullptr) + return subSystemInfo; + + D3DADAPTER_IDENTIFIER9 identifier; + if (FAILED(pDxDevice->GetAdapterIdentifier(subSystemIndex, 0, &identifier))) + return subSystemInfo; + + static const auto friendlyNames = GetFriendlyMonitorNamesForDevicePaths(); + + // If we can't find the friendly name, either because it doesn't exist or we're on an ancient Windows, fall back to the device name + auto it = friendlyNames.find(identifier.DeviceName); + if (it != friendlyNames.end()) + { + strncpy_s(subSystemInfo->name, it->second.c_str(), _TRUNCATE); + } + else + { + strncpy_s(subSystemInfo->name, identifier.Description, _TRUNCATE); + } + + return subSystemInfo; +} + +#define FUNC_DialogFunc 0x745E50 +static INT_PTR CALLBACK CustomDlgProc(HWND window, UINT msg, WPARAM wParam, LPARAM lParam) +{ + auto orgDialogFunc = (DLGPROC)FUNC_DialogFunc; + if (msg == WM_INITDIALOG) + { + orgDialogFunc(window, msg, wParam, lParam); + + // Set Icon + HMODULE hGameModule = GetModuleHandle(nullptr); + SendMessage(window, WM_SETICON, ICON_SMALL, reinterpret_cast(LoadIcon(hGameModule, MAKEINTRESOURCE(100)))); + + // Make the dialog visible in the task bar + // https://stackoverflow.com/a/1462811 + SetWindowLongPtr(window, GWL_EXSTYLE, WS_EX_APPWINDOW); + ShowWindow(window, SW_HIDE); + ShowWindow(window, SW_SHOW); + return FALSE; + } + + return orgDialogFunc(window, msg, wParam, lParam); +} + +void CMultiplayerSA::InitHooks_DeviceSelection() +{ + MemPut(0x746239, (DLGPROC)&CustomDlgProc); + HookInstall(0x7F2C30, (DWORD)RwEngineGetSubSystemInfo_Hooked, 6); +} From 8bc44272d2735194d793e3266906b236ecd32832 Mon Sep 17 00:00:00 2001 From: Kamil Marciniak Date: Sun, 10 Nov 2024 01:14:54 +0100 Subject: [PATCH 02/13] Fix file comment --- Client/multiplayer_sa/CMultiplayerSA_DeviceSelection.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Client/multiplayer_sa/CMultiplayerSA_DeviceSelection.cpp b/Client/multiplayer_sa/CMultiplayerSA_DeviceSelection.cpp index 58f232d3323..583b4ce3ed9 100644 --- a/Client/multiplayer_sa/CMultiplayerSA_DeviceSelection.cpp +++ b/Client/multiplayer_sa/CMultiplayerSA_DeviceSelection.cpp @@ -2,7 +2,7 @@ * * PROJECT: Multi Theft Auto v1.0 * LICENSE: See LICENSE in the top level directory - * FILE: multiplayer_sa/CMultiplayerSA_Weapons.cpp + * FILE: multiplayer_sa/CMultiplayerSA_DeviceSelection.cpp * * Multi Theft Auto is available from http://www.multitheftauto.com/ * From 0d66ab4220f7c4994073297d47796ff0523c097e Mon Sep 17 00:00:00 2001 From: Kamil Marciniak Date: Sun, 10 Nov 2024 16:26:07 +0100 Subject: [PATCH 03/13] Remove NOMINMAX directive --- Client/multiplayer_sa/CMultiplayerSA_DeviceSelection.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/Client/multiplayer_sa/CMultiplayerSA_DeviceSelection.cpp b/Client/multiplayer_sa/CMultiplayerSA_DeviceSelection.cpp index 583b4ce3ed9..9355e9b581d 100644 --- a/Client/multiplayer_sa/CMultiplayerSA_DeviceSelection.cpp +++ b/Client/multiplayer_sa/CMultiplayerSA_DeviceSelection.cpp @@ -10,12 +10,6 @@ #include "StdInc.h" -#ifdef _WIN32 - #ifndef NOMINMAX - #define NOMINMAX - #endif -#endif - // This is copied from SilentPatch: // https://github.com/CookiePLMonster/SilentPatch/blob/dev/SilentPatch/FriendlyMonitorNames.cpp std::map> GetFriendlyMonitorNamesForDevicePaths() From ca847bba952d61e185b627627f1121b734cd20e0 Mon Sep 17 00:00:00 2001 From: Kamil Marciniak Date: Sun, 10 Nov 2024 16:33:09 +0100 Subject: [PATCH 04/13] Early outs --- .../CMultiplayerSA_DeviceSelection.cpp | 139 +++++++++--------- 1 file changed, 71 insertions(+), 68 deletions(-) diff --git a/Client/multiplayer_sa/CMultiplayerSA_DeviceSelection.cpp b/Client/multiplayer_sa/CMultiplayerSA_DeviceSelection.cpp index 9355e9b581d..ae4b0805935 100644 --- a/Client/multiplayer_sa/CMultiplayerSA_DeviceSelection.cpp +++ b/Client/multiplayer_sa/CMultiplayerSA_DeviceSelection.cpp @@ -20,64 +20,69 @@ std::map> GetFriendlyMonitorNamesForDevice return monitorNames; #else HMODULE user32Lib = LoadLibrary(TEXT("user32")); - if (user32Lib != nullptr) + if (!user32Lib) + return monitorNames; + + auto getDisplayConfigBufferSizes = (decltype(GetDisplayConfigBufferSizes)*)GetProcAddress(user32Lib, "GetDisplayConfigBufferSizes"); + auto queryDisplayConfig = (decltype(QueryDisplayConfig)*)GetProcAddress(user32Lib, "QueryDisplayConfig"); + auto displayConfigGetDeviceInfo = (decltype(DisplayConfigGetDeviceInfo)*)GetProcAddress(user32Lib, "DisplayConfigGetDeviceInfo"); + if (!getDisplayConfigBufferSizes || !queryDisplayConfig || !displayConfigGetDeviceInfo) { - auto getDisplayConfigBufferSizes = (decltype(GetDisplayConfigBufferSizes)*)GetProcAddress(user32Lib, "GetDisplayConfigBufferSizes"); - auto queryDisplayConfig = (decltype(QueryDisplayConfig)*)GetProcAddress(user32Lib, "QueryDisplayConfig"); - auto displayConfigGetDeviceInfo = (decltype(DisplayConfigGetDeviceInfo)*)GetProcAddress(user32Lib, "DisplayConfigGetDeviceInfo"); - if (getDisplayConfigBufferSizes != nullptr && queryDisplayConfig != nullptr && displayConfigGetDeviceInfo != nullptr) + FreeLibrary(user32Lib); + return monitorNames; + } + + UINT32 pathCount, modeCount; + std::unique_ptr paths; + std::unique_ptr modes; + + LONG result = ERROR_SUCCESS; + do + { + result = getDisplayConfigBufferSizes(QDC_ONLY_ACTIVE_PATHS, &pathCount, &modeCount); + if (result != ERROR_SUCCESS) { - UINT32 pathCount, modeCount; - std::unique_ptr paths; - std::unique_ptr modes; - - LONG result = ERROR_SUCCESS; - do - { - result = getDisplayConfigBufferSizes(QDC_ONLY_ACTIVE_PATHS, &pathCount, &modeCount); - if (result != ERROR_SUCCESS) - { - break; - } - paths = std::make_unique(pathCount); - modes = std::make_unique(modeCount); - result = queryDisplayConfig(QDC_ONLY_ACTIVE_PATHS, &pathCount, paths.get(), &modeCount, modes.get(), nullptr); - } while (result == ERROR_INSUFFICIENT_BUFFER); - - if (result == ERROR_SUCCESS) - { - for (size_t i = 0; i < pathCount; i++) - { - DISPLAYCONFIG_TARGET_DEVICE_NAME targetName = {}; - targetName.header.adapterId = paths[i].targetInfo.adapterId; - targetName.header.id = paths[i].targetInfo.id; - targetName.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME; - targetName.header.size = sizeof(targetName); - const LONG targetNameResult = DisplayConfigGetDeviceInfo(&targetName.header); - - DISPLAYCONFIG_SOURCE_DEVICE_NAME sourceName = {}; - sourceName.header.adapterId = paths[i].sourceInfo.adapterId; - sourceName.header.id = paths[i].sourceInfo.id; - sourceName.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME; - sourceName.header.size = sizeof(sourceName); - const LONG sourceNameResult = DisplayConfigGetDeviceInfo(&sourceName.header); - if (targetNameResult == ERROR_SUCCESS && sourceNameResult == ERROR_SUCCESS && targetName.monitorFriendlyDeviceName[0] != '\0') - { - char gdiDeviceName[std::size(sourceName.viewGdiDeviceName)]; - char monitorFriendlyDeviceName[std::size(targetName.monitorFriendlyDeviceName)]; - WideCharToMultiByte(CP_ACP, 0, sourceName.viewGdiDeviceName, -1, gdiDeviceName, static_cast(std::size(gdiDeviceName)), nullptr, - nullptr); - WideCharToMultiByte(CP_ACP, 0, targetName.monitorFriendlyDeviceName, -1, monitorFriendlyDeviceName, - static_cast(std::size(monitorFriendlyDeviceName)), nullptr, nullptr); - - monitorNames.try_emplace(gdiDeviceName, monitorFriendlyDeviceName); - } - } - } + break; } + paths = std::make_unique(pathCount); + modes = std::make_unique(modeCount); + result = queryDisplayConfig(QDC_ONLY_ACTIVE_PATHS, &pathCount, paths.get(), &modeCount, modes.get(), nullptr); + } while (result == ERROR_INSUFFICIENT_BUFFER); + + if (result != ERROR_SUCCESS) + { FreeLibrary(user32Lib); + return monitorNames; + } + + for (size_t i = 0; i < pathCount; i++) + { + DISPLAYCONFIG_TARGET_DEVICE_NAME targetName = {}; + targetName.header.adapterId = paths[i].targetInfo.adapterId; + targetName.header.id = paths[i].targetInfo.id; + targetName.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME; + targetName.header.size = sizeof(targetName); + const LONG targetNameResult = DisplayConfigGetDeviceInfo(&targetName.header); + + DISPLAYCONFIG_SOURCE_DEVICE_NAME sourceName = {}; + sourceName.header.adapterId = paths[i].sourceInfo.adapterId; + sourceName.header.id = paths[i].sourceInfo.id; + sourceName.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME; + sourceName.header.size = sizeof(sourceName); + const LONG sourceNameResult = DisplayConfigGetDeviceInfo(&sourceName.header); + if (targetNameResult == ERROR_SUCCESS && sourceNameResult == ERROR_SUCCESS && targetName.monitorFriendlyDeviceName[0] != '\0') + { + char gdiDeviceName[std::size(sourceName.viewGdiDeviceName)]; + char monitorFriendlyDeviceName[std::size(targetName.monitorFriendlyDeviceName)]; + WideCharToMultiByte(CP_ACP, 0, sourceName.viewGdiDeviceName, -1, gdiDeviceName, static_cast(std::size(gdiDeviceName)), nullptr, nullptr); + WideCharToMultiByte(CP_ACP, 0, targetName.monitorFriendlyDeviceName, -1, monitorFriendlyDeviceName, + static_cast(std::size(monitorFriendlyDeviceName)), nullptr, nullptr); + + monitorNames.try_emplace(gdiDeviceName, monitorFriendlyDeviceName); + } } + FreeLibrary(user32Lib); return monitorNames; #endif } @@ -125,23 +130,21 @@ static RwSubSystemInfo* RwEngineGetSubSystemInfo_Hooked(RwSubSystemInfo* subSyst static INT_PTR CALLBACK CustomDlgProc(HWND window, UINT msg, WPARAM wParam, LPARAM lParam) { auto orgDialogFunc = (DLGPROC)FUNC_DialogFunc; - if (msg == WM_INITDIALOG) - { - orgDialogFunc(window, msg, wParam, lParam); - - // Set Icon - HMODULE hGameModule = GetModuleHandle(nullptr); - SendMessage(window, WM_SETICON, ICON_SMALL, reinterpret_cast(LoadIcon(hGameModule, MAKEINTRESOURCE(100)))); - - // Make the dialog visible in the task bar - // https://stackoverflow.com/a/1462811 - SetWindowLongPtr(window, GWL_EXSTYLE, WS_EX_APPWINDOW); - ShowWindow(window, SW_HIDE); - ShowWindow(window, SW_SHOW); - return FALSE; - } + if (msg != WM_INITDIALOG) + return orgDialogFunc(window, msg, wParam, lParam); + + orgDialogFunc(window, msg, wParam, lParam); + + // Set Icon + HMODULE hGameModule = GetModuleHandle(nullptr); + SendMessage(window, WM_SETICON, ICON_SMALL, reinterpret_cast(LoadIcon(hGameModule, MAKEINTRESOURCE(100)))); - return orgDialogFunc(window, msg, wParam, lParam); + // Make the dialog visible in the task bar + // https://stackoverflow.com/a/1462811 + SetWindowLongPtr(window, GWL_EXSTYLE, WS_EX_APPWINDOW); + ShowWindow(window, SW_HIDE); + ShowWindow(window, SW_SHOW); + return FALSE; } void CMultiplayerSA::InitHooks_DeviceSelection() From 83b210d612bfa89d342f23b0e7f2a9080c92b36d Mon Sep 17 00:00:00 2001 From: Kamil Marciniak Date: Sun, 10 Nov 2024 17:02:57 +0100 Subject: [PATCH 05/13] RwGlobals and RwDevice stup in Renderware.h --- .../CMultiplayerSA_DeviceSelection.cpp | 12 ++--- Client/sdk/game/RenderWare.h | 46 +++++++++++++++++++ 2 files changed, 52 insertions(+), 6 deletions(-) diff --git a/Client/multiplayer_sa/CMultiplayerSA_DeviceSelection.cpp b/Client/multiplayer_sa/CMultiplayerSA_DeviceSelection.cpp index ae4b0805935..5bfdb52184e 100644 --- a/Client/multiplayer_sa/CMultiplayerSA_DeviceSelection.cpp +++ b/Client/multiplayer_sa/CMultiplayerSA_DeviceSelection.cpp @@ -93,17 +93,17 @@ struct RwSubSystemInfo }; #define FUNC_rwDeviceSystemRequest 0x7F2AB0 -using rwDeviceSystemRequest = RwSubSystemInfo*(__cdecl*)(void* device, uint32_t requestId, RwSubSystemInfo* pOut, void* pInOut, uint32_t numIn); +using rwDeviceSystemRequest = RwSubSystemInfo*(__cdecl*)(RwDevice* device, std::int32_t requestId, RwSubSystemInfo* pOut, void* pInOut, std::int32_t numIn); static RwSubSystemInfo* RwEngineGetSubSystemInfo_Hooked(RwSubSystemInfo* subSystemInfo, int32_t subSystemIndex) { - static auto rwDeviceSystemRequestFunc = (rwDeviceSystemRequest)(FUNC_rwDeviceSystemRequest); - auto devicePointer = *(uint32_t*)(0xC97B24); - auto result = rwDeviceSystemRequestFunc((void*)(devicePointer + 0x10), 14, subSystemInfo, nullptr, subSystemIndex); - if (result == nullptr) + auto rwGlobals = *(RwGlobals**)(0xC97B24); + auto rwDeviceSystemRequestFunc = (rwDeviceSystemRequest)(FUNC_rwDeviceSystemRequest); + auto result = rwDeviceSystemRequestFunc(&rwGlobals->dOpenDevice, 14, subSystemInfo, nullptr, subSystemIndex); + if (!result) return nullptr; auto pDxDevice = *(IDirect3D9**)0xC97C20; - if (pDxDevice == nullptr) + if (!pDxDevice) return subSystemInfo; D3DADAPTER_IDENTIFIER9 identifier; diff --git a/Client/sdk/game/RenderWare.h b/Client/sdk/game/RenderWare.h index 20249e01fd0..a1004d8bc50 100644 --- a/Client/sdk/game/RenderWare.h +++ b/Client/sdk/game/RenderWare.h @@ -526,3 +526,49 @@ struct RwError { int err1, err2; }; + +/*****************************************************************************/ +/** RenderWare Globals **/ +/*****************************************************************************/ + +typedef bool (*RwSystemFunc)(std::int32_t, void*, void*, std::int32_t); +struct RwDevice +{ + float gammaCorrection; + RwSystemFunc fpSystem; + float zBufferNear; + float zBufferFar; + // RwRenderStateSetFunction fpRenderStateSet; + // RwRenderStateGetFunction fpRenderStateGet; + // RwIm2DRenderLineFunction fpIm2DRenderLine; + // RwIm2DRenderTriangleFunction fpIm2DRenderTriangle; + // RwIm2DRenderPrimitiveFunction fpIm2DRenderPrimitive; + // RwIm2DRenderIndexedPrimitiveFunction fpIm2DRenderIndexedPrimitive; + // RwIm3DRenderLineFunction fpIm3DRenderLine; + // RwIm3DRenderTriangleFunction fpIm3DRenderTriangle; + // RwIm3DRenderPrimitiveFunction fpIm3DRenderPrimitive; + // RwIm3DRenderIndexedPrimitiveFunction fpIm3DRenderIndexedPrimitive; +}; +// static_assert(sizeof(RwDevice) == 0x38, "Incorrect class size: RwGlobals"); + +typedef bool (*RwStandardFunc)(void*, void*, std::int32_t); +struct RwGlobals +{ + void* curCamera; + void* curWorld; + std::uint16_t renderFrame; + std::uint16_t lightFrame; + std::uint16_t pad[2]; + RwDevice dOpenDevice; + RwStandardFunc stdFunc[29]; + // RwLinkList dirtyFrameList; + // RwFileFunctions fileFuncs; + // RwStringFunctions stringFuncs; + // RwMemoryFunctions memoryFuncs; + // RwMemoryAllocFn memoryAlloc; + // RwMemoryFreeFn memoryFree; + // RwMetrics* metrics; + // RwEngineStatus engineStatus; + // RwUInt32 resArenaInitSize; +}; +//static_assert(sizeof(RwGlobals) == 0x158, "Incorrect class size: RwGlobals"); From 148aef6af3e8afd1291eaa9defc72a5e0a2ee38b Mon Sep 17 00:00:00 2001 From: Kamil Marciniak Date: Sun, 10 Nov 2024 17:06:07 +0100 Subject: [PATCH 06/13] Pointles static removal, clarification of some addresses --- .../multiplayer_sa/CMultiplayerSA_DeviceSelection.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/Client/multiplayer_sa/CMultiplayerSA_DeviceSelection.cpp b/Client/multiplayer_sa/CMultiplayerSA_DeviceSelection.cpp index 5bfdb52184e..aa70de4f8c3 100644 --- a/Client/multiplayer_sa/CMultiplayerSA_DeviceSelection.cpp +++ b/Client/multiplayer_sa/CMultiplayerSA_DeviceSelection.cpp @@ -96,9 +96,9 @@ struct RwSubSystemInfo using rwDeviceSystemRequest = RwSubSystemInfo*(__cdecl*)(RwDevice* device, std::int32_t requestId, RwSubSystemInfo* pOut, void* pInOut, std::int32_t numIn); static RwSubSystemInfo* RwEngineGetSubSystemInfo_Hooked(RwSubSystemInfo* subSystemInfo, int32_t subSystemIndex) { - auto rwGlobals = *(RwGlobals**)(0xC97B24); + auto rwGlobals = *(RwGlobals**)(0xC97B24); auto rwDeviceSystemRequestFunc = (rwDeviceSystemRequest)(FUNC_rwDeviceSystemRequest); - auto result = rwDeviceSystemRequestFunc(&rwGlobals->dOpenDevice, 14, subSystemInfo, nullptr, subSystemIndex); + auto result = rwDeviceSystemRequestFunc(&rwGlobals->dOpenDevice, 14, subSystemInfo, nullptr, subSystemIndex); if (!result) return nullptr; @@ -127,7 +127,7 @@ static RwSubSystemInfo* RwEngineGetSubSystemInfo_Hooked(RwSubSystemInfo* subSyst } #define FUNC_DialogFunc 0x745E50 -static INT_PTR CALLBACK CustomDlgProc(HWND window, UINT msg, WPARAM wParam, LPARAM lParam) +INT_PTR CALLBACK CustomDlgProc(HWND window, UINT msg, WPARAM wParam, LPARAM lParam) { auto orgDialogFunc = (DLGPROC)FUNC_DialogFunc; if (msg != WM_INITDIALOG) @@ -147,8 +147,11 @@ static INT_PTR CALLBACK CustomDlgProc(HWND window, UINT msg, WPARAM wParam, LPAR return FALSE; } +#define FUNC_RwEngineGetSubSystemInfo 0x7F2C30 void CMultiplayerSA::InitHooks_DeviceSelection() { + // 0x746239 -> Exact address where the original DialogFunc address is being pushed as an argument to DialogBoxParamA(), + // we're replacing it with out own proxy function MemPut(0x746239, (DLGPROC)&CustomDlgProc); - HookInstall(0x7F2C30, (DWORD)RwEngineGetSubSystemInfo_Hooked, 6); + HookInstall(FUNC_RwEngineGetSubSystemInfo, (DWORD)RwEngineGetSubSystemInfo_Hooked, 6); } From 406f74c7e9eed508eda5779f46f557c02d6b5311 Mon Sep 17 00:00:00 2001 From: Kamil Marciniak Date: Sun, 10 Nov 2024 17:10:51 +0100 Subject: [PATCH 07/13] added missing std:: --- Client/multiplayer_sa/CMultiplayerSA_DeviceSelection.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Client/multiplayer_sa/CMultiplayerSA_DeviceSelection.cpp b/Client/multiplayer_sa/CMultiplayerSA_DeviceSelection.cpp index aa70de4f8c3..09eafaf897e 100644 --- a/Client/multiplayer_sa/CMultiplayerSA_DeviceSelection.cpp +++ b/Client/multiplayer_sa/CMultiplayerSA_DeviceSelection.cpp @@ -94,7 +94,7 @@ struct RwSubSystemInfo #define FUNC_rwDeviceSystemRequest 0x7F2AB0 using rwDeviceSystemRequest = RwSubSystemInfo*(__cdecl*)(RwDevice* device, std::int32_t requestId, RwSubSystemInfo* pOut, void* pInOut, std::int32_t numIn); -static RwSubSystemInfo* RwEngineGetSubSystemInfo_Hooked(RwSubSystemInfo* subSystemInfo, int32_t subSystemIndex) +static RwSubSystemInfo* RwEngineGetSubSystemInfo_Hooked(RwSubSystemInfo* subSystemInfo, std::int32_t subSystemIndex) { auto rwGlobals = *(RwGlobals**)(0xC97B24); auto rwDeviceSystemRequestFunc = (rwDeviceSystemRequest)(FUNC_rwDeviceSystemRequest); From 40b475249c25a08f4962872a651daedf9ca36969 Mon Sep 17 00:00:00 2001 From: Kamil Marciniak Date: Sun, 10 Nov 2024 17:12:05 +0100 Subject: [PATCH 08/13] Fixed incorrect comment --- Client/sdk/game/RenderWare.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Client/sdk/game/RenderWare.h b/Client/sdk/game/RenderWare.h index a1004d8bc50..d85011b2913 100644 --- a/Client/sdk/game/RenderWare.h +++ b/Client/sdk/game/RenderWare.h @@ -549,7 +549,7 @@ struct RwDevice // RwIm3DRenderPrimitiveFunction fpIm3DRenderPrimitive; // RwIm3DRenderIndexedPrimitiveFunction fpIm3DRenderIndexedPrimitive; }; -// static_assert(sizeof(RwDevice) == 0x38, "Incorrect class size: RwGlobals"); +// static_assert(sizeof(RwDevice) == 0x38, "Incorrect class size: RwDevice"); typedef bool (*RwStandardFunc)(void*, void*, std::int32_t); struct RwGlobals From c621fc814b937c914739fe1f2e2d9813c9feedfa Mon Sep 17 00:00:00 2001 From: Kamil Marciniak Date: Sun, 10 Nov 2024 20:13:30 +0100 Subject: [PATCH 09/13] Remove windows 7 safety checks --- Client/multiplayer_sa/CMultiplayerSA_DeviceSelection.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Client/multiplayer_sa/CMultiplayerSA_DeviceSelection.cpp b/Client/multiplayer_sa/CMultiplayerSA_DeviceSelection.cpp index 09eafaf897e..f0e1678bc91 100644 --- a/Client/multiplayer_sa/CMultiplayerSA_DeviceSelection.cpp +++ b/Client/multiplayer_sa/CMultiplayerSA_DeviceSelection.cpp @@ -16,9 +16,6 @@ std::map> GetFriendlyMonitorNamesForDevice { std::map> monitorNames; -#if WINVER < _WIN32_WINNT_WIN7 - return monitorNames; -#else HMODULE user32Lib = LoadLibrary(TEXT("user32")); if (!user32Lib) return monitorNames; @@ -84,7 +81,6 @@ std::map> GetFriendlyMonitorNamesForDevice FreeLibrary(user32Lib); return monitorNames; -#endif } struct RwSubSystemInfo From 486aa596ad9c58b0534175074958e967d7572d19 Mon Sep 17 00:00:00 2001 From: Kamil Marciniak Date: Sun, 10 Nov 2024 20:14:35 +0100 Subject: [PATCH 10/13] Instant return from function if possible --- Client/multiplayer_sa/CMultiplayerSA_DeviceSelection.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Client/multiplayer_sa/CMultiplayerSA_DeviceSelection.cpp b/Client/multiplayer_sa/CMultiplayerSA_DeviceSelection.cpp index f0e1678bc91..e5e6ff68e1c 100644 --- a/Client/multiplayer_sa/CMultiplayerSA_DeviceSelection.cpp +++ b/Client/multiplayer_sa/CMultiplayerSA_DeviceSelection.cpp @@ -94,8 +94,7 @@ static RwSubSystemInfo* RwEngineGetSubSystemInfo_Hooked(RwSubSystemInfo* subSyst { auto rwGlobals = *(RwGlobals**)(0xC97B24); auto rwDeviceSystemRequestFunc = (rwDeviceSystemRequest)(FUNC_rwDeviceSystemRequest); - auto result = rwDeviceSystemRequestFunc(&rwGlobals->dOpenDevice, 14, subSystemInfo, nullptr, subSystemIndex); - if (!result) + if (!rwDeviceSystemRequestFunc(&rwGlobals->dOpenDevice, 14, subSystemInfo, nullptr, subSystemIndex)) return nullptr; auto pDxDevice = *(IDirect3D9**)0xC97C20; From cc90226f60b6216fceb47b98e561e0aa959011ca Mon Sep 17 00:00:00 2001 From: Kamil Marciniak Date: Sun, 10 Nov 2024 20:16:16 +0100 Subject: [PATCH 11/13] use auto* for pointers --- .../CMultiplayerSA_DeviceSelection.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Client/multiplayer_sa/CMultiplayerSA_DeviceSelection.cpp b/Client/multiplayer_sa/CMultiplayerSA_DeviceSelection.cpp index e5e6ff68e1c..09675de8d20 100644 --- a/Client/multiplayer_sa/CMultiplayerSA_DeviceSelection.cpp +++ b/Client/multiplayer_sa/CMultiplayerSA_DeviceSelection.cpp @@ -20,9 +20,9 @@ std::map> GetFriendlyMonitorNamesForDevice if (!user32Lib) return monitorNames; - auto getDisplayConfigBufferSizes = (decltype(GetDisplayConfigBufferSizes)*)GetProcAddress(user32Lib, "GetDisplayConfigBufferSizes"); - auto queryDisplayConfig = (decltype(QueryDisplayConfig)*)GetProcAddress(user32Lib, "QueryDisplayConfig"); - auto displayConfigGetDeviceInfo = (decltype(DisplayConfigGetDeviceInfo)*)GetProcAddress(user32Lib, "DisplayConfigGetDeviceInfo"); + auto* getDisplayConfigBufferSizes = (decltype(GetDisplayConfigBufferSizes)*)GetProcAddress(user32Lib, "GetDisplayConfigBufferSizes"); + auto* queryDisplayConfig = (decltype(QueryDisplayConfig)*)GetProcAddress(user32Lib, "QueryDisplayConfig"); + auto* displayConfigGetDeviceInfo = (decltype(DisplayConfigGetDeviceInfo)*)GetProcAddress(user32Lib, "DisplayConfigGetDeviceInfo"); if (!getDisplayConfigBufferSizes || !queryDisplayConfig || !displayConfigGetDeviceInfo) { FreeLibrary(user32Lib); @@ -92,12 +92,12 @@ struct RwSubSystemInfo using rwDeviceSystemRequest = RwSubSystemInfo*(__cdecl*)(RwDevice* device, std::int32_t requestId, RwSubSystemInfo* pOut, void* pInOut, std::int32_t numIn); static RwSubSystemInfo* RwEngineGetSubSystemInfo_Hooked(RwSubSystemInfo* subSystemInfo, std::int32_t subSystemIndex) { - auto rwGlobals = *(RwGlobals**)(0xC97B24); - auto rwDeviceSystemRequestFunc = (rwDeviceSystemRequest)(FUNC_rwDeviceSystemRequest); + auto* rwGlobals = *(RwGlobals**)(0xC97B24); + auto* rwDeviceSystemRequestFunc = (rwDeviceSystemRequest)(FUNC_rwDeviceSystemRequest); if (!rwDeviceSystemRequestFunc(&rwGlobals->dOpenDevice, 14, subSystemInfo, nullptr, subSystemIndex)) return nullptr; - auto pDxDevice = *(IDirect3D9**)0xC97C20; + auto* pDxDevice = *(IDirect3D9**)0xC97C20; if (!pDxDevice) return subSystemInfo; @@ -124,7 +124,7 @@ static RwSubSystemInfo* RwEngineGetSubSystemInfo_Hooked(RwSubSystemInfo* subSyst #define FUNC_DialogFunc 0x745E50 INT_PTR CALLBACK CustomDlgProc(HWND window, UINT msg, WPARAM wParam, LPARAM lParam) { - auto orgDialogFunc = (DLGPROC)FUNC_DialogFunc; + auto* orgDialogFunc = (DLGPROC)FUNC_DialogFunc; if (msg != WM_INITDIALOG) return orgDialogFunc(window, msg, wParam, lParam); From 1a7e9cd1a66e857a09a9c078fabc89dfe1000980 Mon Sep 17 00:00:00 2001 From: Kamil Marciniak Date: Sun, 10 Nov 2024 20:57:21 +0100 Subject: [PATCH 12/13] Move every single magic number to the defines at the top of the file --- .../CMultiplayerSA_DeviceSelection.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/Client/multiplayer_sa/CMultiplayerSA_DeviceSelection.cpp b/Client/multiplayer_sa/CMultiplayerSA_DeviceSelection.cpp index 09675de8d20..e25b6c85111 100644 --- a/Client/multiplayer_sa/CMultiplayerSA_DeviceSelection.cpp +++ b/Client/multiplayer_sa/CMultiplayerSA_DeviceSelection.cpp @@ -9,6 +9,12 @@ *****************************************************************************/ #include "StdInc.h" +#define FUNC_rwDeviceSystemRequest 0x7F2AB0 +#define FUNC_DialogFunc 0x745E50 +#define FUNC_RwEngineGetSubSystemInfo 0x7F2C30 +#define CLASS_RwGlobals 0xC97B24 +#define CLASS_IDirect3D9 0xC97C20 +#define NUM_DialogFuncStackPushAddress 0x746239 // This is copied from SilentPatch: // https://github.com/CookiePLMonster/SilentPatch/blob/dev/SilentPatch/FriendlyMonitorNames.cpp @@ -88,16 +94,15 @@ struct RwSubSystemInfo char name[80]; }; -#define FUNC_rwDeviceSystemRequest 0x7F2AB0 using rwDeviceSystemRequest = RwSubSystemInfo*(__cdecl*)(RwDevice* device, std::int32_t requestId, RwSubSystemInfo* pOut, void* pInOut, std::int32_t numIn); static RwSubSystemInfo* RwEngineGetSubSystemInfo_Hooked(RwSubSystemInfo* subSystemInfo, std::int32_t subSystemIndex) { - auto* rwGlobals = *(RwGlobals**)(0xC97B24); + auto* rwGlobals = *(RwGlobals**)CLASS_RwGlobals; auto* rwDeviceSystemRequestFunc = (rwDeviceSystemRequest)(FUNC_rwDeviceSystemRequest); if (!rwDeviceSystemRequestFunc(&rwGlobals->dOpenDevice, 14, subSystemInfo, nullptr, subSystemIndex)) return nullptr; - auto* pDxDevice = *(IDirect3D9**)0xC97C20; + auto* pDxDevice = *(IDirect3D9**)CLASS_IDirect3D9; if (!pDxDevice) return subSystemInfo; @@ -121,7 +126,6 @@ static RwSubSystemInfo* RwEngineGetSubSystemInfo_Hooked(RwSubSystemInfo* subSyst return subSystemInfo; } -#define FUNC_DialogFunc 0x745E50 INT_PTR CALLBACK CustomDlgProc(HWND window, UINT msg, WPARAM wParam, LPARAM lParam) { auto* orgDialogFunc = (DLGPROC)FUNC_DialogFunc; @@ -142,11 +146,10 @@ INT_PTR CALLBACK CustomDlgProc(HWND window, UINT msg, WPARAM wParam, LPARAM lPar return FALSE; } -#define FUNC_RwEngineGetSubSystemInfo 0x7F2C30 void CMultiplayerSA::InitHooks_DeviceSelection() { // 0x746239 -> Exact address where the original DialogFunc address is being pushed as an argument to DialogBoxParamA(), // we're replacing it with out own proxy function - MemPut(0x746239, (DLGPROC)&CustomDlgProc); + MemPut(NUM_DialogFuncStackPushAddress, (DLGPROC)&CustomDlgProc); HookInstall(FUNC_RwEngineGetSubSystemInfo, (DWORD)RwEngineGetSubSystemInfo_Hooked, 6); } From 479f0f7c545b568f850606c3df93efab8f07ce18 Mon Sep 17 00:00:00 2001 From: Kamil Marciniak Date: Mon, 11 Nov 2024 12:39:23 +0100 Subject: [PATCH 13/13] Replace std::map with std::unordered_map --- Client/multiplayer_sa/CMultiplayerSA_DeviceSelection.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Client/multiplayer_sa/CMultiplayerSA_DeviceSelection.cpp b/Client/multiplayer_sa/CMultiplayerSA_DeviceSelection.cpp index e25b6c85111..586f3872702 100644 --- a/Client/multiplayer_sa/CMultiplayerSA_DeviceSelection.cpp +++ b/Client/multiplayer_sa/CMultiplayerSA_DeviceSelection.cpp @@ -18,9 +18,9 @@ // This is copied from SilentPatch: // https://github.com/CookiePLMonster/SilentPatch/blob/dev/SilentPatch/FriendlyMonitorNames.cpp -std::map> GetFriendlyMonitorNamesForDevicePaths() +std::unordered_map GetFriendlyMonitorNamesForDevicePaths() { - std::map> monitorNames; + std::unordered_map monitorNames; HMODULE user32Lib = LoadLibrary(TEXT("user32")); if (!user32Lib)