mirror of
https://gitea.tendokyu.moe/TeamTofuShop/segatools.git
synced 2026-10-08 09:47:54 +03:00
Merge branch 'develop'
This commit is contained in:
+140
-45
@@ -1,19 +1,16 @@
|
||||
#include <windows.h>
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <wchar.h>
|
||||
|
||||
#include <psapi.h>
|
||||
#include "hook/pe.h"
|
||||
|
||||
#include "hooklib/spike.h"
|
||||
|
||||
#include "util/dprintf.h"
|
||||
|
||||
static void spike_hook_read_config(const wchar_t *spike_file);
|
||||
|
||||
/* Spike functions. Their "style" is named after the libc function they bear
|
||||
the closest resemblance to. */
|
||||
@@ -92,37 +89,127 @@ static void spike_fn_perror(
|
||||
OutputDebugStringA(line);
|
||||
}
|
||||
|
||||
/* Spike inserters */
|
||||
|
||||
static void spike_insert_jmp(ptrdiff_t rva, void *proc)
|
||||
BOOL is_current_module_x64()
|
||||
{
|
||||
uint8_t *base;
|
||||
uint8_t *target;
|
||||
uint8_t *func_ptr;
|
||||
uint32_t delta;
|
||||
HMODULE hModule = GetModuleHandleW(NULL);
|
||||
MODULEINFO moduleInfo = {0};
|
||||
if (!GetModuleInformation(GetCurrentProcess(), hModule, &moduleInfo,
|
||||
sizeof(moduleInfo))) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
base = (uint8_t *) GetModuleHandleW(NULL);
|
||||
PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)moduleInfo.lpBaseOfDll;
|
||||
PIMAGE_NT_HEADERS ntHeaders =
|
||||
(PIMAGE_NT_HEADERS)((BYTE *)moduleInfo.lpBaseOfDll +
|
||||
dosHeader->e_lfanew);
|
||||
|
||||
target = base + rva;
|
||||
func_ptr = proc;
|
||||
delta = func_ptr - target - 4; /* -4: EIP delta, after end of target insn */
|
||||
|
||||
pe_patch(target, &delta, sizeof(delta));
|
||||
if (ntHeaders->FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64) {
|
||||
return TRUE;
|
||||
} else if (ntHeaders->FileHeader.Machine == IMAGE_FILE_MACHINE_I386) {
|
||||
return FALSE;
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static void spike_insert_ptr(ptrdiff_t rva, void *ptr)
|
||||
{
|
||||
BOOL is_valid_rva(LPCWSTR module_name, uintptr_t rva) {
|
||||
HMODULE module_base = GetModuleHandleW(module_name);
|
||||
if (!module_base) {
|
||||
return false;
|
||||
}
|
||||
PIMAGE_DOS_HEADER dos_header = (PIMAGE_DOS_HEADER)module_base;
|
||||
PIMAGE_NT_HEADERS nt_headers = (PIMAGE_NT_HEADERS)((uint8_t *)module_base + dos_header->e_lfanew);
|
||||
DWORD module_size = nt_headers->OptionalHeader.SizeOfImage;
|
||||
return (rva < module_size);
|
||||
}
|
||||
|
||||
/* Spike inserters */
|
||||
|
||||
static void spike_insert_jmp(LPCWSTR module_name, uintptr_t rva, void *proc) {
|
||||
uint8_t *base = (uint8_t *)GetModuleHandleW(module_name);
|
||||
if ( !(is_valid_rva(module_name, rva))) {
|
||||
dprintf("spike: Invalid RVA 0x%llx for module %S\n", (unsigned long long)rva, module_name);
|
||||
return;
|
||||
}
|
||||
uint8_t *target = base + rva;
|
||||
uint8_t *func_ptr = (uint8_t *)proc;
|
||||
uintptr_t target_addr = (uintptr_t)target;
|
||||
uintptr_t func_addr = (uintptr_t)func_ptr;
|
||||
|
||||
if (is_current_module_x64()) {
|
||||
uint64_t relativeOffset = (uint64_t)(func_addr - target_addr - 5);
|
||||
uint8_t absoluteJump[] = {0x48, 0xB8, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xFF, 0xE0};
|
||||
memcpy(absoluteJump + 2, &func_ptr, 8);
|
||||
pe_patch(target, absoluteJump, sizeof(absoluteJump));
|
||||
}
|
||||
else {
|
||||
uint32_t jumpOffset = (uint32_t)(func_addr - target_addr - 5);
|
||||
uint8_t relativeJump[] = {0xE9, 0x00, 0x00, 0x00, 0x00};
|
||||
memcpy(relativeJump + 1, &jumpOffset, 4);
|
||||
pe_patch(target, relativeJump, sizeof(relativeJump));
|
||||
}
|
||||
}
|
||||
|
||||
static void spike_insert_ptr(LPCWSTR module_name, uintptr_t rva, void *ptr) {
|
||||
uint8_t *base;
|
||||
uint8_t *target;
|
||||
|
||||
base = (uint8_t *) GetModuleHandleW(NULL);
|
||||
if (!(is_valid_rva(module_name, rva))) {
|
||||
dprintf("spike: Invalid RVA 0x%llx for module %S\n", (unsigned long long)rva, module_name);
|
||||
return;
|
||||
}
|
||||
base = (uint8_t *)GetModuleHandleW(module_name);
|
||||
target = base + rva;
|
||||
|
||||
pe_patch(target, &ptr, sizeof(ptr));
|
||||
}
|
||||
|
||||
static void spike_insert_log_levels(ptrdiff_t rva, size_t count)
|
||||
{
|
||||
static void spike_insert_nop(LPCWSTR module_name, uintptr_t rva, size_t count) {
|
||||
uint8_t *base;
|
||||
uint8_t *target;
|
||||
uint8_t *value;
|
||||
if (!(is_valid_rva(module_name, rva))) {
|
||||
dprintf("spike: Invalid RVA 0x%llx for module %S\n", (unsigned long long)rva, module_name);
|
||||
return;
|
||||
}
|
||||
base = (uint8_t *)GetModuleHandleW(module_name);
|
||||
target = base + rva;
|
||||
value = (uint8_t *)malloc(count);
|
||||
if (value == NULL) {
|
||||
return;
|
||||
}
|
||||
memset(value, 0x90, count);
|
||||
|
||||
HRESULT ret = pe_patch(target, value, count);
|
||||
free(value);
|
||||
}
|
||||
|
||||
static void spike_insert_data(LPCWSTR module_name, uintptr_t rva, const wchar_t *patch_str) {
|
||||
uint8_t patch_data[32];
|
||||
int length = 0;
|
||||
int byte_count = wcslen(patch_str) / 2;
|
||||
uint8_t *base;
|
||||
uint8_t *target;
|
||||
if (!(is_valid_rva(module_name, rva))) {
|
||||
dprintf("spike: Invalid RVA 0x%llx for module %S\n", (unsigned long long)rva, module_name);
|
||||
return;
|
||||
}
|
||||
base = (uint8_t *)GetModuleHandleW(module_name);
|
||||
target = base + rva;
|
||||
for (int i = 0; i < byte_count; i++) {
|
||||
unsigned int temp;
|
||||
if (swscanf(patch_str + i * 2, L"%2x", &temp) == 1) {
|
||||
patch_data[i] = (unsigned char)temp;
|
||||
length++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pe_patch(target, patch_data, length);
|
||||
}
|
||||
|
||||
static void spike_insert_log_levels(uintptr_t rva, size_t count) {
|
||||
uint8_t *base;
|
||||
uint32_t *levels;
|
||||
size_t i;
|
||||
@@ -155,7 +242,7 @@ void spike_hook_init(const wchar_t *ini_file)
|
||||
basename = slash + 1;
|
||||
} else {
|
||||
basename = module;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check our INI file to see if any spikes are configured for this EXE.
|
||||
Normally we separate out config reading into a separate module... */
|
||||
@@ -170,19 +257,19 @@ void spike_hook_init(const wchar_t *ini_file)
|
||||
|
||||
if (path[0] != L'\0') {
|
||||
dprintf("Spiking %S using config from %S\n", basename, path);
|
||||
spike_hook_read_config(path);
|
||||
spike_hook_read_config(basename, path);
|
||||
}
|
||||
}
|
||||
|
||||
static void spike_hook_read_config(const wchar_t *spike_file)
|
||||
{
|
||||
void spike_hook_read_config(const wchar_t *target, const wchar_t *spike_file) {
|
||||
int match;
|
||||
int count;
|
||||
int rva;
|
||||
char line[80];
|
||||
unsigned long long rva;
|
||||
char line[256];
|
||||
wchar_t filename[MAX_PATH];
|
||||
wchar_t patch_data[64];
|
||||
char *ret;
|
||||
FILE *f;
|
||||
|
||||
f = _wfopen(spike_file, L"r");
|
||||
|
||||
if (f == NULL) {
|
||||
@@ -202,46 +289,54 @@ static void spike_hook_read_config(const wchar_t *spike_file)
|
||||
continue;
|
||||
}
|
||||
|
||||
match = sscanf(line, "levels %i %i", &rva, &count);
|
||||
match = sscanf(line, "levels %lli %i", &rva, &count);
|
||||
|
||||
if (match == 2) {
|
||||
spike_insert_log_levels((ptrdiff_t) rva, count);
|
||||
spike_insert_log_levels((uintptr_t)rva, count);
|
||||
}
|
||||
|
||||
match = sscanf(line, "j_vprintf %i", &rva);
|
||||
match = sscanf(line, "j_vprintf %lli", &rva);
|
||||
|
||||
if (match == 1) {
|
||||
spike_insert_jmp((ptrdiff_t) rva, spike_fn_vprintf);
|
||||
spike_insert_jmp(target, (uintptr_t)rva, spike_fn_vprintf);
|
||||
}
|
||||
|
||||
match = sscanf(line, "j_vwprintf %i", &rva);
|
||||
match = sscanf(line, "j_vwprintf %lli", &rva);
|
||||
|
||||
if (match == 1) {
|
||||
spike_insert_jmp((ptrdiff_t) rva, spike_fn_vwprintf);
|
||||
spike_insert_jmp(target, (uintptr_t)rva, spike_fn_vwprintf);
|
||||
}
|
||||
|
||||
match = sscanf(line, "j_printf %i", &rva);
|
||||
match = sscanf(line, "j_printf %lli", &rva);
|
||||
|
||||
if (match == 1) {
|
||||
spike_insert_jmp((ptrdiff_t) rva, spike_fn_printf);
|
||||
spike_insert_jmp(target, (uintptr_t)rva, spike_fn_printf);
|
||||
}
|
||||
|
||||
match = sscanf(line, "j_puts %i", &rva);
|
||||
match = sscanf(line, "j_puts %lli", &rva);
|
||||
|
||||
if (match == 1) {
|
||||
spike_insert_jmp((ptrdiff_t) rva, spike_fn_puts);
|
||||
spike_insert_jmp(target, (uintptr_t)rva, spike_fn_puts);
|
||||
}
|
||||
|
||||
match = sscanf(line, "j_perror %i", &rva);
|
||||
match = sscanf(line, "j_perror %lli", &rva);
|
||||
|
||||
if (match == 1) {
|
||||
spike_insert_jmp((ptrdiff_t) rva, spike_fn_perror);
|
||||
spike_insert_jmp(target, (uintptr_t)rva, spike_fn_perror);
|
||||
}
|
||||
|
||||
match = sscanf(line, "c_fputs %i", &rva); /* c == "callback" */
|
||||
match = sscanf(line, "c_fputs %lli", &rva); /* c == "callback" */
|
||||
|
||||
if (match == 1) {
|
||||
spike_insert_ptr((ptrdiff_t) rva, spike_fn_fputs);
|
||||
spike_insert_ptr(target, (uintptr_t)rva, spike_fn_fputs);
|
||||
}
|
||||
match = sscanf(line, "patch_memory_nop %255ls %lli %i", filename, &rva, &count);
|
||||
if (match == 3 && (_wcsicmp(filename, target) == 0)) {
|
||||
spike_insert_nop((LPCWSTR)filename, (uintptr_t)rva, count);
|
||||
}
|
||||
match = sscanf(line, "patch_memory_data %255ls %lli %64ls", filename, &rva, patch_data);
|
||||
if (match == 3 && (_wcsicmp(filename, target) == 0)) {
|
||||
spike_insert_data((LPCWSTR)filename, (uintptr_t)rva, patch_data);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,3 +3,4 @@
|
||||
#include <stddef.h>
|
||||
|
||||
void spike_hook_init(const wchar_t *ini_file);
|
||||
void spike_hook_read_config(const wchar_t *target, const wchar_t *spike_file);
|
||||
|
||||
@@ -23,6 +23,8 @@
|
||||
#include "platform/platform.h"
|
||||
#include "platform/vfs.h"
|
||||
#include "platform/system.h"
|
||||
#include "platform/openssl.h"
|
||||
|
||||
|
||||
void platform_config_load(struct platform_config *cfg, const wchar_t *filename)
|
||||
{
|
||||
@@ -41,6 +43,7 @@ void platform_config_load(struct platform_config *cfg, const wchar_t *filename)
|
||||
nusec_config_load(&cfg->nusec, filename);
|
||||
vfs_config_load(&cfg->vfs, filename);
|
||||
system_config_load(&cfg->system, filename);
|
||||
openssl_config_load(&cfg->openssl, filename);
|
||||
}
|
||||
|
||||
void amvideo_config_load(struct amvideo_config *cfg, const wchar_t *filename)
|
||||
@@ -362,3 +365,12 @@ void epay_config_load(struct epay_config *cfg, const wchar_t *filename)
|
||||
cfg->enable = GetPrivateProfileIntW(L"epay", L"enable", 1, filename);
|
||||
cfg->hook = GetPrivateProfileIntW(L"epay", L"hook", 1, filename);
|
||||
}
|
||||
|
||||
void openssl_config_load(struct openssl_config *cfg, const wchar_t *filename)
|
||||
{
|
||||
assert(cfg != NULL);
|
||||
assert(filename != NULL);
|
||||
|
||||
cfg->enable = GetPrivateProfileIntW(L"openssl", L"enable", 1, filename);
|
||||
cfg->override = GetPrivateProfileIntW(L"openssl", L"override", 0, filename);
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "platform/platform.h"
|
||||
#include "platform/vfs.h"
|
||||
#include "platform/system.h"
|
||||
#include "platform/openssl.h"
|
||||
|
||||
void platform_config_load(
|
||||
struct platform_config *cfg,
|
||||
@@ -36,3 +37,4 @@ void nusec_config_load(struct nusec_config *cfg, const wchar_t *filename);
|
||||
void pcbid_config_load(struct pcbid_config *cfg, const wchar_t *filename);
|
||||
void vfs_config_load(struct vfs_config *cfg, const wchar_t *filename);
|
||||
void system_config_load(struct system_config *cfg, const wchar_t *filename);
|
||||
void openssl_config_load(struct openssl_config *cfg, const wchar_t *filename);
|
||||
|
||||
@@ -38,5 +38,7 @@ platform_lib = static_library(
|
||||
'vfs.h',
|
||||
'system.c',
|
||||
'system.h',
|
||||
'openssl.c',
|
||||
'openssl.h'
|
||||
],
|
||||
)
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
#include <windows.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <intrin.h>
|
||||
|
||||
#include "hook/table.h"
|
||||
|
||||
#include "hooklib/config.h"
|
||||
|
||||
#include "platform/openssl.h"
|
||||
|
||||
#include "util/dprintf.h"
|
||||
|
||||
/* API hooks */
|
||||
|
||||
static char * __cdecl hook_getenv(const char *name);
|
||||
|
||||
/* Link pointers */
|
||||
|
||||
static char * (__cdecl *next_getenv)(const char *name);
|
||||
|
||||
static bool openssl_hook_initted;
|
||||
static struct openssl_config openssl_config;
|
||||
|
||||
static const struct hook_symbol openssl_hooks[] = {
|
||||
{
|
||||
.name = "getenv",
|
||||
.patch = hook_getenv,
|
||||
.link = (void **) &next_getenv
|
||||
},
|
||||
};
|
||||
|
||||
static int check_intel_sha_extension() {
|
||||
int n_ids;
|
||||
int is_intel;
|
||||
char vendor[0x20] = {0};
|
||||
int cpui[4] = {0};
|
||||
|
||||
/* OpenSSL 1.0.2 beta to 1.0.2k contain bugs that crash "AM Daemon" due to
|
||||
bad SHA values on processors with the SHA extensions, such as Intel 10th
|
||||
gen CPUs or higher.
|
||||
|
||||
Credits: kagaminehaku */
|
||||
|
||||
__cpuid(cpui, 0);
|
||||
n_ids = cpui[0];
|
||||
|
||||
*((int *) vendor) = cpui[1];
|
||||
*((int *) (vendor + 4)) = cpui[3];
|
||||
*((int *) (vendor + 8)) = cpui[2];
|
||||
|
||||
/* Check that the CPU vendor is Intel */
|
||||
is_intel = (strcmp(vendor, "GenuineIntel") == 0);
|
||||
|
||||
if (is_intel && n_ids >= 7) {
|
||||
__cpuidex(cpui, 7, 0);
|
||||
|
||||
/* SHA extensions supported */
|
||||
return (cpui[1] & (1 << 29)) != 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
HRESULT openssl_hook_init(const struct openssl_config *cfg)
|
||||
{
|
||||
assert(cfg != NULL);
|
||||
|
||||
if (!cfg->enable) {
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
if (openssl_hook_initted) {
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
if (cfg->override) {
|
||||
dprintf("OpenSSL: hook enabled.\n");
|
||||
} else if (check_intel_sha_extension()) {
|
||||
dprintf("OpenSSL: Intel CPU SHA extension detected, hook enabled.\n");
|
||||
} else {
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
openssl_hook_initted = true;
|
||||
|
||||
memcpy(&openssl_config, cfg, sizeof(*cfg));
|
||||
hook_table_apply(
|
||||
NULL,
|
||||
"msvcr110.dll",
|
||||
openssl_hooks,
|
||||
_countof(openssl_hooks)
|
||||
);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static char * __cdecl hook_getenv(const char *name)
|
||||
{
|
||||
/* Overrides OpenSSL's Intel CPU identification. This disables the OpenSSL
|
||||
code check for SHA extensions. */
|
||||
if (name && strcmp(name, "OPENSSL_ia32cap") == 0) {
|
||||
static char override[] = "~0x20000000";
|
||||
|
||||
dprintf("OpenSSL: Overriding OPENSSL_ia32cap -> %s\n", override);
|
||||
|
||||
return override;
|
||||
}
|
||||
|
||||
char *real_val = next_getenv(name);
|
||||
|
||||
return real_val;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
struct openssl_config {
|
||||
bool enable;
|
||||
bool override;
|
||||
};
|
||||
|
||||
HRESULT openssl_hook_init(const struct openssl_config *cfg);
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "platform/platform.h"
|
||||
#include "platform/vfs.h"
|
||||
#include "platform/system.h"
|
||||
#include "platform/openssl.h"
|
||||
|
||||
HRESULT platform_hook_init(
|
||||
const struct platform_config *cfg,
|
||||
@@ -94,5 +95,11 @@ HRESULT platform_hook_init(
|
||||
return hr;
|
||||
}
|
||||
|
||||
hr = openssl_hook_init(&cfg->openssl);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "platform/pcbid.h"
|
||||
#include "platform/vfs.h"
|
||||
#include "platform/system.h"
|
||||
#include "platform/openssl.h"
|
||||
|
||||
struct platform_config {
|
||||
struct amvideo_config amvideo;
|
||||
@@ -28,6 +29,7 @@ struct platform_config {
|
||||
struct nusec_config nusec;
|
||||
struct vfs_config vfs;
|
||||
struct system_config system;
|
||||
struct openssl_config openssl;
|
||||
};
|
||||
|
||||
HRESULT platform_hook_init(
|
||||
|
||||
Vendored
+2
@@ -17,8 +17,10 @@ if exist %tmp%\SequenceSetting.json (
|
||||
:BEGIN
|
||||
pushd %~dp0
|
||||
|
||||
set DOORSTOP_DISABLE=TRUE
|
||||
qprocess amdaemon.exe > NUL
|
||||
IF %ERRORLEVEL% NEQ 0 start /min "AM Daemon" inject -d -k apm3hook.dll amdaemon.exe -c daemon_config\common.json daemon_config\server.json config_hook.json
|
||||
set DOORSTOP_DISABLE=
|
||||
|
||||
REM Add "-screen-fullscreen 0 -popupWindow" if you want to run in windowed mode
|
||||
inject -d -k apm3hook.dll APMV3System -logFile output_log.txt
|
||||
|
||||
Vendored
+3
@@ -235,6 +235,9 @@ viewChg=2
|
||||
; This is not possible on most devices, so we set the left and right button again.
|
||||
left=7
|
||||
right=8
|
||||
; Additional mapping for up and down buttons in DPad.
|
||||
up=4
|
||||
down=3
|
||||
; Button mappings for the simulated six-speed shifter.
|
||||
shiftDn=6
|
||||
shiftUp=5
|
||||
|
||||
+18
-1
@@ -663,4 +663,21 @@ Enables the Thinca emulation. This will allow you to enable E-Money on compatibl
|
||||
|
||||
Default: `1`
|
||||
|
||||
Enables hooking of respective Thinca DLL functions to emulate the existence of E-Money. This cannot be used with a real E-Money server.
|
||||
Enables hooking of respective Thinca DLL functions to emulate the existence of E-Money. This cannot be used with a real E-Money server.
|
||||
|
||||
## `[openssl]`
|
||||
|
||||
Configure the OpenSSL SHA extension bug hook.
|
||||
|
||||
### `enable`
|
||||
|
||||
Default: `1`
|
||||
|
||||
Enables the OpenSSL hook to fix the SHA extension bug on Intel CPUs.
|
||||
|
||||
### `override`
|
||||
|
||||
Default: `0`
|
||||
|
||||
Enables the override to always hook the OpenSSL env variable. By default the
|
||||
hook is only applied to Intel CPUs with the SHA extension present.
|
||||
|
||||
@@ -76,6 +76,13 @@ void indrun_config_load(
|
||||
assert(filename != NULL);
|
||||
|
||||
cfg->enable = GetPrivateProfileIntW(L"indrun", L"enable", 1, filename);
|
||||
GetPrivateProfileStringW(
|
||||
L"indrun",
|
||||
L"spike",
|
||||
L"",
|
||||
cfg->patch_file,
|
||||
_countof(cfg->patch_file),
|
||||
filename);
|
||||
}
|
||||
|
||||
void idac_hook_config_load(
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "hook/table.h"
|
||||
|
||||
@@ -9,11 +10,14 @@
|
||||
#include "util/dprintf.h"
|
||||
|
||||
#include "indrun.h"
|
||||
#include "hooklib/spike.h"
|
||||
|
||||
static const wchar_t *target_modules[] = {
|
||||
L"IndRun.dll",
|
||||
};
|
||||
|
||||
static wchar_t spike_file[MAX_PATH] = L"";
|
||||
|
||||
static const size_t target_modules_len = _countof(target_modules);
|
||||
|
||||
static void dll_hook_insert_hooks(HMODULE target);
|
||||
@@ -88,11 +92,17 @@ static const struct hook_symbol indrun_kernel32_syms[] = {
|
||||
void indrun_hook_init(struct indrun_config *cfg)
|
||||
{
|
||||
assert(cfg != NULL);
|
||||
wchar_t full_path[MAX_PATH];
|
||||
|
||||
if (!cfg->enable) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (wcscmp(cfg->patch_file, L"") != 0) {
|
||||
GetCurrentDirectoryW(MAX_PATH, full_path);
|
||||
swprintf_s(spike_file, MAX_PATH, L"%ls\\%ls", full_path, cfg->patch_file);
|
||||
}
|
||||
|
||||
dprintf("IDAC: Hooks enabled.\n");
|
||||
|
||||
// GameProject-Win64-Shipping.exe hooks
|
||||
@@ -176,6 +186,10 @@ static HMODULE WINAPI hook_LoadLibraryW(const wchar_t *name)
|
||||
|
||||
dll_hook_insert_hooks(result);
|
||||
app_hook_insert_hooks(result);
|
||||
|
||||
if (wcscmp(spike_file, L"") != 0) {
|
||||
spike_hook_read_config(target_module, spike_file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
struct indrun_config {
|
||||
bool enable;
|
||||
wchar_t patch_file[MAX_PATH];
|
||||
};
|
||||
|
||||
void indrun_hook_init(struct indrun_config *cfg);
|
||||
|
||||
@@ -60,6 +60,8 @@ void idac_di_config_load(struct idac_di_config *cfg, const wchar_t *filename)
|
||||
cfg->view_chg = GetPrivateProfileIntW(L"dinput", L"viewChg", 0, filename);
|
||||
cfg->left = GetPrivateProfileIntW(L"dinput", L"left", 0, filename);
|
||||
cfg->right = GetPrivateProfileIntW(L"dinput", L"right", 0, filename);
|
||||
cfg->up = GetPrivateProfileIntW(L"dinput", L"up", 0, filename);
|
||||
cfg->down = GetPrivateProfileIntW(L"dinput", L"down", 0, filename);
|
||||
cfg->shift_dn = GetPrivateProfileIntW(L"dinput", L"shiftDn", 0, filename);
|
||||
cfg->shift_up = GetPrivateProfileIntW(L"dinput", L"shiftUp", 0, filename);
|
||||
|
||||
|
||||
@@ -18,6 +18,8 @@ struct idac_di_config {
|
||||
uint8_t view_chg;
|
||||
uint8_t left;
|
||||
uint8_t right;
|
||||
uint8_t up;
|
||||
uint8_t down;
|
||||
uint8_t shift_dn;
|
||||
uint8_t shift_up;
|
||||
uint8_t gear[6];
|
||||
|
||||
@@ -71,6 +71,8 @@ static uint8_t idac_di_view_chg;
|
||||
static uint8_t idac_di_start;
|
||||
static uint8_t idac_di_left;
|
||||
static uint8_t idac_di_right;
|
||||
static uint8_t idac_di_up;
|
||||
static uint8_t idac_di_down;
|
||||
static uint8_t idac_di_gear[6];
|
||||
static bool idac_di_use_pedals;
|
||||
static bool idac_di_reverse_brake_axis;
|
||||
@@ -247,6 +249,16 @@ static HRESULT idac_di_config_apply(const struct idac_di_config *cfg)
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
if (cfg->up > 32) {
|
||||
dprintf("Wheel: Invalid up button: %i\n", cfg->up);
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
if (cfg->down > 32) {
|
||||
dprintf("Wheel: Invalid down button: %i\n", cfg->down);
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
if (cfg->shift_dn > 32) {
|
||||
dprintf("Wheel: Invalid shift down button: %i\n", cfg->shift_dn);
|
||||
|
||||
@@ -282,6 +294,8 @@ static HRESULT idac_di_config_apply(const struct idac_di_config *cfg)
|
||||
dprintf("Wheel: View Change button : %i\n", cfg->view_chg);
|
||||
dprintf("Wheel: Left button . . . . : %i\n", cfg->left);
|
||||
dprintf("Wheel: Right button . . . : %i\n", cfg->right);
|
||||
dprintf("Wheel: Up button . . . . . : %i\n", cfg->up);
|
||||
dprintf("Wheel: Down button . . . : %i\n", cfg->down);
|
||||
dprintf("Wheel: Shift Down button . : %i\n", cfg->shift_dn);
|
||||
dprintf("Wheel: Shift Up button . . : %i\n", cfg->shift_up);
|
||||
dprintf("Wheel: Reverse Brake Axis : %i\n", cfg->reverse_brake_axis);
|
||||
@@ -317,6 +331,8 @@ static HRESULT idac_di_config_apply(const struct idac_di_config *cfg)
|
||||
idac_di_view_chg = cfg->view_chg;
|
||||
idac_di_left = cfg->left;
|
||||
idac_di_right = cfg->right;
|
||||
idac_di_up = cfg->up;
|
||||
idac_di_down = cfg->down;
|
||||
idac_di_shift_dn = cfg->shift_dn;
|
||||
idac_di_shift_up = cfg->shift_up;
|
||||
idac_di_reverse_brake_axis = cfg->reverse_brake_axis;
|
||||
@@ -480,6 +496,14 @@ static void idac_di_get_buttons(uint8_t *gamebtn_out)
|
||||
gamebtn |= IDAC_IO_GAMEBTN_RIGHT;
|
||||
}
|
||||
|
||||
if (idac_di_up && state.st.rgbButtons[idac_di_up - 1]) {
|
||||
gamebtn |= IDAC_IO_GAMEBTN_UP;
|
||||
}
|
||||
|
||||
if (idac_di_down && state.st.rgbButtons[idac_di_down - 1]) {
|
||||
gamebtn |= IDAC_IO_GAMEBTN_DOWN;
|
||||
}
|
||||
|
||||
*gamebtn_out = gamebtn;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
[wrap-git]
|
||||
directory = capnhook
|
||||
url = https://gitea.tendokyu.moe/TeamTofuShop/capnhook
|
||||
revision = dafd0aa336ab80ba87a82370a9dc95a3389ef5e5
|
||||
revision = 252465b23f51f36206e614190496663425f4ee5d
|
||||
|
||||
Reference in New Issue
Block a user