From 3cf3d4494582f4b20f8f703f307ed0290b46b212 Mon Sep 17 00:00:00 2001 From: Will Xyen Date: Tue, 15 Mar 2022 00:38:46 -0700 Subject: [PATCH] sdvxhook2: add nvapi and power hooks --- Module.mk | 4 +- dist/sdvx5/sdvxhook2.conf | 15 ++++++ src/main/d3d9exhook/config-gfx.c | 2 +- src/main/sdvxhook2/acio.c | 13 +++-- src/main/sdvxhook2/acio.h | 2 +- src/main/sdvxhook2/config-io.c | 61 ++++++++++++++++++++++ src/main/sdvxhook2/config-io.h | 3 ++ src/main/sdvxhook2/dllmain.c | 14 ++++- src/main/sdvxhook2/nvapi.c | 89 ++++++++++++++++++++++++++++++++ src/main/sdvxhook2/nvapi.h | 8 +++ src/main/sdvxhook2/power.c | 86 ++++++++++++++++++++++++++++++ src/main/sdvxhook2/power.h | 8 +++ src/main/sdvxio/sdvxio.c | 2 +- 13 files changed, 297 insertions(+), 10 deletions(-) create mode 100644 src/main/sdvxhook2/nvapi.c create mode 100644 src/main/sdvxhook2/nvapi.h create mode 100644 src/main/sdvxhook2/power.c create mode 100644 src/main/sdvxhook2/power.h diff --git a/Module.mk b/Module.mk index e8732b4..1b31a4f 100644 --- a/Module.mk +++ b/Module.mk @@ -517,7 +517,7 @@ $(zipdir)/sdvx-01-to-04.zip: \ $(V)echo ... $@ $(V)zip -j $@ $^ -$(zipdir)/sdvx-05.zip: \ +$(zipdir)/sdvx-05-to-06.zip: \ build/bin/avs2_1700-64/launcher.exe \ build/bin/avs2_1700-64/sdvxhook2.dll \ build/bin/indep-64/config.exe \ @@ -671,7 +671,7 @@ $(BUILDDIR)/bemanitools.zip: \ $(zipdir)/jb-08.zip \ $(zipdir)/jb-hwio.zip \ $(zipdir)/sdvx-01-to-04.zip \ - $(zipdir)/sdvx-05.zip \ + $(zipdir)/sdvx-05-to-06.zip \ $(zipdir)/sdvx-05-cn.zip \ $(zipdir)/sdvx-hwio-x86.zip \ $(zipdir)/sdvx-hwio-x64.zip \ diff --git a/dist/sdvx5/sdvxhook2.conf b/dist/sdvx5/sdvxhook2.conf index 3a0106b..8d2b386 100644 --- a/dist/sdvx5/sdvxhook2.conf +++ b/dist/sdvx5/sdvxhook2.conf @@ -13,6 +13,15 @@ io.force_headphones=false # Disables the built in file hooks, requiring manual file creation (/dev/raw/j.dest) io.disable_file_hooks=false +# Disables the built in power control hooks, allowing game to modify system power settings +io.disable_power_hooks=false + +# Disables the built in NVAPI control hooks, allowing game to modify system monitor settings +io.disable_nvapi_hooks=false + +# Emulates the card reader on COM1 instead of COM2 +io.com1_card_reader=false + # Run the game in a framed window (requires windowed option) gfx.framed=true @@ -43,6 +52,12 @@ gfx.device_adapter=-1 # Orientation to force monitor into, -1 to use default, 0, 1, 2, 3 to do 0, 90, 180, 270 degrees gfx.force_orientation=-1 +# Force a screen resolution (width), -1 to disable. Use this if the game does not auto detect your monitor's resolution properly, e.g. 1368x768 instead of 1280x720. +gfx.force_screen_res.width=-1 + +# Force a screen resolution (height), -1 to disable. Use this if the game does not auto detect your monitor's resolution properly, e.g. 1368x768 instead of 1280x720. +gfx.force_screen_res.height=-1 + # Disables the camera emulation cam.disable_emu=false diff --git a/src/main/d3d9exhook/config-gfx.c b/src/main/d3d9exhook/config-gfx.c index 8b75daf..dbd5e99 100644 --- a/src/main/d3d9exhook/config-gfx.c +++ b/src/main/d3d9exhook/config-gfx.c @@ -52,7 +52,7 @@ void d3d9exhook_config_gfx_init(struct cconfig *config) config, D3D9EXHOOK_CONFIG_GFX_CONFINED_KEY, D3D9EXHOOK_CONFIG_GFX_DEFAULT_CONFINED_VALUE, - "Confine mouse coursor to window"); + "Confine mouse cursor to window"); cconfig_util_set_int( config, diff --git a/src/main/sdvxhook2/acio.c b/src/main/sdvxhook2/acio.c index ee39901..6ac0cdc 100644 --- a/src/main/sdvxhook2/acio.c +++ b/src/main/sdvxhook2/acio.c @@ -30,11 +30,16 @@ static struct ac_io_emu ac_io_emu; static struct ac_io_emu_icca ac_io_emu_icca; -void ac_io_port_init(void) +void ac_io_port_init(bool use_new_reader) { - ac_io_emu_init(&ac_io_emu, L"\\\\.\\COM2"); - - ac_io_emu_icca_init(&ac_io_emu_icca, &ac_io_emu, 0); + if (use_new_reader) { + ac_io_emu_init(&ac_io_emu, L"COM1"); + ac_io_emu_icca_init(&ac_io_emu_icca, &ac_io_emu, 0); + ac_io_emu_icca_set_version(&ac_io_emu_icca, v170); + } else { + ac_io_emu_init(&ac_io_emu, L"\\\\.\\COM2"); + ac_io_emu_icca_init(&ac_io_emu_icca, &ac_io_emu, 0); + } rs232_hook_add_fd(ac_io_emu.fd); } diff --git a/src/main/sdvxhook2/acio.h b/src/main/sdvxhook2/acio.h index 5766a2f..38a0d3a 100644 --- a/src/main/sdvxhook2/acio.h +++ b/src/main/sdvxhook2/acio.h @@ -7,7 +7,7 @@ #include "hook/iohook.h" -void ac_io_port_init(void); +void ac_io_port_init(bool use_new_reader); void ac_io_port_fini(void); HRESULT ac_io_port_dispatch_irp(struct irp *irp); diff --git a/src/main/sdvxhook2/config-io.c b/src/main/sdvxhook2/config-io.c index 81be301..993d20a 100644 --- a/src/main/sdvxhook2/config-io.c +++ b/src/main/sdvxhook2/config-io.c @@ -10,12 +10,19 @@ #define SDVXHOOK2_CONFIG_IO_DISABLE_POLL_LIMITER_KEY "io.disable_poll_limiter" #define SDVXHOOK2_CONFIG_IO_FORCE_HEADPHONES_KEY "io.force_headphones" #define SDVXHOOK2_CONFIG_IO_DISABLE_FILE_HOOKS_KEY "io.disable_file_hooks" +#define SDVXHOOK2_CONFIG_IO_DISABLE_POWER_HOOKS_KEY "io.disable_power_hooks" +#define SDVXHOOK2_CONFIG_IO_DISABLE_NVAPI_HOOKS_KEY "io.disable_nvapi_hooks" +#define SDVXHOOK2_CONFIG_IO_COM1_CARD_READER_KEY "io.com1_card_reader" #define SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_CARD_READER_EMU_VALUE false #define SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_BIO2_EMU_VALUE false #define SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_POLL_LIMITER_VALUE false #define SDVXHOOK2_CONFIG_IO_DEFAULT_FORCE_HEADPHONES_VALUE false #define SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_FILE_HOOKS_VALUE false +#define SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_POWER_HOOKS_VALUE false +#define SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_NVAPI_HOOKS_VALUE false +#define SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_NVAPI_HOOKS_VALUE false +#define SDVXHOOK2_CONFIG_IO_DEFAULT_COM1_CARD_READER_VALUE false void sdvxhook2_config_io_init(struct cconfig *config) { @@ -49,6 +56,24 @@ void sdvxhook2_config_io_init(struct cconfig *config) SDVXHOOK2_CONFIG_IO_DISABLE_FILE_HOOKS_KEY, SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_FILE_HOOKS_VALUE, "Disables the built in file hooks, requiring manual file creation (/dev/raw/j.dest)"); + + cconfig_util_set_bool( + config, + SDVXHOOK2_CONFIG_IO_DISABLE_POWER_HOOKS_KEY, + SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_POWER_HOOKS_VALUE, + "Disables the built in power control hooks, allowing game to modify system power settings"); + + cconfig_util_set_bool( + config, + SDVXHOOK2_CONFIG_IO_DISABLE_NVAPI_HOOKS_KEY, + SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_NVAPI_HOOKS_VALUE, + "Disables the built in NVAPI control hooks, allowing game to modify system monitor settings"); + + cconfig_util_set_bool( + config, + SDVXHOOK2_CONFIG_IO_COM1_CARD_READER_KEY, + SDVXHOOK2_CONFIG_IO_DEFAULT_COM1_CARD_READER_VALUE, + "Emulates the card reader on COM1 instead of COM2"); } void sdvxhook2_config_io_get( @@ -113,4 +138,40 @@ void sdvxhook2_config_io_get( SDVXHOOK2_CONFIG_IO_DISABLE_FILE_HOOKS_KEY, SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_FILE_HOOKS_VALUE); } + + if (!cconfig_util_get_bool( + config, + SDVXHOOK2_CONFIG_IO_DISABLE_POWER_HOOKS_KEY, + &config_io->disable_power_hooks, + SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_POWER_HOOKS_VALUE)) { + log_warning( + "Invalid value for key '%s' specified, fallback " + "to default '%d'", + SDVXHOOK2_CONFIG_IO_DISABLE_POWER_HOOKS_KEY, + SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_POWER_HOOKS_VALUE); + } + + if (!cconfig_util_get_bool( + config, + SDVXHOOK2_CONFIG_IO_DISABLE_NVAPI_HOOKS_KEY, + &config_io->disable_nvapi_hooks, + SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_NVAPI_HOOKS_VALUE)) { + log_warning( + "Invalid value for key '%s' specified, fallback " + "to default '%d'", + SDVXHOOK2_CONFIG_IO_DISABLE_NVAPI_HOOKS_KEY, + SDVXHOOK2_CONFIG_IO_DEFAULT_DISABLE_NVAPI_HOOKS_VALUE); + } + + if (!cconfig_util_get_bool( + config, + SDVXHOOK2_CONFIG_IO_COM1_CARD_READER_KEY, + &config_io->com1_card_reader, + SDVXHOOK2_CONFIG_IO_DEFAULT_COM1_CARD_READER_VALUE)) { + log_warning( + "Invalid value for key '%s' specified, fallback " + "to default '%d'", + SDVXHOOK2_CONFIG_IO_COM1_CARD_READER_KEY, + SDVXHOOK2_CONFIG_IO_DEFAULT_COM1_CARD_READER_VALUE); + } } diff --git a/src/main/sdvxhook2/config-io.h b/src/main/sdvxhook2/config-io.h index 670a3ae..dec90fb 100644 --- a/src/main/sdvxhook2/config-io.h +++ b/src/main/sdvxhook2/config-io.h @@ -11,6 +11,9 @@ struct sdvxhook2_config_io { bool disable_poll_limiter; bool force_headphones; bool disable_file_hooks; + bool disable_power_hooks; + bool disable_nvapi_hooks; + bool com1_card_reader; }; void sdvxhook2_config_io_init(struct cconfig *config); diff --git a/src/main/sdvxhook2/dllmain.c b/src/main/sdvxhook2/dllmain.c index 33b3f8b..9e958df 100644 --- a/src/main/sdvxhook2/dllmain.c +++ b/src/main/sdvxhook2/dllmain.c @@ -22,6 +22,8 @@ #include "sdvxhook2/acio.h" #include "sdvxhook2/bi2a.h" #include "sdvxhook2/config-io.h" +#include "sdvxhook2/nvapi.h" +#include "sdvxhook2/power.h" #include "camhook/cam.h" #include "camhook/config-cam.h" @@ -147,7 +149,7 @@ static bool my_dll_entry_init(char *sidcode, struct property_node *param) } if (!config_io.disable_card_reader_emu) { - ac_io_port_init(); + ac_io_port_init(config_io.com1_card_reader); } // camera hooks @@ -155,6 +157,16 @@ static bool my_dll_entry_init(char *sidcode, struct property_node *param) camhook_init(&config_cam); } + // power hooks + if (!config_io.disable_power_hooks) { + powerhook_init(); + } + + // nvapi hooks + if (!config_io.disable_nvapi_hooks) { + nvapihook_init(); + } + adapter_hook_override(config_adapter.override_ip); log_info("--- End sdvxhook dll_entry_init ---"); diff --git a/src/main/sdvxhook2/nvapi.c b/src/main/sdvxhook2/nvapi.c new file mode 100644 index 0000000..b7e957e --- /dev/null +++ b/src/main/sdvxhook2/nvapi.c @@ -0,0 +1,89 @@ +#define LOG_MODULE "power-hook" + +// clang-format off +// Don't format because the order is important here +#include +#include +// clang-format on + +#include + +#include + +#include "hook/com-proxy.h" +#include "hook/table.h" + +#include "sdvxhook2/nvapi.h" + +#include "util/log.h" + +static HMODULE my_LoadLibraryExW(const wchar_t *name, HANDLE hFile, DWORD dwFlags); +static void *my_GetProcAddress(HMODULE dll, const char *name); + +static HMODULE(*real_LoadLibraryExW)(const wchar_t *name, HANDLE hFile, DWORD dwFlags); +static void *(*real_GetProcAddress)(HMODULE dll, const char *name); + +// nvapi64.dll +static void *my_nvapi_QueryInterface(uint32_t FunctionOffset); +static void *(*real_nvapi_QueryInterface)(uint32_t FunctionOffset); + +static struct hook_symbol nvapihook_kernel_syms[] = { + {.name = "LoadLibraryExW", + .patch = my_LoadLibraryExW, + .link = (void *) &real_LoadLibraryExW}, + {.name = "GetProcAddress", + .patch = my_GetProcAddress, + .link = (void *) &real_GetProcAddress}, +}; + +static HMODULE my_LoadLibraryExW(const wchar_t *name, HANDLE hFile, DWORD dwFlags) +{ + // if (wcsicmp(name, L"nvpowerapi.dll") == 0 || wcsicmp(name, L"nvapi64.dll") == 0)) { + // return NULL; + // } + + return real_LoadLibraryExW(name, hFile, dwFlags); +} + +static void *my_GetProcAddress(HMODULE dll, const char *name) +{ + // if (dll != NULL) { + // return real_GetProcAddress(dll, name); + // } + + if (strcmp("nvapi_QueryInterface", name) == 0) { + log_info("Request for stub %s", name); + real_nvapi_QueryInterface = real_GetProcAddress(dll, name); + return &my_nvapi_QueryInterface; + } + + // log_warning("Request for unknown stub %s", name); + return real_GetProcAddress(dll, name); +} + +#define OFFSET_NvAPI_DISP_SetDisplayConfig 0x5D8CF8DE + +static void *my_nvapi_QueryInterface(uint32_t FunctionOffset) { + if (FunctionOffset == OFFSET_NvAPI_DISP_SetDisplayConfig) { + log_info("Request for interface %x intercepted", FunctionOffset); + // no point stubbing this, the error checking for now doesn't check the response anyways + return NULL; + } + + log_info("Request for interface %x passed", FunctionOffset); + return real_nvapi_QueryInterface(FunctionOffset); +} + +void nvapihook_init() +{ + hook_table_apply( + NULL, + "kernel32.dll", + nvapihook_kernel_syms, + lengthof(nvapihook_kernel_syms)); +} + +void nvapihook_fini(void) +{ + return; +} \ No newline at end of file diff --git a/src/main/sdvxhook2/nvapi.h b/src/main/sdvxhook2/nvapi.h new file mode 100644 index 0000000..523a81d --- /dev/null +++ b/src/main/sdvxhook2/nvapi.h @@ -0,0 +1,8 @@ +#ifndef NVAPIHOOK_H +#define NVAPIHOOK_H + +void nvapihook_init(); + +void nvapihook_fini(void); + +#endif diff --git a/src/main/sdvxhook2/power.c b/src/main/sdvxhook2/power.c new file mode 100644 index 0000000..f860c1b --- /dev/null +++ b/src/main/sdvxhook2/power.c @@ -0,0 +1,86 @@ +#define LOG_MODULE "power-hook" + +// clang-format off +// Don't format because the order is important here +#include +#include +// clang-format on + +#include + +#include + +#include "hook/com-proxy.h" +#include "hook/table.h" + +#include "sdvxhook2/power.h" + +#include "util/log.h" + +static DWORD +my_PowerSetActiveScheme(HKEY UserRootPowerKey, const GUID *SchemeGuid); +static DWORD my_PowerWriteACValueIndex( + HKEY RootPowerKey, + const GUID *SchemeGuid, + const GUID *SubGroupOfPowerSettingsGuid, + const GUID *PowerSettingGuid, + DWORD AcValueIndex); +static DWORD +my_PowerGetActiveScheme(HKEY UserRootPowerKey, GUID **ActivePolicyGuid); + +static DWORD (*real_PowerSetActiveScheme)( + HKEY UserRootPowerKey, const GUID *SchemeGuid); +static DWORD (*real_PowerWriteACValueIndex)( + HKEY RootPowerKey, + const GUID *SchemeGuid, + const GUID *SubGroupOfPowerSettingsGuid, + const GUID *PowerSettingGuid, + DWORD AcValueIndex); +static DWORD (*real_PowerGetActiveScheme)( + HKEY UserRootPowerKey, GUID **ActivePolicyGuid); + +static const struct hook_symbol powerhook_pp_syms[] = { + {.name = "PowerGetActiveScheme", + .patch = my_PowerGetActiveScheme, + .link = (void **) &real_PowerGetActiveScheme}, + {.name = "PowerWriteACValueIndex", + .patch = my_PowerWriteACValueIndex, + .link = (void **) &real_PowerWriteACValueIndex}, + {.name = "PowerSetActiveScheme", + .patch = my_PowerSetActiveScheme, + .link = (void **) &real_PowerSetActiveScheme}, +}; + +static DWORD +my_PowerSetActiveScheme(HKEY UserRootPowerKey, const GUID *SchemeGuid) +{ + // stubbed + return 0; +} +static DWORD my_PowerWriteACValueIndex( + HKEY RootPowerKey, + const GUID *SchemeGuid, + const GUID *SubGroupOfPowerSettingsGuid, + const GUID *PowerSettingGuid, + DWORD AcValueIndex) +{ + // stubbed + return 0; +} +static DWORD +my_PowerGetActiveScheme(HKEY UserRootPowerKey, GUID **ActivePolicyGuid) +{ + // stubbed + return 0; +} + +void powerhook_init() +{ + hook_table_apply( + NULL, "PowrProf.dll", powerhook_pp_syms, lengthof(powerhook_pp_syms)); +} + +void powerhook_fini(void) +{ + return; +} \ No newline at end of file diff --git a/src/main/sdvxhook2/power.h b/src/main/sdvxhook2/power.h new file mode 100644 index 0000000..867677e --- /dev/null +++ b/src/main/sdvxhook2/power.h @@ -0,0 +1,8 @@ +#ifndef POWERHOOK_H +#define POWERHOOK_H + +void powerhook_init(); + +void powerhook_fini(void); + +#endif diff --git a/src/main/sdvxio/sdvxio.c b/src/main/sdvxio/sdvxio.c index 3bf59a6..238f0a0 100644 --- a/src/main/sdvxio/sdvxio.c +++ b/src/main/sdvxio/sdvxio.c @@ -67,7 +67,7 @@ bool sdvx_io_read_input(void) sdvx_io_gpio[0] = (pack >> 8) & 0x00FF; sdvx_io_gpio[1] = (pack >> 16) & 0x00FF; - return 0; + return true; } uint8_t sdvx_io_get_input_gpio_sys(void)