Changes for 1.4.2

This commit is contained in:
rebtd7 2020-02-01 17:03:46 -03:00 committed by GitHub
parent 98ed61b776
commit 1c131f5038
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 346 additions and 313 deletions

View file

@ -23,6 +23,14 @@ FFXIIIIngameFrameRateLimit = 0
# Enables controller vibration on the first connected XInput device.
FFXIIIEnableControllerVibration = true
# FFXIIIDisableIngameControllerHotSwapping
#
# By default FF13Fix disables the game's continuous controller scanning that causes stuttering (especially if you do not have any controller connected)
# If you with you can enable it again (by setting the config to 'false', so you can re-connect your controller while playing.
# Note that FFXIIIEnableControllerVibration is incompatible with the controller hotswapping,
# so it is automatically disabled if FFXIIIDisableIngameControllerHotSwapping is set to 'false'
FFXIIIDisableIngameControllerHotSwapping = true
# FullScreenRefreshRate
#
# If you are not using any adaptive sync technology (e.g. FreeSync/Gsync) you may want to set this to the highest

View file

@ -106,14 +106,14 @@ HRESULT APIENTRY MainContext::ApplyVertexBufferFix(IDirect3DDevice9* pIDirect3DD
void MainContext::FF13_InitializeGameAddresses()
{
// FF13 always seem to use the same addresses (even if you force ASLR on the OS), but we are calculating the addresses just in case...
byte* baseAddr = (byte*)GetModuleHandle(NULL); // Should be 400000
uint8_t* baseAddr = (uint8_t*)GetModuleHandle(NULL); // Should be 400000
PrintLog("Base Addr = %x", baseAddr);
ff13_frame_pacer_ptr = (float**)(baseAddr + 0x243E34C);
ff13_set_framerate_ingame_instruction_address = baseAddr + 0xA8D65F;
ff13_continuous_scan_instruction_address = baseAddr + 0x420868;
ff13_enemy_scan_box_code_address = baseAddr + 0x54C920;
ff13_base_controller_input_address_ptr = (byte**)(baseAddr + 0x02411220);
ff13_base_controller_input_address_ptr = (uint8_t**)(baseAddr + 0x02411220);
ff13_vibration_low_set_zero_address = baseAddr + 0x4210DF;
ff13_vibration_high_set_zero_address = baseAddr + 0x4210F3;
ff13_internal_res_w = (uint32_t*)(baseAddr + 0x22E5168);
@ -137,6 +137,10 @@ void MainContext::FF13_EnableControllerVibration()
PrintLog("Vibration should not be enabled (config file)");
return;
}
if (!config.GetFFXIIIDisableIngameControllerHotSwapping()) {
PrintLog("Vibration disabled because FFXIIIDisableIngameControllerHotSwapping is set to false (config file)");
return;
}
PrintLog("Enabling controller vibration...");
ChangeMemoryProtectionToReadWriteExecute(ff13_vibration_low_set_zero_address, 5);
@ -156,12 +160,16 @@ void MainContext::FF13_EnableControllerVibration()
}
void MainContext::FF13_RemoveContinuousControllerScan() {
if (!config.GetFFXIIIDisableIngameControllerHotSwapping()) {
PrintLog("Continuous controller scanning not disabled (config)");
return;
}
// Disable continuous controller scanning.
PrintLog("Removing game slow and synchronous controller continuous controller scanning...");
context.ChangeMemoryProtectionToReadWriteExecute(ff13_continuous_scan_instruction_address, 1);
// change a jne to jmp
*(byte*)ff13_continuous_scan_instruction_address = 0xEB;
*(uint8_t*)ff13_continuous_scan_instruction_address = 0xEB;
}
void MainContext::FF13_FixMissingEnemyScan() {
@ -179,21 +187,21 @@ void MainContext::FF13_FixMissingEnemyScan() {
context.ChangeMemoryProtectionToReadWriteExecute(ff13_enemy_scan_box_code_address, 18);
//push rectHeight
*(byte*)(ff13_enemy_scan_box_code_address + 0) = 0x68;
*(uint8_t*)(ff13_enemy_scan_box_code_address + 0) = 0x68;
*(uint32_t*)(ff13_enemy_scan_box_code_address + 1) = rectHeight;
// push rectWidth
*(byte*)(ff13_enemy_scan_box_code_address + 5) = 0x68;
*(uint8_t*)(ff13_enemy_scan_box_code_address + 5) = 0x68;
*(uint32_t*)(ff13_enemy_scan_box_code_address + 6) = rectWidth;
// push rectPosY
*(byte*)(ff13_enemy_scan_box_code_address + 10) = 0x68;
*(uint8_t*)(ff13_enemy_scan_box_code_address + 10) = 0x68;
*(uint32_t*)(ff13_enemy_scan_box_code_address + 11) = rectPosY;
// NOP NOP NOP
*(byte*)(ff13_enemy_scan_box_code_address + 15) = 0x90;
*(byte*)(ff13_enemy_scan_box_code_address + 16) = 0x90;
*(byte*)(ff13_enemy_scan_box_code_address + 17) = 0x90;
*(uint8_t*)(ff13_enemy_scan_box_code_address + 15) = 0x90;
*(uint8_t*)(ff13_enemy_scan_box_code_address + 16) = 0x90;
*(uint8_t*)(ff13_enemy_scan_box_code_address + 17) = 0x90;
}
void MainContext::FF13_NOPIngameFrameRateLimitSetter() {
@ -284,24 +292,28 @@ void MainContext::FF13_2_EnableControllerVibration()
void MainContext::FF13_2_InitializeGameAddresses()
{
// FF13-2 uses address space layout randomization (ASLR) so we can't rely on fixed addresses without considering the base address
byte* baseAddr = (byte*)GetModuleHandle(NULL);
uint8_t* baseAddr = (uint8_t*)GetModuleHandle(NULL);
PrintLog("Base Addr = %x", baseAddr);
ff13_2_continuous_scan_instruction_address = baseAddr + 0x2A6E7F;
ff13_2_set_frame_rate_address = baseAddr + 0x802616;
ff13_2_frame_pacer_ptr_address = (float**)(baseAddr + 0x4D67208);
ff13_2_base_controller_input_address_ptr = (byte**)(baseAddr + 0x212A164);
ff13_2_base_controller_input_address_ptr = (uint8_t**)(baseAddr + 0x212A164);
ff13_2_vibration_low_set_zero_address = baseAddr + 0x2A7221;
ff13_2_vibration_high_set_zero_address = baseAddr + 0x2A7226;
}
void MainContext::FF13_2_RemoveContinuousControllerScan() {
if (!config.GetFFXIIIDisableIngameControllerHotSwapping()) {
PrintLog("Continuous controller scanning not disabled (config)");
return;
}
// Disable continuous controller scanning.
PrintLog("Removing game slow and synchronous controller continuous controller scanning...");
context.ChangeMemoryProtectionToReadWriteExecute(ff13_2_continuous_scan_instruction_address, 1);
// change a jne to jmp
*(byte*)ff13_2_continuous_scan_instruction_address = 0xEB;
*(uint8_t*)ff13_2_continuous_scan_instruction_address = 0xEB;
}
void MainContext::FF13_2_AddHookIngameFrameRateLimitSetter() {
@ -322,7 +334,7 @@ void MainContext::FF13_2_AddHookIngameFrameRateLimitSetter() {
void MainContext::FF13_2_CreateSetFrameRateCodeBlock()
{
const int blockSize = 31;
FF13_2_SET_FRAME_RATE_INJECTED_CODE = new byte[blockSize];
FF13_2_SET_FRAME_RATE_INJECTED_CODE = new uint8_t[blockSize];
ChangeMemoryProtectionToReadWriteExecute(FF13_2_SET_FRAME_RATE_INJECTED_CODE, blockSize);
@ -377,7 +389,7 @@ void MainContext::ChangeMemoryProtectionToReadWriteExecute(void* address, const
}
void MainContext::PrintVersionInfo() {
PrintLog("FF13Fix 1.4.1 https://github.com/rebtd7/FF13Fix");
PrintLog("FF13Fix 1.4.2 https://github.com/rebtd7/FF13Fix");
}
bool MainContext::AreAlmostTheSame(float a, float b) {

View file

@ -46,22 +46,34 @@ MainContext::MainContext() : oldWndProc(nullptr)
if (config.GetAutoFix()) EnableAutoFix();
MH_Initialize();
PrintLog("Enabling hooks:");
const MH_STATUS initializeHooks = MH_Initialize();
PrintLog("initializeHooks = %d", initializeHooks);
MH_CreateHook(D3D9DLL::Get().Direct3DCreate9, HookDirect3DCreate9, reinterpret_cast<void**>(&TrueDirect3DCreate9));
MH_EnableHook(D3D9DLL::Get().Direct3DCreate9);
const MH_STATUS createHookDirect3DCreate9 = MH_CreateHook(D3D9DLL::Get().Direct3DCreate9, HookDirect3DCreate9, reinterpret_cast<void**>(&TrueDirect3DCreate9));
PrintLog("createHookDirect3DCreate9 = %d", createHookDirect3DCreate9);
const MH_STATUS enableHookDirect3DCreate9 = MH_EnableHook(D3D9DLL::Get().Direct3DCreate9);
PrintLog("enableHookDirect3DCreate9 = %d", enableHookDirect3DCreate9);
MH_CreateHook(CreateWindowExA, HookCreateWindowExA, reinterpret_cast<void**>(&TrueCreateWindowExA));
MH_EnableHook(CreateWindowExA);
const MH_STATUS createHookCreateWindowExA = MH_CreateHook(CreateWindowExA, HookCreateWindowExA, reinterpret_cast<void**>(&TrueCreateWindowExA));
PrintLog("createHookCreateWindowExA = %d", createHookCreateWindowExA);
const MH_STATUS enableHookCreateWindowExA = MH_EnableHook(CreateWindowExA);
PrintLog("enableHookCreateWindowExA = %d", enableHookCreateWindowExA);
MH_CreateHook(CreateWindowExW, HookCreateWindowExW, reinterpret_cast<void**>(&TrueCreateWindowExW));
MH_EnableHook(CreateWindowExW);
const MH_STATUS createHookCreateWindowExW = MH_CreateHook(CreateWindowExW, HookCreateWindowExW, reinterpret_cast<void**>(&TrueCreateWindowExW));
PrintLog("createHookCreateWindowExW = %d", createHookCreateWindowExW);
const MH_STATUS enableHookCreateWindowExW = MH_EnableHook(CreateWindowExW);
PrintLog("enableHookCreateWindowExW = %d", enableHookCreateWindowExW);
MH_CreateHook(SetWindowLongA, HookSetWindowLongA, reinterpret_cast<void**>(&TrueSetWindowLongA));
MH_EnableHook(SetWindowLongA);
const MH_STATUS createHookSetWindowLongA = MH_CreateHook(SetWindowLongA, HookSetWindowLongA, reinterpret_cast<void**>(&TrueSetWindowLongA));
PrintLog("createHookSetWindowLongA = %d", createHookSetWindowLongA);
const MH_STATUS enableHookSetWindowLongA = MH_EnableHook(SetWindowLongA);
PrintLog("enableHookSetWindowLongA = %d", enableHookSetWindowLongA);
MH_CreateHook(SetWindowLongW, HookSetWindowLongW, reinterpret_cast<void**>(&TrueSetWindowLongW));
MH_EnableHook(SetWindowLongW);
const MH_STATUS createHookSetWindowLongW = MH_CreateHook(SetWindowLongW, HookSetWindowLongW, reinterpret_cast<void**>(&TrueSetWindowLongW));
PrintLog("createHookSetWindowLongW = %d", createHookSetWindowLongW);
const MH_STATUS enableHookSetWindowLongW = MH_EnableHook(SetWindowLongW);
PrintLog("enableHookSetWindowLongW = %d", enableHookSetWindowLongW);
}

View file

@ -79,23 +79,23 @@ private:
const float MAX_FRAME_RATE_LIMIT = 250000.0F;
float** ff13_frame_pacer_ptr = NULL;
byte* ff13_set_framerate_ingame_instruction_address = NULL;
byte* ff13_continuous_scan_instruction_address = NULL;
byte* ff13_enemy_scan_box_code_address = NULL;
byte** ff13_base_controller_input_address_ptr = NULL;
byte* ff13_vibration_high_set_zero_address = NULL;
byte* ff13_vibration_low_set_zero_address = NULL;
uint8_t* ff13_set_framerate_ingame_instruction_address = NULL;
uint8_t* ff13_continuous_scan_instruction_address = NULL;
uint8_t* ff13_enemy_scan_box_code_address = NULL;
uint8_t** ff13_base_controller_input_address_ptr = NULL;
uint8_t* ff13_vibration_high_set_zero_address = NULL;
uint8_t* ff13_vibration_low_set_zero_address = NULL;
uint32_t* ff13_internal_res_w;
uint32_t* ff13_internal_res_h;
byte* FF13_2_SET_FRAME_RATE_INJECTED_CODE = NULL;
byte* ff13_2_continuous_scan_instruction_address;
byte* ff13_2_set_frame_rate_address;
uint8_t* FF13_2_SET_FRAME_RATE_INJECTED_CODE = NULL;
uint8_t* ff13_2_continuous_scan_instruction_address;
uint8_t* ff13_2_set_frame_rate_address;
float** ff13_2_frame_pacer_ptr_address;
float ff13_2_targetFrameRate;
byte** ff13_2_base_controller_input_address_ptr = NULL;
byte* ff13_2_vibration_high_set_zero_address = NULL;
byte* ff13_2_vibration_low_set_zero_address = NULL;
uint8_t** ff13_2_base_controller_input_address_ptr = NULL;
uint8_t* ff13_2_vibration_high_set_zero_address = NULL;
uint8_t* ff13_2_vibration_low_set_zero_address = NULL;
const float FF13_2_30_FPS = 30.0F;
const float FF13_2_MAX_FRAME_CAP = 1000.0F;

View file

@ -101,7 +101,7 @@ HRESULT APIENTRY hkIDirect3DDevice9::GetSwapChain(UINT iSwapChain, IDirect3DSwap
IDirect3DDevice9_PrintLog(__FUNCTION__);
// Steam Overlay Fix
// Add some space, 16bytes should be enough
// Add some space, 16uint8_ts should be enough
__nop();
__nop();
__nop();
@ -549,14 +549,14 @@ HRESULT APIENTRY hkIDirect3DDevice9::GetVertexShaderConstantB(UINT StartRegister
return m_pWrapped->GetVertexShaderConstantB(StartRegister, pConstantData, BoolCount);
}
HRESULT APIENTRY hkIDirect3DDevice9::SetStreamSource(UINT StreamNumber, IDirect3DVertexBuffer9* pStreamData, UINT OffsetInBytes, UINT Stride) {
HRESULT APIENTRY hkIDirect3DDevice9::SetStreamSource(UINT StreamNumber, IDirect3DVertexBuffer9* pStreamData, UINT OffsetInuint8_ts, UINT Stride) {
IDirect3DDevice9_PrintLog(__FUNCTION__);
return m_pWrapped->SetStreamSource(StreamNumber, pStreamData, OffsetInBytes, Stride);
return m_pWrapped->SetStreamSource(StreamNumber, pStreamData, OffsetInuint8_ts, Stride);
}
HRESULT APIENTRY hkIDirect3DDevice9::GetStreamSource(UINT StreamNumber, IDirect3DVertexBuffer9** ppStreamData, UINT* pOffsetInBytes, UINT* pStride) {
HRESULT APIENTRY hkIDirect3DDevice9::GetStreamSource(UINT StreamNumber, IDirect3DVertexBuffer9** ppStreamData, UINT* pOffsetInuint8_ts, UINT* pStride) {
IDirect3DDevice9_PrintLog(__FUNCTION__);
return m_pWrapped->GetStreamSource(StreamNumber, ppStreamData, pOffsetInBytes, pStride);
return m_pWrapped->GetStreamSource(StreamNumber, ppStreamData, pOffsetInuint8_ts, pStride);
}
HRESULT APIENTRY hkIDirect3DDevice9::SetStreamSourceFreq(UINT StreamNumber, UINT Setting) {

View file

@ -107,8 +107,8 @@ public:
STDMETHOD(GetVertexShaderConstantI)(UINT StartRegister, int* pConstantData, UINT Vector4iCount);
STDMETHOD(SetVertexShaderConstantB)(UINT StartRegister, CONST BOOL* pConstantData, UINT BoolCount);
STDMETHOD(GetVertexShaderConstantB)(UINT StartRegister, BOOL* pConstantData, UINT BoolCount);
STDMETHOD(SetStreamSource)(UINT StreamNumber, IDirect3DVertexBuffer9* pStreamData, UINT OffsetInBytes, UINT Stride);
STDMETHOD(GetStreamSource)(UINT StreamNumber, IDirect3DVertexBuffer9** ppStreamData, UINT* pOffsetInBytes, UINT* pStride);
STDMETHOD(SetStreamSource)(UINT StreamNumber, IDirect3DVertexBuffer9* pStreamData, UINT OffsetInuint8_ts, UINT Stride);
STDMETHOD(GetStreamSource)(UINT StreamNumber, IDirect3DVertexBuffer9** ppStreamData, UINT* pOffsetInuint8_ts, UINT* pStride);
STDMETHOD(SetStreamSourceFreq)(UINT StreamNumber, UINT Setting);
STDMETHOD(GetStreamSourceFreq)(UINT StreamNumber, UINT* pSetting);
STDMETHOD(SetIndices)(IDirect3DIndexBuffer9* pIndexData);

View file

@ -11,8 +11,10 @@ SETTING(bool, BoolValue, ForceHideCursor, Options, false);
SETTING(u32, LongValue, BehaviorFlags, Options, 0);
SETTING(double, DoubleValue, FFXIIIIngameFrameRateLimit, Options, 0.0);
SETTING(bool, BoolValue, FFXIIIDisableIngameControllerHotSwapping, Options, true);
SETTING(bool, BoolValue, FFXIIIEnableControllerVibration, Options, true);
SETTING(bool, BoolValue, Adapter, Adapter, false);
SETTING(u32, LongValue, VendorId, Adapter, 0);
SETTING(u32, LongValue, DeviceId, Adapter, 0);

View file

@ -1,260 +1,260 @@
#pragma once
#include "comdef.h"
#include "d3d9.h"
#include "dinput.h"
#include "xinput.h"
template <class T>
class WrapperBase
{
public:
WrapperBase(const WrapperBase&) = delete;
const WrapperBase& operator=(WrapperBase& other) = delete;
WrapperBase(): m_module(nullptr) {}
~WrapperBase()
{
if (m_module)
{
FreeLibrary(m_module);
PrintLog("Unloaded %s", module_path.c_str());
}
}
static T& Get()
{
static T instance;
return instance;
}
protected:
void WrapperLoad(const char* module_name)
{
module_path = CreateSystemModulePath(module_name);
m_module = LoadLibraryA(module_path.c_str());
if (!m_module)
{
HRESULT hr = HRESULT_FROM_WIN32(GetLastError());
_com_error err(hr);
std::string msg = StringFromFormat("Cannot load %s\nHRESULT 0x%08X: \"%s\"", module_path.c_str(), err.Error(), err.ErrorMessage());
PrintLog(msg.c_str());
MessageBoxA(NULL, msg.c_str(), "Error", MB_ICONERROR);
ExitProcess(hr);
}
PrintLog("Loaded %s", module_path.c_str());
}
template<typename T>
void StoreAddress(T* dest, const char* name)
{
*dest = reinterpret_cast<T>(::GetProcAddress(m_module, name));
}
private:
HMODULE m_module;
std::string module_path;
};
class D3D9DLL : public WrapperBase<D3D9DLL>
{
public:
IDirect3D9* (WINAPI* Direct3DCreate9)(UINT SDKVersion);
HRESULT(WINAPI* Direct3DCreate9Ex)(UINT SDKVersion, IDirect3D9Ex **ppD3D);
int (WINAPI* D3DPERF_BeginEvent)(D3DCOLOR col, LPCWSTR wszName);
int (WINAPI* D3DPERF_EndEvent)(void);
DWORD(WINAPI* D3DPERF_GetStatus)();
BOOL(WINAPI* D3DPERF_QueryRepeatFrame)();
void (WINAPI* D3DPERF_SetMarker)(D3DCOLOR col, LPCWSTR wszName);
void (WINAPI* D3DPERF_SetOptions)(DWORD dwOptions);
void (WINAPI* D3DPERF_SetRegion)(D3DCOLOR col, LPCWSTR wszName);
D3D9DLL()
{
WrapperLoad("d3d9.dll");
StoreAddress(&Direct3DCreate9, "Direct3DCreate9");
StoreAddress(&Direct3DCreate9Ex, "Direct3DCreate9Ex");
StoreAddress(&D3DPERF_BeginEvent, "D3DPERF_BeginEvent");
StoreAddress(&D3DPERF_EndEvent, "D3DPERF_EndEvent");
StoreAddress(&D3DPERF_GetStatus, "D3DPERF_GetStatus");
StoreAddress(&D3DPERF_QueryRepeatFrame, "D3DPERF_QueryRepeatFrame");
StoreAddress(&D3DPERF_SetMarker, "D3DPERF_SetMarker");
StoreAddress(&D3DPERF_SetOptions, "D3DPERF_SetOptions");
StoreAddress(&D3DPERF_SetRegion, "D3DPERF_SetRegion");
}
};
extern "C"
{
IDirect3D9 * WINAPI _Direct3DCreate9(UINT SDKVersion)
{
return D3D9DLL::Get().Direct3DCreate9(SDKVersion);
}
HRESULT WINAPI _Direct3DCreate9Ex(UINT SDKVersion, IDirect3D9Ex **ppD3D)
{
return D3D9DLL::Get().Direct3DCreate9Ex(SDKVersion, ppD3D);
}
int WINAPI _D3DPERF_BeginEvent(D3DCOLOR col, LPCWSTR wszName)
{
return D3D9DLL::Get().D3DPERF_BeginEvent(col, wszName);
}
int WINAPI _D3DPERF_EndEvent()
{
return D3D9DLL::Get().D3DPERF_EndEvent();
}
DWORD WINAPI _D3DPERF_GetStatus()
{
return D3D9DLL::Get().D3DPERF_GetStatus();
}
BOOL WINAPI _D3DPERF_QueryRepeatFrame()
{
return D3D9DLL::Get().D3DPERF_QueryRepeatFrame();
}
void WINAPI _D3DPERF_SetMarker(D3DCOLOR col, LPCWSTR wszName)
{
return D3D9DLL::Get().D3DPERF_SetMarker(col, wszName);
}
void WINAPI _D3DPERF_SetOptions(DWORD dwOptions)
{
return D3D9DLL::Get().D3DPERF_SetOptions(dwOptions);
}
void WINAPI _D3DPERF_SetRegion(D3DCOLOR col, LPCWSTR wszName)
{
return D3D9DLL::Get().D3DPERF_SetRegion(col, wszName);
}
}
class DINPUT8DLL : public WrapperBase<DINPUT8DLL>
{
public:
HRESULT (WINAPI* DirectInput8Create)(HINSTANCE hinst, DWORD dwVersion, REFIID riidltf, LPVOID *ppvOut, LPUNKNOWN punkOuter);
DINPUT8DLL()
{
WrapperLoad("dinput8.dll");
StoreAddress(&DirectInput8Create, "DirectInput8Create");
}
};
extern "C"
{
HRESULT WINAPI _DirectInput8Create(HINSTANCE hinst, DWORD dwVersion, REFIID riidltf, LPVOID *ppvOut, LPUNKNOWN punkOuter)
{
return DINPUT8DLL::Get().DirectInput8Create(hinst, dwVersion, riidltf, ppvOut, punkOuter);
}
}
class XINPUTDLL : public WrapperBase<XINPUTDLL>
{
public:
// XInput 1.3 and older functions
DWORD(WINAPI* XInputGetState)(DWORD dwUserIndex, XINPUT_STATE* pState);
DWORD(WINAPI* XInputSetState)(DWORD dwUserIndex, XINPUT_VIBRATION* pVibration);
DWORD(WINAPI* XInputGetCapabilities)(DWORD dwUserIndex, DWORD dwFlags, XINPUT_CAPABILITIES* pCapabilities);
VOID(WINAPI* XInputEnable)(BOOL enable);
DWORD(WINAPI* XInputGetDSoundAudioDeviceGuids)(DWORD dwUserIndex, GUID* pDSoundRenderGuid, GUID* pDSoundCaptureGuid);
DWORD(WINAPI* XInputGetBatteryInformation)(DWORD dwUserIndex, BYTE devType, XINPUT_BATTERY_INFORMATION* pBatteryInformation);
DWORD(WINAPI* XInputGetKeystroke)(DWORD dwUserIndex, DWORD dwReserved, PXINPUT_KEYSTROKE pKeystroke);
// XInput 1.3 undocumented functions
DWORD(WINAPI* XInputGetStateEx)(DWORD dwUserIndex, XINPUT_STATE *pState); // 100
DWORD(WINAPI* XInputWaitForGuideButton)(DWORD dwUserIndex, DWORD dwFlag, LPVOID pVoid); // 101
DWORD(WINAPI* XInputCancelGuideButtonWait)(DWORD dwUserIndex); // 102
DWORD(WINAPI* XInputPowerOffController)(DWORD dwUserIndex); // 103
// XInput 1.4 functions
DWORD(WINAPI* XInputGetAudioDeviceIds)(DWORD dwUserIndex, LPWSTR pRenderDeviceId, UINT* pRenderCount, LPWSTR pCaptureDeviceId, UINT* pCaptureCount);
// XInput 1.4 undocumented functionss
DWORD(WINAPI* XInputGetBaseBusInformation)(DWORD dwUserIndex, struct XINPUT_BUSINFO* pBusinfo); // 104
DWORD(WINAPI* XInputGetCapabilitiesEx)(DWORD unk1, DWORD dwUserIndex, DWORD dwFlags, struct XINPUT_CAPABILITIESEX* pCapabilitiesEx); // 108
XINPUTDLL()
{
WrapperLoad("xinput1_3.dll");
// XInput 1.3 and older functions
StoreAddress(&XInputGetState, "XInputGetState");
StoreAddress(&XInputSetState, "XInputSetState");
StoreAddress(&XInputGetCapabilities, "XInputGetCapabilities");
StoreAddress(&XInputEnable, "XInputEnable");
StoreAddress(&XInputGetDSoundAudioDeviceGuids, "XInputGetDSoundAudioDeviceGuids");
StoreAddress(&XInputGetBatteryInformation, "XInputGetBatteryInformation");
StoreAddress(&XInputGetKeystroke, "XInputGetKeystroke");
// XInput 1.3 undocumented functions
StoreAddress(&XInputGetStateEx, (const char*)100);
StoreAddress(&XInputWaitForGuideButton, (const char*)101);
StoreAddress(&XInputCancelGuideButtonWait, (const char*)102);
StoreAddress(&XInputPowerOffController, (const char*)103);
// XInput 1.4 functions
StoreAddress(&XInputGetAudioDeviceIds, "XInputGetAudioDeviceIds");
// XInput 1.4 undocumented functionss
StoreAddress(&XInputGetBaseBusInformation, (const char*)104);
StoreAddress(&XInputGetCapabilitiesEx, (const char*)108);
}
};
extern "C"
{
// XInput 1.3 and older functions
DWORD WINAPI _XInputGetState(DWORD dwUserIndex, XINPUT_STATE* pState)
{
return XINPUTDLL::Get().XInputGetState(dwUserIndex, pState);
}
DWORD WINAPI _XInputSetState(DWORD dwUserIndex, XINPUT_VIBRATION* pVibration)
{
return XINPUTDLL::Get().XInputSetState(dwUserIndex, pVibration);
}
DWORD WINAPI _XInputGetCapabilities(DWORD dwUserIndex, DWORD dwFlags, XINPUT_CAPABILITIES* pCapabilities)
{
return XINPUTDLL::Get().XInputGetCapabilities(dwUserIndex, dwFlags, pCapabilities);
}
VOID WINAPI _XInputEnable(BOOL enable)
{
return XINPUTDLL::Get().XInputEnable(enable);
}
DWORD WINAPI _XInputGetDSoundAudioDeviceGuids(DWORD dwUserIndex, GUID* pDSoundRenderGuid, GUID* pDSoundCaptureGuid)
{
return XINPUTDLL::Get().XInputGetDSoundAudioDeviceGuids(dwUserIndex, pDSoundRenderGuid, pDSoundCaptureGuid);
}
DWORD WINAPI _XInputGetBatteryInformation(DWORD dwUserIndex, BYTE devType, XINPUT_BATTERY_INFORMATION* pBatteryInformation)
{
return XINPUTDLL::Get().XInputGetBatteryInformation(dwUserIndex, devType, pBatteryInformation);
}
DWORD WINAPI _XInputGetKeystroke(DWORD dwUserIndex, DWORD dwReserved, PXINPUT_KEYSTROKE pKeystroke)
{
return XINPUTDLL::Get().XInputGetKeystroke(dwUserIndex, dwReserved, pKeystroke);
}
}
#pragma once
#include "comdef.h"
#include "d3d9.h"
#include "dinput.h"
#include "xinput.h"
template <class T>
class WrapperBase
{
public:
WrapperBase(const WrapperBase&) = delete;
const WrapperBase& operator=(WrapperBase& other) = delete;
WrapperBase(): m_module(nullptr) {}
~WrapperBase()
{
if (m_module)
{
FreeLibrary(m_module);
PrintLog("Unloaded %s", module_path.c_str());
}
}
static T& Get()
{
static T instance;
return instance;
}
protected:
void WrapperLoad(const char* module_name)
{
module_path = CreateSystemModulePath(module_name);
m_module = LoadLibraryA(module_path.c_str());
if (!m_module)
{
HRESULT hr = HRESULT_FROM_WIN32(GetLastError());
_com_error err(hr);
std::string msg = StringFromFormat("Cannot load %s\nHRESULT 0x%08X: \"%s\"", module_path.c_str(), err.Error(), err.ErrorMessage());
PrintLog(msg.c_str());
MessageBoxA(NULL, msg.c_str(), "Error", MB_ICONERROR);
ExitProcess(hr);
}
PrintLog("Loaded %s", module_path.c_str());
}
template<typename T>
void StoreAddress(T* dest, const char* name)
{
*dest = reinterpret_cast<T>(::GetProcAddress(m_module, name));
}
private:
HMODULE m_module;
std::string module_path;
};
class D3D9DLL : public WrapperBase<D3D9DLL>
{
public:
IDirect3D9* (WINAPI* Direct3DCreate9)(UINT SDKVersion);
HRESULT(WINAPI* Direct3DCreate9Ex)(UINT SDKVersion, IDirect3D9Ex **ppD3D);
int (WINAPI* D3DPERF_BeginEvent)(D3DCOLOR col, LPCWSTR wszName);
int (WINAPI* D3DPERF_EndEvent)(void);
DWORD(WINAPI* D3DPERF_GetStatus)();
BOOL(WINAPI* D3DPERF_QueryRepeatFrame)();
void (WINAPI* D3DPERF_SetMarker)(D3DCOLOR col, LPCWSTR wszName);
void (WINAPI* D3DPERF_SetOptions)(DWORD dwOptions);
void (WINAPI* D3DPERF_SetRegion)(D3DCOLOR col, LPCWSTR wszName);
D3D9DLL()
{
WrapperLoad("d3d9.dll");
StoreAddress(&Direct3DCreate9, "Direct3DCreate9");
StoreAddress(&Direct3DCreate9Ex, "Direct3DCreate9Ex");
StoreAddress(&D3DPERF_BeginEvent, "D3DPERF_BeginEvent");
StoreAddress(&D3DPERF_EndEvent, "D3DPERF_EndEvent");
StoreAddress(&D3DPERF_GetStatus, "D3DPERF_GetStatus");
StoreAddress(&D3DPERF_QueryRepeatFrame, "D3DPERF_QueryRepeatFrame");
StoreAddress(&D3DPERF_SetMarker, "D3DPERF_SetMarker");
StoreAddress(&D3DPERF_SetOptions, "D3DPERF_SetOptions");
StoreAddress(&D3DPERF_SetRegion, "D3DPERF_SetRegion");
}
};
extern "C"
{
IDirect3D9 * WINAPI _Direct3DCreate9(UINT SDKVersion)
{
return D3D9DLL::Get().Direct3DCreate9(SDKVersion);
}
HRESULT WINAPI _Direct3DCreate9Ex(UINT SDKVersion, IDirect3D9Ex **ppD3D)
{
return D3D9DLL::Get().Direct3DCreate9Ex(SDKVersion, ppD3D);
}
int WINAPI _D3DPERF_BeginEvent(D3DCOLOR col, LPCWSTR wszName)
{
return D3D9DLL::Get().D3DPERF_BeginEvent(col, wszName);
}
int WINAPI _D3DPERF_EndEvent()
{
return D3D9DLL::Get().D3DPERF_EndEvent();
}
DWORD WINAPI _D3DPERF_GetStatus()
{
return D3D9DLL::Get().D3DPERF_GetStatus();
}
BOOL WINAPI _D3DPERF_QueryRepeatFrame()
{
return D3D9DLL::Get().D3DPERF_QueryRepeatFrame();
}
void WINAPI _D3DPERF_SetMarker(D3DCOLOR col, LPCWSTR wszName)
{
return D3D9DLL::Get().D3DPERF_SetMarker(col, wszName);
}
void WINAPI _D3DPERF_SetOptions(DWORD dwOptions)
{
return D3D9DLL::Get().D3DPERF_SetOptions(dwOptions);
}
void WINAPI _D3DPERF_SetRegion(D3DCOLOR col, LPCWSTR wszName)
{
return D3D9DLL::Get().D3DPERF_SetRegion(col, wszName);
}
}
class DINPUT8DLL : public WrapperBase<DINPUT8DLL>
{
public:
HRESULT (WINAPI* DirectInput8Create)(HINSTANCE hinst, DWORD dwVersion, REFIID riidltf, LPVOID *ppvOut, LPUNKNOWN punkOuter);
DINPUT8DLL()
{
WrapperLoad("dinput8.dll");
StoreAddress(&DirectInput8Create, "DirectInput8Create");
}
};
extern "C"
{
HRESULT WINAPI _DirectInput8Create(HINSTANCE hinst, DWORD dwVersion, REFIID riidltf, LPVOID *ppvOut, LPUNKNOWN punkOuter)
{
return DINPUT8DLL::Get().DirectInput8Create(hinst, dwVersion, riidltf, ppvOut, punkOuter);
}
}
class XINPUTDLL : public WrapperBase<XINPUTDLL>
{
public:
// XInput 1.3 and older functions
DWORD(WINAPI* XInputGetState)(DWORD dwUserIndex, XINPUT_STATE* pState);
DWORD(WINAPI* XInputSetState)(DWORD dwUserIndex, XINPUT_VIBRATION* pVibration);
DWORD(WINAPI* XInputGetCapabilities)(DWORD dwUserIndex, DWORD dwFlags, XINPUT_CAPABILITIES* pCapabilities);
VOID(WINAPI* XInputEnable)(BOOL enable);
DWORD(WINAPI* XInputGetDSoundAudioDeviceGuids)(DWORD dwUserIndex, GUID* pDSoundRenderGuid, GUID* pDSoundCaptureGuid);
DWORD(WINAPI* XInputGetBatteryInformation)(DWORD dwUserIndex, uint8_t devType, XINPUT_BATTERY_INFORMATION* pBatteryInformation);
DWORD(WINAPI* XInputGetKeystroke)(DWORD dwUserIndex, DWORD dwReserved, PXINPUT_KEYSTROKE pKeystroke);
// XInput 1.3 undocumented functions
DWORD(WINAPI* XInputGetStateEx)(DWORD dwUserIndex, XINPUT_STATE *pState); // 100
DWORD(WINAPI* XInputWaitForGuideButton)(DWORD dwUserIndex, DWORD dwFlag, LPVOID pVoid); // 101
DWORD(WINAPI* XInputCancelGuideButtonWait)(DWORD dwUserIndex); // 102
DWORD(WINAPI* XInputPowerOffController)(DWORD dwUserIndex); // 103
// XInput 1.4 functions
DWORD(WINAPI* XInputGetAudioDeviceIds)(DWORD dwUserIndex, LPWSTR pRenderDeviceId, UINT* pRenderCount, LPWSTR pCaptureDeviceId, UINT* pCaptureCount);
// XInput 1.4 undocumented functionss
DWORD(WINAPI* XInputGetBaseBusInformation)(DWORD dwUserIndex, struct XINPUT_BUSINFO* pBusinfo); // 104
DWORD(WINAPI* XInputGetCapabilitiesEx)(DWORD unk1, DWORD dwUserIndex, DWORD dwFlags, struct XINPUT_CAPABILITIESEX* pCapabilitiesEx); // 108
XINPUTDLL()
{
WrapperLoad("xinput1_3.dll");
// XInput 1.3 and older functions
StoreAddress(&XInputGetState, "XInputGetState");
StoreAddress(&XInputSetState, "XInputSetState");
StoreAddress(&XInputGetCapabilities, "XInputGetCapabilities");
StoreAddress(&XInputEnable, "XInputEnable");
StoreAddress(&XInputGetDSoundAudioDeviceGuids, "XInputGetDSoundAudioDeviceGuids");
StoreAddress(&XInputGetBatteryInformation, "XInputGetBatteryInformation");
StoreAddress(&XInputGetKeystroke, "XInputGetKeystroke");
// XInput 1.3 undocumented functions
StoreAddress(&XInputGetStateEx, (const char*)100);
StoreAddress(&XInputWaitForGuideButton, (const char*)101);
StoreAddress(&XInputCancelGuideButtonWait, (const char*)102);
StoreAddress(&XInputPowerOffController, (const char*)103);
// XInput 1.4 functions
StoreAddress(&XInputGetAudioDeviceIds, "XInputGetAudioDeviceIds");
// XInput 1.4 undocumented functionss
StoreAddress(&XInputGetBaseBusInformation, (const char*)104);
StoreAddress(&XInputGetCapabilitiesEx, (const char*)108);
}
};
extern "C"
{
// XInput 1.3 and older functions
DWORD WINAPI _XInputGetState(DWORD dwUserIndex, XINPUT_STATE* pState)
{
return XINPUTDLL::Get().XInputGetState(dwUserIndex, pState);
}
DWORD WINAPI _XInputSetState(DWORD dwUserIndex, XINPUT_VIBRATION* pVibration)
{
return XINPUTDLL::Get().XInputSetState(dwUserIndex, pVibration);
}
DWORD WINAPI _XInputGetCapabilities(DWORD dwUserIndex, DWORD dwFlags, XINPUT_CAPABILITIES* pCapabilities)
{
return XINPUTDLL::Get().XInputGetCapabilities(dwUserIndex, dwFlags, pCapabilities);
}
VOID WINAPI _XInputEnable(BOOL enable)
{
return XINPUTDLL::Get().XInputEnable(enable);
}
DWORD WINAPI _XInputGetDSoundAudioDeviceGuids(DWORD dwUserIndex, GUID* pDSoundRenderGuid, GUID* pDSoundCaptureGuid)
{
return XINPUTDLL::Get().XInputGetDSoundAudioDeviceGuids(dwUserIndex, pDSoundRenderGuid, pDSoundCaptureGuid);
}
DWORD WINAPI _XInputGetBatteryInformation(DWORD dwUserIndex, uint8_t devType, XINPUT_BATTERY_INFORMATION* pBatteryInformation)
{
return XINPUTDLL::Get().XInputGetBatteryInformation(dwUserIndex, devType, pBatteryInformation);
}
DWORD WINAPI _XInputGetKeystroke(DWORD dwUserIndex, DWORD dwReserved, PXINPUT_KEYSTROKE pKeystroke)
{
return XINPUTDLL::Get().XInputGetKeystroke(dwUserIndex, dwReserved, pKeystroke);
}
}

View file

@ -2,20 +2,19 @@
#include "XInputManager.h"
#include <XInput.h>
XInputManager::XInputManager(byte** base_controller_input_address_ptr)
XInputManager::XInputManager(uint8_t** base_controller_input_address_ptr)
{
xinputThread = std::thread(&XInputManager::Run, this, base_controller_input_address_ptr);
}
void XInputManager::Run(byte** base_controller_input_address_ptr)
void XInputManager::Run(uint8_t** base_controller_input_address_ptr)
{
DWORD controllerState;
bool hasConnected = false;
for (DWORD i = 0; i < XUSER_MAX_COUNT; i++) {
XINPUT_STATE state;
ZeroMemory(&state, sizeof(XINPUT_STATE));
controllerState = XInputGetState(i, &state);
const DWORD controllerState = XInputGetState(i, &state);
if (controllerState == ERROR_SUCCESS) {
controllerId = i;
hasConnected = true;
@ -28,7 +27,7 @@ void XInputManager::Run(byte** base_controller_input_address_ptr)
}
}
void XInputManager::WaitAndSetVibrationAddress(byte** base_controller_input_address_ptr)
void XInputManager::WaitAndSetVibrationAddress(uint8_t** base_controller_input_address_ptr)
{
do {
std::this_thread::sleep_for(std::chrono::milliseconds(4));
@ -47,7 +46,7 @@ void XInputManager::VibrationLoop()
while (true) {
const float vibrationStrengthLowFrequency = *vibration_address_low_frequency;
const float vibrationStrengthHighFrequency = *vibration_address_high_frequency;
if (vibrationStrengthLowFrequency || vibrationStrengthHighFrequency) {
if (vibrationStrengthLowFrequency > 0.0f || vibrationStrengthHighFrequency > 0.0f) {
SetControllerVibration((WORD)(vibrationStrengthLowFrequency * maxVibrationStrength), (WORD)(vibrationStrengthHighFrequency * maxVibrationStrength));
wasVibrating = true;
}

View file

@ -6,9 +6,9 @@ class XInputManager
DWORD controllerId = -1;
std::thread xinputThread;
public:
XInputManager(byte** base_controller_input_address_ptr);
void Run(byte** base_controller_input_address_ptr);
void WaitAndSetVibrationAddress(byte** base_controller_input_address_ptr);
XInputManager(uint8_t** base_controller_input_address_ptr);
void Run(uint8_t** base_controller_input_address_ptr);
void WaitAndSetVibrationAddress(uint8_t** base_controller_input_address_ptr);
void VibrationLoop();
void SetControllerVibration(const WORD& leftMotorVibration, const WORD& rightMotorVibration);
};