Add files for version 1.4.0

This commit is contained in:
rebtd7 2020-01-22 19:34:48 -03:00 committed by GitHub
parent c470d53a9e
commit bf87990a5f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 421 additions and 232 deletions

View file

@ -2,6 +2,7 @@
#include "Context.h"
#include "IDirect3DVertexBuffer9.h"
#include <intrin.h>
void MainContext::EnableAutoFix()
{
@ -24,6 +25,7 @@ void MainContext::EnableAutoFix()
{
autofix = FINAL_FANTASY_XIII;
PrintLog("AutoFix for \"Final Fantasy XIII\" enabled");
FF13_InitializeGameAddresses();
}
if (exe_name == "ffxiii2img.exe")
@ -35,65 +37,6 @@ void MainContext::EnableAutoFix()
}
}
void MainContext::FF13_2_CreateSetFrameRateCodeBlock()
{
const int blockSize = 31;
FF13_2_SET_FRAME_RATE_INJECTED_CODE = new byte[blockSize];
ChangeMemoryProtectionToReadWriteExecute(FF13_2_SET_FRAME_RATE_INJECTED_CODE, blockSize);
float frameRateConfigValue = (float)context.config.GetFFXIIIIngameFrameRateLimit();
if (AreAlmostTheSame(frameRateConfigValue, -1.0F) || frameRateConfigValue > FF13_2_MAX_FRAME_CAP) {
ff13_2_targetFrameRate = FF13_2_MAX_FRAME_CAP;
}
else {
ff13_2_targetFrameRate = frameRateConfigValue;
}
// movss xmm1,[&FF13_2_30_FPS]
*(FF13_2_SET_FRAME_RATE_INJECTED_CODE + 0) = 0xF3;
*(FF13_2_SET_FRAME_RATE_INJECTED_CODE + 1) = 0x0F;
*(FF13_2_SET_FRAME_RATE_INJECTED_CODE + 2) = 0x10;
*(FF13_2_SET_FRAME_RATE_INJECTED_CODE + 3) = 0x0D;
*(float**)(FF13_2_SET_FRAME_RATE_INJECTED_CODE + 4) = (float*)(&FF13_2_30_FPS);
// ucomiss xmm0,xmm1
*(FF13_2_SET_FRAME_RATE_INJECTED_CODE + 8) = 0x0F;
*(FF13_2_SET_FRAME_RATE_INJECTED_CODE + 9) = 0x2E;
*(FF13_2_SET_FRAME_RATE_INJECTED_CODE + 10) = 0xC1;
//jna SetFrameRateVar
*(FF13_2_SET_FRAME_RATE_INJECTED_CODE + 11) = 0x76;
*(FF13_2_SET_FRAME_RATE_INJECTED_CODE + 12) = 0x08;
// movss xmm0,[&FF13_2_30_FPS]
*(FF13_2_SET_FRAME_RATE_INJECTED_CODE + 13) = 0xF3;
*(FF13_2_SET_FRAME_RATE_INJECTED_CODE + 14) = 0x0F;
*(FF13_2_SET_FRAME_RATE_INJECTED_CODE + 15) = 0x10;
*(FF13_2_SET_FRAME_RATE_INJECTED_CODE + 16) = 0x05;
*(float**)(FF13_2_SET_FRAME_RATE_INJECTED_CODE + 17) = (float*)(&ff13_2_targetFrameRate);
// movss [ecx+04],xmm0
*(FF13_2_SET_FRAME_RATE_INJECTED_CODE + 21) = 0xF3;
*(FF13_2_SET_FRAME_RATE_INJECTED_CODE + 22) = 0x0F;
*(FF13_2_SET_FRAME_RATE_INJECTED_CODE + 23) = 0x11;
*(FF13_2_SET_FRAME_RATE_INJECTED_CODE + 24) = 0x41;
*(FF13_2_SET_FRAME_RATE_INJECTED_CODE + 25) = 0x04;
//jmp ffxiii2img.exe + 80261B
*(FF13_2_SET_FRAME_RATE_INJECTED_CODE + 26) = 0xE9;
*(uint32_t*)(FF13_2_SET_FRAME_RATE_INJECTED_CODE + 27) = ff13_2_set_frame_rate_address - FF13_2_SET_FRAME_RATE_INJECTED_CODE - 26;
}
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);
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);
}
const std::map<const MainContext::AutoFixes, const uint32_t> MainContext::behaviorflags_fixes =
{
{ RESIDENT_EVIL_4, D3DCREATE_SOFTWARE_VERTEXPROCESSING },
@ -161,28 +104,63 @@ HRESULT APIENTRY MainContext::ApplyVertexBufferFix(IDirect3DDevice9* pIDirect3DD
return pIDirect3DDevice9->CreateVertexBuffer(Length, Usage, FVF, Pool, ppVertexBuffer, pSharedHandle);
}
void MainContext::FF13_OneTimeFixes() {
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
PrintLog("Base Addr = %x", baseAddr);
bool successSoFar = true;
// The game repeatedly sets the frame rate limit. Disable the instruction that does it.
MainContext::FF13_AddHookIngameFrameRateLimitSetter();
successSoFar &= MainContext::FF13_SetFrameRateVariables();
if (successSoFar) {
context.FF13_RemoveContinuousControllerScan();
context.FF13_FixMissingEnemyScan();
context.didOneTimeFixes = true;
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_vibration_low_set_zero_address = baseAddr + 0x4210DF;
ff13_vibration_high_set_zero_address = baseAddr + 0x4210F3;
}
void MainContext::FF13_OneTimeFixes() {
MainContext::FF13_NOPIngameFrameRateLimitSetter();
MainContext::FF13_SetFrameRateVariables();
MainContext::FF13_RemoveContinuousControllerScan();
MainContext::FF13_FixMissingEnemyScan();
MainContext::FF13_EnableControllerVibration();
PrintLog("Finished FF13 One Time Fixes");
MainContext::didOneTimeFixes = true;
}
void MainContext::FF13_EnableControllerVibration()
{
if (!config.GetFFXIIIEnableControllerVibration()) {
PrintLog("Vibration should not be enabled (config file)");
return;
}
PrintLog("Enabling controller vibration...");
ChangeMemoryProtectionToReadWriteExecute(ff13_vibration_low_set_zero_address, 5);
*ff13_vibration_low_set_zero_address = 0x90;
*(ff13_vibration_low_set_zero_address + 1) = 0x90;
*(ff13_vibration_low_set_zero_address + 2) = 0x90;
*(ff13_vibration_low_set_zero_address + 3) = 0x90;
*(ff13_vibration_low_set_zero_address + 4) = 0x90;
ChangeMemoryProtectionToReadWriteExecute(ff13_vibration_high_set_zero_address, 5);
*ff13_vibration_high_set_zero_address = 0x90;
*(ff13_vibration_high_set_zero_address + 1) = 0x90;
*(ff13_vibration_high_set_zero_address + 2) = 0x90;
*(ff13_vibration_high_set_zero_address + 3) = 0x90;
*(ff13_vibration_high_set_zero_address + 4) = 0x90;
xinputManager = new XInputManager(ff13_base_controller_input_address_ptr);
}
void MainContext::FF13_RemoveContinuousControllerScan() {
// Disable continuous controller scanning.
PrintLog("Removing game slow and synchronous controller continuous controller scanning...");
context.ChangeMemoryProtectionToReadWriteExecute(FF13_CONTINUOUS_SCAN_INSTRUCTION_ADDRESS, 1);
context.ChangeMemoryProtectionToReadWriteExecute(ff13_continuous_scan_instruction_address, 1);
// change a jne to jmp
*(byte*)FF13_CONTINUOUS_SCAN_INSTRUCTION_ADDRESS = 0xEB;
*(byte*)ff13_continuous_scan_instruction_address = 0xEB;
}
void MainContext::FF13_FixMissingEnemyScan() {
@ -197,37 +175,41 @@ void MainContext::FF13_FixMissingEnemyScan() {
const uint32_t rectWidth = context.backbufferWidth;
const uint32_t rectPosY = (uint32_t)(496.0F * resolutionFactor);
context.ChangeMemoryProtectionToReadWriteExecute(FF13_ENEMY_SCAN_BOX_CODE_ADDRESS, 18);
context.ChangeMemoryProtectionToReadWriteExecute(ff13_enemy_scan_box_code_address, 18);
//push boxHeight
*(byte*)(FF13_ENEMY_SCAN_BOX_CODE_ADDRESS + 0) = 0x68;
*(uint32_t*)(FF13_ENEMY_SCAN_BOX_CODE_ADDRESS + 1) = rectHeight;
//push rectHeight
*(byte*)(ff13_enemy_scan_box_code_address + 0) = 0x68;
*(uint32_t*)(ff13_enemy_scan_box_code_address + 1) = rectHeight;
// push boxWidth
*(byte*)(FF13_ENEMY_SCAN_BOX_CODE_ADDRESS + 5) = 0x68;
*(uint32_t*)(FF13_ENEMY_SCAN_BOX_CODE_ADDRESS + 6) = rectWidth;
// push rectWidth
*(byte*)(ff13_enemy_scan_box_code_address + 5) = 0x68;
*(uint32_t*)(ff13_enemy_scan_box_code_address + 6) = rectWidth;
// push boxPosY
*(byte*)(FF13_ENEMY_SCAN_BOX_CODE_ADDRESS + 10) = 0x68;
*(uint32_t*)(FF13_ENEMY_SCAN_BOX_CODE_ADDRESS + 11) = rectPosY;
// push rectPosY
*(byte*)(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;
*(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;
}
void MainContext::FF13_AddHookIngameFrameRateLimitSetter() {
PrintLog("Using the ingame the instruction that sets the frame rate to get the frame rate address.");
void MainContext::FF13_NOPIngameFrameRateLimitSetter() {
PrintLog("NOPing the in-game instruction that sets the frame rate.");
context.ChangeMemoryProtectionToReadWriteExecute(FF13_SET_FRAMERATE_INGAME_INSTRUCTION_ADDRESS, 5);
context.ChangeMemoryProtectionToReadWriteExecute(ff13_set_framerate_ingame_instruction_address, 5);
// patching to: mov [framePacerTargetPtr], eax
*FF13_SET_FRAMERATE_INGAME_INSTRUCTION_ADDRESS = 0xA3;
*((uint32_t*)(FF13_SET_FRAMERATE_INGAME_INSTRUCTION_ADDRESS + 1)) = (uint32_t)(&framePacerTargetPtr);
// patching to: NOP NOP NOP NOP
*ff13_set_framerate_ingame_instruction_address = 0x90;
*(ff13_set_framerate_ingame_instruction_address + 1) = 0x90;
*(ff13_set_framerate_ingame_instruction_address + 2) = 0x90;
*(ff13_set_framerate_ingame_instruction_address + 3) = 0x90;
*(ff13_set_framerate_ingame_instruction_address + 4) = 0x90;
}
bool MainContext::FF13_SetFrameRateVariables() {
void MainContext::FF13_SetFrameRateVariables() {
float* framePacerTargetPtr = *ff13_frame_pacer_ptr;
if (framePacerTargetPtr) {
PrintLog("Frame pacer target frame rate is at address %x", framePacerTargetPtr);
@ -255,10 +237,8 @@ bool MainContext::FF13_SetFrameRateVariables() {
}
}
else {
PrintLog("Unable to find frame rate pattern. This is normal if the game still hasn't completely started yet.");
PrintLog("Unable to find frame pacer / frame rate address. This shouldn't happen! Report this.");
}
return framePacerTargetPtr;
}
void MainContext::FF13_2_OneTimeFixes() {
@ -269,10 +249,51 @@ void MainContext::FF13_2_OneTimeFixes() {
context.FF13_2_AddHookIngameFrameRateLimitSetter();
context.FF13_2_RemoveContinuousControllerScan();
context.FF13_2_EnableControllerVibration();
PrintLog("Finished FF13-2 One Time Fixes");
context.didOneTimeFixes = true;
}
}
void MainContext::FF13_2_EnableControllerVibration()
{
if (!config.GetFFXIIIEnableControllerVibration()) {
PrintLog("Vibration should not be enabled (config file)");
return;
}
PrintLog("Enabling controller vibration...");
ChangeMemoryProtectionToReadWriteExecute(ff13_2_vibration_low_set_zero_address, 5);
*ff13_2_vibration_low_set_zero_address = 0x90;
*(ff13_2_vibration_low_set_zero_address + 1) = 0x90;
*(ff13_2_vibration_low_set_zero_address + 2) = 0x90;
*(ff13_2_vibration_low_set_zero_address + 3) = 0x90;
*(ff13_2_vibration_low_set_zero_address + 4) = 0x90;
ChangeMemoryProtectionToReadWriteExecute(ff13_2_vibration_high_set_zero_address, 5);
*ff13_2_vibration_high_set_zero_address = 0x90;
*(ff13_2_vibration_high_set_zero_address + 1) = 0x90;
*(ff13_2_vibration_high_set_zero_address + 2) = 0x90;
*(ff13_2_vibration_high_set_zero_address + 3) = 0x90;
*(ff13_2_vibration_high_set_zero_address + 4) = 0x90;
xinputManager = new XInputManager(ff13_2_base_controller_input_address_ptr);
}
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);
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_vibration_low_set_zero_address = baseAddr + 0x2A7221;
ff13_2_vibration_high_set_zero_address = baseAddr + 0x2A7226;
}
void MainContext::FF13_2_RemoveContinuousControllerScan() {
// Disable continuous controller scanning.
@ -297,13 +318,65 @@ void MainContext::FF13_2_AddHookIngameFrameRateLimitSetter() {
*((uint32_t*)(ff13_2_set_frame_rate_address + 1)) = FF13_2_SET_FRAME_RATE_INJECTED_CODE - ff13_2_set_frame_rate_address - 5;
}
void MainContext::FF13_2_CreateSetFrameRateCodeBlock()
{
const int blockSize = 31;
FF13_2_SET_FRAME_RATE_INJECTED_CODE = new byte[blockSize];
ChangeMemoryProtectionToReadWriteExecute(FF13_2_SET_FRAME_RATE_INJECTED_CODE, blockSize);
float frameRateConfigValue = (float)context.config.GetFFXIIIIngameFrameRateLimit();
if (AreAlmostTheSame(frameRateConfigValue, -1.0F) || frameRateConfigValue > FF13_2_MAX_FRAME_CAP) {
ff13_2_targetFrameRate = FF13_2_MAX_FRAME_CAP;
}
else {
ff13_2_targetFrameRate = frameRateConfigValue;
}
// movss xmm1,[&FF13_2_30_FPS]
*(FF13_2_SET_FRAME_RATE_INJECTED_CODE + 0) = 0xF3;
*(FF13_2_SET_FRAME_RATE_INJECTED_CODE + 1) = 0x0F;
*(FF13_2_SET_FRAME_RATE_INJECTED_CODE + 2) = 0x10;
*(FF13_2_SET_FRAME_RATE_INJECTED_CODE + 3) = 0x0D;
*(float**)(FF13_2_SET_FRAME_RATE_INJECTED_CODE + 4) = (float*)(&FF13_2_30_FPS);
// ucomiss xmm0,xmm1
*(FF13_2_SET_FRAME_RATE_INJECTED_CODE + 8) = 0x0F;
*(FF13_2_SET_FRAME_RATE_INJECTED_CODE + 9) = 0x2E;
*(FF13_2_SET_FRAME_RATE_INJECTED_CODE + 10) = 0xC1;
//jna SetFrameRateVar
*(FF13_2_SET_FRAME_RATE_INJECTED_CODE + 11) = 0x76;
*(FF13_2_SET_FRAME_RATE_INJECTED_CODE + 12) = 0x08;
// movss xmm0,[&FF13_2_30_FPS]
*(FF13_2_SET_FRAME_RATE_INJECTED_CODE + 13) = 0xF3;
*(FF13_2_SET_FRAME_RATE_INJECTED_CODE + 14) = 0x0F;
*(FF13_2_SET_FRAME_RATE_INJECTED_CODE + 15) = 0x10;
*(FF13_2_SET_FRAME_RATE_INJECTED_CODE + 16) = 0x05;
*(float**)(FF13_2_SET_FRAME_RATE_INJECTED_CODE + 17) = (float*)(&ff13_2_targetFrameRate);
// SetFrameRateVar:
// movss [ecx+04],xmm0
*(FF13_2_SET_FRAME_RATE_INJECTED_CODE + 21) = 0xF3;
*(FF13_2_SET_FRAME_RATE_INJECTED_CODE + 22) = 0x0F;
*(FF13_2_SET_FRAME_RATE_INJECTED_CODE + 23) = 0x11;
*(FF13_2_SET_FRAME_RATE_INJECTED_CODE + 24) = 0x41;
*(FF13_2_SET_FRAME_RATE_INJECTED_CODE + 25) = 0x04;
// jmp ffxiii2img.exe + 80261B
*(FF13_2_SET_FRAME_RATE_INJECTED_CODE + 26) = 0xE9;
*(uint32_t*)(FF13_2_SET_FRAME_RATE_INJECTED_CODE + 27) = ff13_2_set_frame_rate_address - FF13_2_SET_FRAME_RATE_INJECTED_CODE - 26;
}
void MainContext::ChangeMemoryProtectionToReadWriteExecute(void* address, const int size) {
DWORD oldProtection;
VirtualProtect(address, size, PAGE_EXECUTE_READWRITE, &oldProtection);
}
void MainContext::PrintVersionInfo() {
PrintLog("FF13Fix 1.3.1 https://github.com/rebtd7/FF13Fix");
PrintLog("FF13Fix 1.4.0 https://github.com/rebtd7/FF13Fix");
}
bool MainContext::AreAlmostTheSame(float a, float b) {

View file

@ -5,6 +5,7 @@
#include "Context.h"
#include "IDirect3D9.h"
#include <thread>
MainContext context;
@ -41,7 +42,7 @@ Config::Config()
MainContext::MainContext() : oldWndProc(nullptr)
{
LogFile("FF13Fix.log");
PrintVersionInfo();
context.PrintVersionInfo();
if (config.GetAutoFix()) EnableAutoFix();
@ -61,6 +62,8 @@ MainContext::MainContext() : oldWndProc(nullptr)
MH_CreateHook(SetWindowLongW, HookSetWindowLongW, reinterpret_cast<void**>(&TrueSetWindowLongW));
MH_EnableHook(SetWindowLongW);
}
MainContext::~MainContext()
@ -178,15 +181,21 @@ bool MainContext::CheckWindow(HWND hWnd)
PrintLog("HWND 0x%p: ClassName \"%ls\", WindowName: \"%ls\"", hWnd, className.get(), windowName.get());
if (!context.didOneTimeFixes) {
if (context.autofix == FINAL_FANTASY_XIII) {
if (context.autofix == FINAL_FANTASY_XIII && wcscmp(windowName.get(), L"DIEmWin") == 0) {
const std::lock_guard<std::mutex> lock(context.oneTimeFixesMutex);
if(!context.didOneTimeFixes){
PrintLog("Starting FFXIII one time RAM patches.");
context.FF13_OneTimeFixes();
}
}
else if (context.autofix == FINAL_FANTASY_XIII2 && wcscmp(windowName.get(), L"DIEmWin") == 0) {
const std::lock_guard<std::mutex> lock(context.oneTimeFixesMutex);
if (!context.didOneTimeFixes) {
PrintLog("Starting FFXIII-2 one time RAM patches.");
context.FF13_2_OneTimeFixes();
}
}
}
bool class_found = config.GetWindowClass().compare(className.get()) == 0;
bool window_found = config.GetWindowName().compare(windowName.get()) == 0;
bool force = config.GetAllWindows();

View file

@ -4,6 +4,7 @@
#include "d3d9.h"
#include <MinHook.h>
#include "SimpleIni.h"
#include "XInputManager.h"
struct hkIDirect3D9;
@ -44,6 +45,7 @@ class MainContext
public:
MainContext();
void Foo();
~MainContext();
bool ApplyPresentationParameters(D3DPRESENT_PARAMETERS* pPresentationParameters);
@ -69,27 +71,34 @@ private:
};
void EnableAutoFix();
void FF13_2_CreateSetFrameRateCodeBlock();
void FF13_2_InitializeGameAddresses();
AutoFixes autofix = AutoFixes::NONE;
std::mutex oneTimeFixesMutex;
bool didOneTimeFixes = false;
const float MAX_FRAME_RATE_LIMIT = 250000.0F;
byte* FF13_SET_FRAMERATE_INGAME_INSTRUCTION_ADDRESS = (byte*)0x00E8D65F;
byte* FF13_CONTINUOUS_SCAN_INSTRUCTION_ADDRESS = (byte*)0x00820868;
byte* FF13_ENEMY_SCAN_BOX_CODE_ADDRESS = (byte*)0x0094C920;
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;
byte* FF13_2_SET_FRAME_RATE_INJECTED_CODE = NULL;
byte* ff13_2_continuous_scan_instruction_address;
byte* 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;
const float FF13_2_30_FPS = 30.0F;
const float FF13_2_MAX_FRAME_CAP = 1000.0F;
XInputManager* xinputManager;
float* framePacerTargetPtr = NULL;
UINT backbufferWidth = 0;
void FixBehaviorFlagConflict(const DWORD flags_in, DWORD* flags_out);
@ -102,15 +111,20 @@ private:
bool AreAlmostTheSame(float a, float b);
void PrintVersionInfo();
void FF13_InitializeGameAddresses();
void FF13_OneTimeFixes();
void FF13_AddHookIngameFrameRateLimitSetter();
bool FF13_SetFrameRateVariables();
void FF13_EnableControllerVibration();
void FF13_NOPIngameFrameRateLimitSetter();
void FF13_SetFrameRateVariables();
void FF13_FixMissingEnemyScan();
void FF13_RemoveContinuousControllerScan();
void FF13_2_CreateSetFrameRateCodeBlock();
void FF13_2_InitializeGameAddresses();
void FF13_2_RemoveContinuousControllerScan();
void FF13_2_AddHookIngameFrameRateLimitSetter();
void FF13_2_OneTimeFixes();
void FF13_2_EnableControllerVibration();
};
extern MainContext context;

View file

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

69
d3d9ex/XInputManager.cpp Normal file
View file

@ -0,0 +1,69 @@
#include "stdafx.h"
#include "XInputManager.h"
#include <XInput.h>
XInputManager::XInputManager(byte** 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)
{
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);
if (controllerState == ERROR_SUCCESS) {
controllerId = i;
hasConnected = true;
break;
}
}
if (hasConnected) {
WaitAndSetVibrationAddress(base_controller_input_address_ptr);
VibrationLoop();
}
}
void XInputManager::WaitAndSetVibrationAddress(byte** base_controller_input_address_ptr)
{
do {
std::this_thread::sleep_for(std::chrono::milliseconds(4));
if (base_controller_input_address_ptr && *base_controller_input_address_ptr) {
vibration_address_low_frequency = (float*)(*base_controller_input_address_ptr + 0x40 + 0x60 - 0x4);
vibration_address_high_frequency = vibration_address_low_frequency + 1;
}
} while (vibration_address_low_frequency == NULL);
}
void XInputManager::VibrationLoop()
{
const WORD maxVibrationStrength = 65535;
bool wasVibrating = false;
SetControllerVibration(0, 0);
while (true) {
const float vibrationStrengthLowFrequency = *vibration_address_low_frequency;
const float vibrationStrengthHighFrequency = *vibration_address_high_frequency;
if (vibrationStrengthLowFrequency || vibrationStrengthHighFrequency) {
SetControllerVibration(vibrationStrengthLowFrequency * maxVibrationStrength, vibrationStrengthHighFrequency * maxVibrationStrength);
wasVibrating = true;
}
else if(wasVibrating) {
SetControllerVibration(0, 0);
wasVibrating = false;
}
std::this_thread::sleep_for(std::chrono::milliseconds(4));
}
}
void XInputManager::SetControllerVibration(const WORD& leftMotorVibration, const WORD& rightMotorVibration)
{
XINPUT_VIBRATION vibration;
ZeroMemory(&vibration, sizeof(XINPUT_VIBRATION));
vibration.wLeftMotorSpeed = leftMotorVibration;
vibration.wRightMotorSpeed = rightMotorVibration;
XInputSetState(controllerId, &vibration);
}

15
d3d9ex/XInputManager.h Normal file
View file

@ -0,0 +1,15 @@
#pragma once
class XInputManager
{
float* vibration_address_high_frequency = NULL;
float* vibration_address_low_frequency = NULL;
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);
void VibrationLoop();
void SetControllerVibration(const WORD& leftMotorVibration, const WORD& rightMotorVibration);
};

View file

@ -137,7 +137,7 @@
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>d3d9.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>XINPUT9_1_0.LIB;d3d9.lib;%(AdditionalDependencies)</AdditionalDependencies>
<ModuleDefinitionFile>exports.def</ModuleDefinitionFile>
</Link>
</ItemDefinitionGroup>
@ -172,6 +172,7 @@
<ClInclude Include="Settings.h" />
<ClInclude Include="stdafx.h" />
<ClInclude Include="targetver.h" />
<ClInclude Include="XInputManager.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="AutoFix.cpp" />
@ -199,6 +200,7 @@
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="XInputManager.cpp" />
</ItemGroup>
<ItemGroup>
<None Include="exports.def" />

View file

@ -42,6 +42,9 @@
<ClInclude Include="IDirect3DVertexBuffer9.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="XInputManager.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="stdafx.cpp">
@ -65,6 +68,9 @@
<ClCompile Include="IDirect3DVertexBuffer9.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="XInputManager.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="exports.def">