9 Commits

21 changed files with 208 additions and 221 deletions

View 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);
}

View File

@ -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);

View File

@ -38,5 +38,7 @@ platform_lib = static_library(
'vfs.h',
'system.c',
'system.h',
'openssl.c',
'openssl.h'
],
)

116
common/platform/openssl.c Normal file
View File

@ -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;
}

12
common/platform/openssl.h Normal file
View File

@ -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);

View File

@ -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;
}

View File

@ -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(

View File

@ -17,10 +17,13 @@ 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=
inject -d -k apm3hook.dll APMV3System -screen-fullscreen 0 -screen-width 1920 -screen-height 1080 -popupWindow -logFile output_log.txt
REM Add "-screen-fullscreen 0 -popupWindow" if you want to run in windowed mode
inject -d -k apm3hook.dll APMV3System -logFile output_log.txt
if exist %tmp%\segaboot (
del %tmp%\segaboot

View File

@ -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

View File

@ -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.

View File

@ -88,18 +88,9 @@ void idac_hook_config_load(
platform_config_load(&cfg->platform, filename);
aime_config_load(&cfg->aime, filename);
idac_dll_config_load(&cfg->dll, filename);
zinput_config_load(&cfg->zinput, filename);
dvd_config_load(&cfg->dvd, filename);
io4_config_load(&cfg->io4, filename);
ffb_config_load(&cfg->ffb, filename);
led15070_config_load(&cfg->led15070, filename);
indrun_config_load(&cfg->indrun, filename);
}
void zinput_config_load(struct zinput_config *cfg, const wchar_t *filename)
{
assert(cfg != NULL);
assert(filename != NULL);
cfg->enable = GetPrivateProfileIntW(L"zinput", L"enable", 1, filename);
}

View File

@ -9,7 +9,6 @@
#include "hooklib/dvd.h"
#include "idachook/idac-dll.h"
#include "idachook/zinput.h"
#include "idachook/indrun.h"
#include "platform/platform.h"
@ -21,7 +20,6 @@ struct idac_hook_config {
struct io4_config io4;
struct ffb_config ffb;
struct idac_dll_config dll;
struct zinput_config zinput;
struct led15070_config led15070;
struct indrun_config indrun;
};
@ -34,10 +32,6 @@ void idac_hook_config_load(
struct idac_hook_config *cfg,
const wchar_t *filename);
void zinput_config_load(
struct zinput_config *cfg,
const wchar_t *filename);
void indrun_config_load(
struct indrun_config *cfg,
const wchar_t *filename);

View File

@ -31,7 +31,6 @@
#include "idachook/idac-dll.h"
#include "idachook/io4.h"
#include "idachook/ffb.h"
#include "idachook/zinput.h"
#include "platform/platform.h"
@ -55,7 +54,6 @@ static DWORD CALLBACK idac_pre_startup(void)
/* Hook Win32 APIs */
serial_hook_init();
zinput_hook_init(&idac_hook_cfg.zinput);
dvd_hook_init(&idac_hook_cfg.dvd, idac_hook_mod);
/* Initialize emulation hooks */

View File

@ -25,8 +25,6 @@ shared_library(
'idac-dll.h',
'io4.c',
'io4.h',
'zinput.c',
'zinput.h',
'indrun.c',
'indrun.h',
'ffb.c',

View File

@ -1,187 +0,0 @@
#include <windows.h>
#include <dinput.h>
#include <assert.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "idachook/config.h"
#include "idachook/zinput.h"
#include "hook/table.h"
#include "util/dprintf.h"
HRESULT WINAPI hook_DirectInput8Create(
HINSTANCE hinst,
DWORD dwVersion,
REFIID riidltf,
LPVOID *ppvOut,
LPUNKNOWN punkOuter);
static unsigned long WINAPI hook_AddRef(IUnknown *self);
static unsigned long WINAPI hook_Release(IUnknown *self);
static HRESULT WINAPI hook_CreateDevice(
IDirectInput8W *self,
REFGUID rguid,
LPDIRECTINPUTDEVICE8W * lplpDirectInputDevice,
LPUNKNOWN pUnkOuter);
static HRESULT WINAPI hook_EnumDevices(
IDirectInput8W *self,
DWORD dwDevType,
LPDIENUMDEVICESCALLBACKW lpCallback,
LPVOID pvRef,
DWORD dwFlags);
static HRESULT WINAPI hook_SetDataFormat(
IDirectInputDevice8W *self,
LPCDIDATAFORMAT lpdf);
static HRESULT WINAPI hook_SetCooperativeLevel(
IDirectInputDevice8W *self,
HWND hwnd,
DWORD flags);
static HRESULT WINAPI hook_Acquire(IDirectInputDevice8W *self);
static HRESULT WINAPI hook_Unacquire(IDirectInputDevice8W *self);
static HRESULT WINAPI hook_GetDeviceState(
IDirectInputDevice8W *self,
DWORD cbData,
LPVOID lpvData);
static const IDirectInput8WVtbl api_vtbl = {
.AddRef = (void *) hook_AddRef,
.Release = (void *) hook_Release,
.CreateDevice = hook_CreateDevice,
.EnumDevices = hook_EnumDevices,
};
static const IDirectInput8W api = { (void *) &api_vtbl };
static const IDirectInputDevice8WVtbl dev_vtbl = {
.AddRef = (void *) hook_AddRef,
.Release = (void *) hook_Release,
.SetDataFormat = hook_SetDataFormat,
.SetCooperativeLevel= hook_SetCooperativeLevel,
.Acquire = hook_Acquire,
.Unacquire = hook_Unacquire,
.GetDeviceState = hook_GetDeviceState,
};
static const IDirectInputDevice8W dev = { (void *) &dev_vtbl };
static const struct hook_symbol zinput_hook_syms[] = {
{
.name = "DirectInput8Create",
.patch = hook_DirectInput8Create,
}
};
HRESULT zinput_hook_init(struct zinput_config *cfg)
{
assert(cfg != NULL);
if (!cfg->enable) {
return S_FALSE;
}
hook_table_apply(
NULL,
"dinput8.dll",
zinput_hook_syms,
_countof(zinput_hook_syms));
return S_OK;
}
HRESULT WINAPI hook_DirectInput8Create(
HINSTANCE hinst,
DWORD dwVersion,
REFIID riidltf,
LPVOID *ppvOut,
LPUNKNOWN punkOuter)
{
dprintf("ZInput: Blocking built-in DirectInput support\n");
*ppvOut = (void *) &api;
return S_OK;
}
static unsigned long WINAPI hook_AddRef(IUnknown *self)
{
return 1;
}
static unsigned long WINAPI hook_Release(IUnknown *self)
{
return 1;
}
static HRESULT WINAPI hook_CreateDevice(
IDirectInput8W *self,
REFGUID rguid,
LPDIRECTINPUTDEVICE8W *lplpDirectInputDevice,
LPUNKNOWN pUnkOuter)
{
dprintf("ZInput: %s\n", __func__);
*lplpDirectInputDevice = (void *) &dev;
return S_OK;
}
static HRESULT WINAPI hook_EnumDevices(
IDirectInput8W *self,
DWORD dwDevType,
LPDIENUMDEVICESCALLBACKW lpCallback,
LPVOID pvRef,
DWORD dwFlags)
{
dprintf("ZInput: %s\n", __func__);
return S_OK;
}
static HRESULT WINAPI hook_SetDataFormat(
IDirectInputDevice8W *self,
LPCDIDATAFORMAT lpdf)
{
dprintf("ZInput: %s\n", __func__);
return S_OK;
}
static HRESULT WINAPI hook_SetCooperativeLevel(
IDirectInputDevice8W *self,
HWND hwnd,
DWORD flags)
{
dprintf("ZInput: %s\n", __func__);
return S_OK;
}
static HRESULT WINAPI hook_Acquire(IDirectInputDevice8W *self)
{
return S_OK;
}
static HRESULT WINAPI hook_Unacquire(IDirectInputDevice8W *self)
{
return S_OK;
}
static HRESULT WINAPI hook_GetDeviceState(
IDirectInputDevice8W *self,
DWORD cbData,
LPVOID lpvData)
{
memset(lpvData, 0, cbData);
return S_OK;
}

View File

@ -1,11 +0,0 @@
#pragma once
#include <windows.h>
#include <stdbool.h>
struct zinput_config {
bool enable;
};
HRESULT zinput_hook_init(struct zinput_config *cfg);

View File

@ -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);

View File

@ -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];

View File

@ -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;
}

View File

@ -179,7 +179,7 @@ static int16_t calculate_norm_steering(int16_t axis, uint16_t deadzone, bool lin
// optionally normalize the magnitude with respect to its expected range
// giving a magnitude value of 0.0 to 1.0
norm_magnitude = (int16_t)(magnitude / (max_stick_value - deadzone));
norm_magnitude = (magnitude / (max_stick_value - deadzone));
} else // if the controller is in the deadzone zero out the magnitude
{
magnitude = 0.0;

View File

@ -1,4 +1,4 @@
[wrap-git]
directory = capnhook
url = https://gitea.tendokyu.moe/TeamTofuShop/capnhook
revision = dafd0aa336ab80ba87a82370a9dc95a3389ef5e5
revision = 252465b23f51f36206e614190496663425f4ee5d