mirror of
https://github.com/CookiePLMonster/SilentPatch.git
synced 2024-12-28 06:43:01 +05:00
SA: Remake the monitor/resolution selection dialog
* Uses Common Controls 6 (modern styling) * Lists friendly monitor names * Acts correctly on pressing Escape * Doesn't bug out when an inexistent adapter is selected * Remembers the selected adapter * Gives an option to skip the dialog and remember the choice * Shows in the taskbar correctly * Explicitly asks the system to scale for DPI, overriding compat options
This commit is contained in:
parent
686031437d
commit
15f9f08052
7 changed files with 400 additions and 18 deletions
77
SilentPatch/FriendlyMonitorNames.cpp
Normal file
77
SilentPatch/FriendlyMonitorNames.cpp
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
#include "FriendlyMonitorNames.h"
|
||||||
|
|
||||||
|
// This API is Win7 only, so make sure we use dynamic imports
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
|
||||||
|
#define NOMINMAX
|
||||||
|
#define WINVER 0x0602
|
||||||
|
#define _WIN32_WINNT 0x0602
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
std::map<std::string, std::string, std::less<>> FriendlyMonitorNames::GetNamesForDevicePaths()
|
||||||
|
{
|
||||||
|
std::map<std::string, std::string, std::less<>> monitorNames;
|
||||||
|
|
||||||
|
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<DISPLAYCONFIG_PATH_INFO[]> paths;
|
||||||
|
std::unique_ptr<DISPLAYCONFIG_MODE_INFO[]> modes;
|
||||||
|
|
||||||
|
LONG result = ERROR_SUCCESS;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
result = getDisplayConfigBufferSizes(QDC_ONLY_ACTIVE_PATHS, &pathCount, &modeCount);
|
||||||
|
if (result != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
paths = std::make_unique<DISPLAYCONFIG_PATH_INFO[]>(pathCount);
|
||||||
|
modes = std::make_unique<DISPLAYCONFIG_MODE_INFO[]>(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<int>(std::size(gdiDeviceName)), nullptr, nullptr);
|
||||||
|
WideCharToMultiByte(CP_ACP, 0, targetName.monitorFriendlyDeviceName, -1, monitorFriendlyDeviceName, static_cast<int>(std::size(monitorFriendlyDeviceName)), nullptr, nullptr);
|
||||||
|
|
||||||
|
monitorNames.try_emplace(gdiDeviceName, monitorFriendlyDeviceName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FreeLibrary(user32Lib);
|
||||||
|
}
|
||||||
|
|
||||||
|
return monitorNames;
|
||||||
|
}
|
9
SilentPatch/FriendlyMonitorNames.h
Normal file
9
SilentPatch/FriendlyMonitorNames.h
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace FriendlyMonitorNames
|
||||||
|
{
|
||||||
|
std::map<std::string, std::string, std::less<>> GetNamesForDevicePaths();
|
||||||
|
}
|
|
@ -30,11 +30,16 @@
|
||||||
#include "Utils/HookEach.hpp"
|
#include "Utils/HookEach.hpp"
|
||||||
|
|
||||||
#include "Desktop.h"
|
#include "Desktop.h"
|
||||||
|
#include "FriendlyMonitorNames.h"
|
||||||
#include "SVF.h"
|
#include "SVF.h"
|
||||||
|
|
||||||
#include "debugmenu_public.h"
|
#include "debugmenu_public.h"
|
||||||
#include "resource.h"
|
#include "resource.h"
|
||||||
|
|
||||||
|
#pragma comment(linker,"\"/manifestdependency:type='win32' \
|
||||||
|
name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \
|
||||||
|
processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
|
||||||
|
|
||||||
EXTERN_C IMAGE_DOS_HEADER __ImageBase;
|
EXTERN_C IMAGE_DOS_HEADER __ImageBase;
|
||||||
|
|
||||||
// ============= Mod compatibility stuff =============
|
// ============= Mod compatibility stuff =============
|
||||||
|
@ -130,6 +135,8 @@ static void* varRwMatrixRotate = AddressByVersion<void*>(0x7F1FD0, 0x7F28D0, 0x8
|
||||||
WRAPPER RwMatrix* RwMatrixRotate(RwMatrix* matrix, const RwV3d* axis, RwReal angle, RwOpCombineType combineOp) { WRAPARG(matrix); WRAPARG(axis); WRAPARG(angle); WRAPARG(combineOp); VARJMP(varRwMatrixRotate); }
|
WRAPPER RwMatrix* RwMatrixRotate(RwMatrix* matrix, const RwV3d* axis, RwReal angle, RwOpCombineType combineOp) { WRAPARG(matrix); WRAPARG(axis); WRAPARG(angle); WRAPARG(combineOp); VARJMP(varRwMatrixRotate); }
|
||||||
static void* varRwD3D9SetRenderState = AddressByVersion<void*>(0x7FC2D0, 0x7FCBD0, 0x836290);
|
static void* varRwD3D9SetRenderState = AddressByVersion<void*>(0x7FC2D0, 0x7FCBD0, 0x836290);
|
||||||
WRAPPER void RwD3D9SetRenderState(RwUInt32 state, RwUInt32 value) { WRAPARG(state); WRAPARG(value); VARJMP(varRwD3D9SetRenderState); }
|
WRAPPER void RwD3D9SetRenderState(RwUInt32 state, RwUInt32 value) { WRAPARG(state); WRAPARG(value); VARJMP(varRwD3D9SetRenderState); }
|
||||||
|
static void* varRwEngineSetSubSystem = AddressByVersion<void*>(0x7F2C90, { "50 6A 00 6A 00 83 C1 10 6A 10 51", -0xA });
|
||||||
|
WRAPPER RwBool RwEngineSetSubSystem(RwInt32 subSystemIndex) { WRAPARG(subSystemIndex); VARJMP(varRwEngineSetSubSystem); }
|
||||||
|
|
||||||
RwCamera* RwCameraBeginUpdate(RwCamera* camera)
|
RwCamera* RwCameraBeginUpdate(RwCamera* camera)
|
||||||
{
|
{
|
||||||
|
@ -2533,6 +2540,225 @@ namespace Rand16bit
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ============= Improved resolution selection dialog =============
|
||||||
|
namespace NewResolutionSelectionDialog
|
||||||
|
{
|
||||||
|
static IDirect3D9** ppRWD3D9;
|
||||||
|
static void* FrontEndMenuManager;
|
||||||
|
static char* (*orgGetDocumentsPath)();
|
||||||
|
|
||||||
|
static constexpr const char* SettingsFileName = "device_remembered.set";
|
||||||
|
|
||||||
|
static bool ShouldSkipDeviceSelection()
|
||||||
|
{
|
||||||
|
char cTmpPath[MAX_PATH];
|
||||||
|
PathCombineA(cTmpPath, GetMyDocumentsPathSA(), SettingsFileName);
|
||||||
|
|
||||||
|
bool bSkip = false;
|
||||||
|
|
||||||
|
FILE* hFile = nullptr;
|
||||||
|
if (fopen_s(&hFile, cTmpPath, "r") == 0)
|
||||||
|
{
|
||||||
|
unsigned int val = 0;
|
||||||
|
bSkip = fscanf_s(hFile, "%u", &val) == 1 && val != 0;
|
||||||
|
fclose(hFile);
|
||||||
|
}
|
||||||
|
return bSkip;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void RememberDeviceSelection(bool bDoNotShowAgain)
|
||||||
|
{
|
||||||
|
char cTmpPath[MAX_PATH];
|
||||||
|
PathCombineA(cTmpPath, GetMyDocumentsPathSA(), SettingsFileName);
|
||||||
|
|
||||||
|
FILE* hFile = nullptr;
|
||||||
|
if (fopen_s(&hFile, cTmpPath, "w") == 0)
|
||||||
|
{
|
||||||
|
fprintf_s(hFile, "%u", bDoNotShowAgain ? 1 : 0);
|
||||||
|
fclose(hFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static RwSubSystemInfo *RwEngineGetSubSystemInfo_GetFriendlyNames(RwSubSystemInfo *subSystemInfo, RwInt32 subSystemIndex)
|
||||||
|
{
|
||||||
|
static const auto friendlyNames = FriendlyMonitorNames::GetNamesForDevicePaths();
|
||||||
|
|
||||||
|
D3DADAPTER_IDENTIFIER9 identifier;
|
||||||
|
if (FAILED((*ppRWD3D9)->GetAdapterIdentifier(subSystemIndex, 0, &identifier)))
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t MenuManagerAdapterOffset = 0xDC;
|
||||||
|
static RwInt32 RwEngineGetCurrentSubSystem_FromSettings()
|
||||||
|
{
|
||||||
|
RwInt32 subSystem = *reinterpret_cast<RwInt32*>(static_cast<char*>(FrontEndMenuManager) + MenuManagerAdapterOffset);
|
||||||
|
if (subSystem > 0)
|
||||||
|
{
|
||||||
|
// Force the device selection dialog to show again if anything is wrong
|
||||||
|
bool bResetDisplay = false;
|
||||||
|
if ((*ppRWD3D9)->GetAdapterCount() <= (UINT)subSystem)
|
||||||
|
{
|
||||||
|
subSystem = 0;
|
||||||
|
bResetDisplay = true;
|
||||||
|
}
|
||||||
|
if (RwEngineSetSubSystem(subSystem) == FALSE || bResetDisplay)
|
||||||
|
{
|
||||||
|
RememberDeviceSelection(false);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return subSystem;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void CreateNewButtonTooltip(HINSTANCE hInstance, HWND hDlg)
|
||||||
|
{
|
||||||
|
HWND hCheckbox = GetDlgItem(hDlg, IDC_REMEMBERRESCHOICE);
|
||||||
|
HWND hwndTip = CreateWindowEx(WS_EX_TOPMOST, TOOLTIPS_CLASS, NULL, WS_POPUP | TTS_ALWAYSTIP, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
|
||||||
|
hDlg, nullptr, hInstance, nullptr);
|
||||||
|
|
||||||
|
if (hCheckbox == nullptr || hwndTip == nullptr)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
TOOLINFO toolInfo { sizeof(toolInfo) };
|
||||||
|
toolInfo.hwnd = hDlg;
|
||||||
|
toolInfo.uFlags = TTF_IDISHWND | TTF_SUBCLASS;
|
||||||
|
toolInfo.uId = (UINT_PTR)hCheckbox;
|
||||||
|
toolInfo.lpszText = (LPWSTR)TEXT("Delete 'device_remembered.set' from GTA San Andreas User Files to show this dialog again.");
|
||||||
|
|
||||||
|
SendMessage(hwndTip, TTM_ADDTOOL, 0, (LPARAM)&toolInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct WrappedDialocFunc
|
||||||
|
{
|
||||||
|
DLGPROC lpDialogFunc;
|
||||||
|
LPARAM dwInitParam;
|
||||||
|
};
|
||||||
|
static INT_PTR CALLBACK CustomDlgProc(HWND window, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
if (msg == WM_INITDIALOG)
|
||||||
|
{
|
||||||
|
const WrappedDialocFunc* data = reinterpret_cast<WrappedDialocFunc*>(lParam);
|
||||||
|
SetWindowLongPtr(window, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(data->lpDialogFunc));
|
||||||
|
|
||||||
|
data->lpDialogFunc(window, msg, wParam, data->dwInitParam);
|
||||||
|
|
||||||
|
// The stock dialog func loaded the selected adapter and resolution at this point,
|
||||||
|
// we can bail if we don't need to show the dialog
|
||||||
|
if (ShouldSkipDeviceSelection())
|
||||||
|
{
|
||||||
|
// The game inits the selected resolution weirdly, and corrects it in the IDOK handler
|
||||||
|
// so let's invoke it manually (bleh)
|
||||||
|
data->lpDialogFunc(window, WM_COMMAND, IDOK, 0);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
HMODULE hGameModule = GetModuleHandle(nullptr);
|
||||||
|
SendMessage(window, WM_SETICON, ICON_SMALL, reinterpret_cast<LPARAM>(LoadIcon(hGameModule, MAKEINTRESOURCE(100))));
|
||||||
|
CreateNewButtonTooltip(hGameModule, window);
|
||||||
|
|
||||||
|
// Return TRUE instead of FALSE on init, we want keyboard focus
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Custom handling for IDCANCEL (IDOK is fine)
|
||||||
|
if (msg == WM_COMMAND)
|
||||||
|
{
|
||||||
|
if (LOWORD(wParam) == IDCANCEL)
|
||||||
|
{
|
||||||
|
EndDialog(window, 0);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Just remember the selection, let the game handle the rest
|
||||||
|
if (LOWORD(wParam) == IDOK && IsDlgButtonChecked(window, IDC_REMEMBERRESCHOICE) == BST_CHECKED)
|
||||||
|
{
|
||||||
|
RememberDeviceSelection(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DLGPROC origProc = reinterpret_cast<DLGPROC>(GetWindowLongPtr(window, GWLP_USERDATA));
|
||||||
|
if (origProc != nullptr)
|
||||||
|
{
|
||||||
|
return origProc(window, msg, wParam, lParam);
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static INT_PTR WINAPI DialogBoxParamA_New(HINSTANCE /*hInstance*/, LPCSTR /*lpTemplateName*/, HWND /*hWndParent*/, DLGPROC lpDialogFunc, LPARAM dwInitParam)
|
||||||
|
{
|
||||||
|
int32_t (WINAPI *pSetThreadDpiAwarenessContext)(int32_t dpiContext) = nullptr;
|
||||||
|
int32_t oldDpiContext = 0;
|
||||||
|
|
||||||
|
// Specify the dialog as DPI unaware, so Windows scales it by itself
|
||||||
|
HMODULE user32Module = LoadLibraryW(L"user32");
|
||||||
|
if (user32Module != nullptr)
|
||||||
|
{
|
||||||
|
pSetThreadDpiAwarenessContext = (decltype(pSetThreadDpiAwarenessContext))GetProcAddress(user32Module, "SetThreadDpiAwarenessContext");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pSetThreadDpiAwarenessContext != nullptr)
|
||||||
|
{
|
||||||
|
oldDpiContext = pSetThreadDpiAwarenessContext(/*DPI_AWARENESS_CONTEXT_UNAWARE*/-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
ACTCTX actCtx { sizeof(actCtx) };
|
||||||
|
actCtx.hModule = reinterpret_cast<HMODULE>(&__ImageBase);
|
||||||
|
actCtx.lpResourceName = MAKEINTRESOURCE(2);
|
||||||
|
actCtx.dwFlags = ACTCTX_FLAG_HMODULE_VALID | ACTCTX_FLAG_RESOURCE_NAME_VALID;
|
||||||
|
|
||||||
|
ULONG_PTR cookie = 0;
|
||||||
|
bool bContextActivated = false;
|
||||||
|
|
||||||
|
HANDLE hActCtx = CreateActCtx(&actCtx);
|
||||||
|
if (hActCtx != INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
bContextActivated = ActivateActCtx(hActCtx, &cookie) != FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Include our own context to allow for custom message handling
|
||||||
|
const WrappedDialocFunc origDlgProc { lpDialogFunc, dwInitParam };
|
||||||
|
const INT_PTR result = DialogBoxParam(reinterpret_cast<HMODULE>(&__ImageBase), MAKEINTRESOURCE(IDD_RESSELECT), nullptr, CustomDlgProc, reinterpret_cast<LPARAM>(&origDlgProc));
|
||||||
|
|
||||||
|
if (bContextActivated)
|
||||||
|
{
|
||||||
|
DeactivateActCtx(0, cookie);
|
||||||
|
}
|
||||||
|
if (hActCtx != INVALID_HANDLE_VALUE)
|
||||||
|
{
|
||||||
|
ReleaseActCtx(hActCtx);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pSetThreadDpiAwarenessContext != nullptr)
|
||||||
|
{
|
||||||
|
pSetThreadDpiAwarenessContext(oldDpiContext);
|
||||||
|
}
|
||||||
|
if (user32Module != nullptr)
|
||||||
|
{
|
||||||
|
FreeLibrary(user32Module);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
static auto* const pDialogBoxParamA_New = &DialogBoxParamA_New;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// ============= LS-RP Mode stuff =============
|
// ============= LS-RP Mode stuff =============
|
||||||
namespace LSRPMode
|
namespace LSRPMode
|
||||||
{
|
{
|
||||||
|
@ -5372,6 +5598,22 @@ void Patch_SA_10(HINSTANCE hInstance)
|
||||||
Patch<uint8_t>(0x63F576, 0x75);
|
Patch<uint8_t>(0x63F576, 0x75);
|
||||||
|
|
||||||
|
|
||||||
|
// Improved resolution selection dialog
|
||||||
|
{
|
||||||
|
using namespace NewResolutionSelectionDialog;
|
||||||
|
|
||||||
|
ppRWD3D9 = *(IDirect3D9***)(0x7F6312 + 1);
|
||||||
|
FrontEndMenuManager = *(void**)(0x4054DB + 1);
|
||||||
|
|
||||||
|
orgGetDocumentsPath = (char*(*)())0x744FB0;
|
||||||
|
|
||||||
|
Patch(0x0746241 + 2, &pDialogBoxParamA_New);
|
||||||
|
|
||||||
|
InjectHook(0x7461D8, RwEngineGetSubSystemInfo_GetFriendlyNames);
|
||||||
|
InjectHook(0x7461ED, RwEngineGetCurrentSubSystem_FromSettings);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#if FULL_PRECISION_D3D
|
#if FULL_PRECISION_D3D
|
||||||
// Test - full precision D3D device
|
// Test - full precision D3D device
|
||||||
Patch<uint8_t>( 0x7F672B+1, *(uint8_t*)(0x7F672B+1) | D3DCREATE_FPU_PRESERVE );
|
Patch<uint8_t>( 0x7F672B+1, *(uint8_t*)(0x7F672B+1) | D3DCREATE_FPU_PRESERVE );
|
||||||
|
@ -7351,6 +7593,39 @@ void Patch_SA_NewBinaries_Common(HINSTANCE hInstance)
|
||||||
Patch<uint8_t>(isAlive, 0x75);
|
Patch<uint8_t>(isAlive, 0x75);
|
||||||
}
|
}
|
||||||
TXN_CATCH();
|
TXN_CATCH();
|
||||||
|
|
||||||
|
|
||||||
|
// Improved resolution selection dialog
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using namespace NewResolutionSelectionDialog;
|
||||||
|
|
||||||
|
// RGL changed one of the parameters
|
||||||
|
auto dialogBoxParam = [] {
|
||||||
|
try {
|
||||||
|
// Steam
|
||||||
|
return get_pattern("51 FF 15 ? ? ? ? 85 C0 0F 84", 1 + 2);
|
||||||
|
} catch (const hook::txn_exception&) {
|
||||||
|
// RGL
|
||||||
|
return get_pattern("53 FF 15 ? ? ? ? 85 C0", 1 + 2);
|
||||||
|
}
|
||||||
|
}();
|
||||||
|
|
||||||
|
auto rRwEngineGetSubSystemInfo = get_pattern("E8 ? ? ? ? 46 83 C4 08 83 C7 50");
|
||||||
|
auto rwEngineGetCurrentSubSystem = get_pattern("7C EA E8 ? ? ? ? A3", 2);
|
||||||
|
MenuManagerAdapterOffset = 0xD8;
|
||||||
|
|
||||||
|
ppRWD3D9 = *get_pattern<IDirect3D9**>("33 ED A3 ? ? ? ? 3B C5", 2 + 1);
|
||||||
|
FrontEndMenuManager = *get_pattern<void**>("50 50 68 ? ? ? ? B9 ? ? ? ? E8", 7 + 1); // This has 2 identical matches, we just need one
|
||||||
|
|
||||||
|
orgGetDocumentsPath = static_cast<char*(*)()>(get_pattern( "8D 45 FC 50 68 19 00 02 00", -6 ));
|
||||||
|
|
||||||
|
Patch(dialogBoxParam, &pDialogBoxParamA_New);
|
||||||
|
|
||||||
|
InjectHook(rRwEngineGetSubSystemInfo, RwEngineGetSubSystemInfo_GetFriendlyNames);
|
||||||
|
InjectHook(rwEngineGetCurrentSubSystem, RwEngineGetCurrentSubSystem_FromSettings);
|
||||||
|
}
|
||||||
|
TXN_CATCH();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Binary file not shown.
|
@ -207,6 +207,11 @@ copy /y "$(TargetPath)" "H:\Rockstar Games\Grand Theft Auto San Andreas\SilentPa
|
||||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Shipping|Win32'">NotUsing</PrecompiledHeader>
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Shipping|Win32'">NotUsing</PrecompiledHeader>
|
||||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\SilentPatch\FriendlyMonitorNames.cpp">
|
||||||
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
|
||||||
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Shipping|Win32'">NotUsing</PrecompiledHeader>
|
||||||
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">NotUsing</PrecompiledHeader>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="..\SilentPatch\ParseUtils.cpp">
|
<ClCompile Include="..\SilentPatch\ParseUtils.cpp">
|
||||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
|
||||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Shipping|Win32'">NotUsing</PrecompiledHeader>
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Shipping|Win32'">NotUsing</PrecompiledHeader>
|
||||||
|
@ -250,10 +255,10 @@ copy /y "$(TargetPath)" "H:\Rockstar Games\Grand Theft Auto San Andreas\SilentPa
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="..\SilentPatch\debugmenu_public.h" />
|
<ClInclude Include="..\SilentPatch\debugmenu_public.h" />
|
||||||
<ClInclude Include="..\SilentPatch\Desktop.h" />
|
<ClInclude Include="..\SilentPatch\Desktop.h" />
|
||||||
|
<ClInclude Include="..\SilentPatch\FriendlyMonitorNames.h" />
|
||||||
<ClInclude Include="..\SilentPatch\Maths.h" />
|
<ClInclude Include="..\SilentPatch\Maths.h" />
|
||||||
<ClInclude Include="..\SilentPatch\ParseUtils.hpp" />
|
<ClInclude Include="..\SilentPatch\ParseUtils.hpp" />
|
||||||
<ClInclude Include="..\SilentPatch\Random.h" />
|
<ClInclude Include="..\SilentPatch\Random.h" />
|
||||||
<ClInclude Include="..\SilentPatch\resource1.h" />
|
|
||||||
<ClInclude Include="..\SilentPatch\RWUtils.hpp" />
|
<ClInclude Include="..\SilentPatch\RWUtils.hpp" />
|
||||||
<ClInclude Include="..\SilentPatch\SVF.h" />
|
<ClInclude Include="..\SilentPatch\SVF.h" />
|
||||||
<ClInclude Include="..\SilentPatch\TheFLAUtils.h" />
|
<ClInclude Include="..\SilentPatch\TheFLAUtils.h" />
|
||||||
|
@ -279,11 +284,11 @@ copy /y "$(TargetPath)" "H:\Rockstar Games\Grand Theft Auto San Andreas\SilentPa
|
||||||
<ClInclude Include="WaveDecoderSA.h" />
|
<ClInclude Include="WaveDecoderSA.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ResourceCompile Include="..\SilentPatch\SilentPatch.rc" />
|
<Image Include="lunar64.png" />
|
||||||
<ResourceCompile Include="SilentPatchSA.rc" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Image Include="lunar64.png" />
|
<ResourceCompile Include="..\SilentPatch\SilentPatch.rc" />
|
||||||
|
<ResourceCompile Include="SilentPatchSA.rc" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
<ImportGroup Label="ExtensionTargets">
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
|
|
@ -84,6 +84,9 @@
|
||||||
<ClCompile Include="..\SilentPatch\ParseUtils.cpp">
|
<ClCompile Include="..\SilentPatch\ParseUtils.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\SilentPatch\FriendlyMonitorNames.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="StdAfxSA.h">
|
<ClInclude Include="StdAfxSA.h">
|
||||||
|
@ -116,18 +119,12 @@
|
||||||
<ClInclude Include="PedSA.h">
|
<ClInclude Include="PedSA.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="resource.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="WaveDecoderSA.h">
|
<ClInclude Include="WaveDecoderSA.h">
|
||||||
<Filter>Source Files\decoders</Filter>
|
<Filter>Source Files\decoders</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="FLACDecoderSA.h">
|
<ClInclude Include="FLACDecoderSA.h">
|
||||||
<Filter>Source Files\decoders</Filter>
|
<Filter>Source Files\decoders</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\SilentPatch\resource1.h">
|
|
||||||
<Filter>Header Files</Filter>
|
|
||||||
</ClInclude>
|
|
||||||
<ClInclude Include="..\SilentPatch\TheFLAUtils.h">
|
<ClInclude Include="..\SilentPatch\TheFLAUtils.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
@ -173,18 +170,24 @@
|
||||||
<ClInclude Include="..\SilentPatch\Random.h">
|
<ClInclude Include="..\SilentPatch\Random.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
</ItemGroup>
|
<ClInclude Include="..\SilentPatch\FriendlyMonitorNames.h">
|
||||||
<ItemGroup>
|
<Filter>Header Files</Filter>
|
||||||
<ResourceCompile Include="..\SilentPatch\SilentPatch.rc">
|
</ClInclude>
|
||||||
<Filter>Resource Files</Filter>
|
<ClInclude Include="resource.h">
|
||||||
</ResourceCompile>
|
<Filter>Header Files</Filter>
|
||||||
<ResourceCompile Include="SilentPatchSA.rc">
|
</ClInclude>
|
||||||
<Filter>Resource Files</Filter>
|
|
||||||
</ResourceCompile>
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Image Include="lunar64.png">
|
<Image Include="lunar64.png">
|
||||||
<Filter>Resource Files</Filter>
|
<Filter>Resource Files</Filter>
|
||||||
</Image>
|
</Image>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ResourceCompile Include="SilentPatchSA.rc">
|
||||||
|
<Filter>Resource Files</Filter>
|
||||||
|
</ResourceCompile>
|
||||||
|
<ResourceCompile Include="..\SilentPatch\SilentPatch.rc">
|
||||||
|
<Filter>Resource Files</Filter>
|
||||||
|
</ResourceCompile>
|
||||||
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
|
@ -3,3 +3,16 @@
|
||||||
// Used by SilentPatchSA.rc
|
// Used by SilentPatchSA.rc
|
||||||
//
|
//
|
||||||
#define IDB_LUNAR64 101
|
#define IDB_LUNAR64 101
|
||||||
|
#define IDD_RESSELECT 102
|
||||||
|
#define IDC_REMEMBERRESCHOICE 1003
|
||||||
|
|
||||||
|
// Next default values for new objects
|
||||||
|
//
|
||||||
|
#ifdef APSTUDIO_INVOKED
|
||||||
|
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||||
|
#define _APS_NEXT_RESOURCE_VALUE 104
|
||||||
|
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||||
|
#define _APS_NEXT_CONTROL_VALUE 1004
|
||||||
|
#define _APS_NEXT_SYMED_VALUE 101
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue