Initial FF13-2 support
This commit is contained in:
parent
4133d6b03a
commit
cc4e3f0c34
|
@ -25,6 +25,73 @@ void MainContext::EnableAutoFix()
|
|||
autofix = FINAL_FANTASY_XIII;
|
||||
PrintLog("AutoFix for \"Final Fantasy XIII\" enabled");
|
||||
}
|
||||
|
||||
if (exe_name == "ffxiii2img.exe")
|
||||
{
|
||||
autofix = FINAL_FANTASY_XIII2;
|
||||
PrintLog("AutoFix for \"Final Fantasy XIII-2\" enabled");
|
||||
FF13_2_InitializeGameAddresses();
|
||||
FF13_2_CreateSetFrameRateCodeBlock();
|
||||
}
|
||||
}
|
||||
|
||||
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 = 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 =
|
||||
|
@ -90,3 +157,148 @@ HRESULT APIENTRY MainContext::ApplyVertexBufferFix(IDirect3DDevice9 *pIDirect3DD
|
|||
}
|
||||
return pIDirect3DDevice9->CreateVertexBuffer(Length, Usage, FVF, Pool, ppVertexBuffer, pSharedHandle);
|
||||
}
|
||||
|
||||
void MainContext::FF13_OneTimeFixes() {
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
// change a jne to jmp
|
||||
*(byte*)FF13_CONTINUOUS_SCAN_INSTRUCTION_ADDRESS = 0xEB;
|
||||
}
|
||||
|
||||
void MainContext::FF13_FixMissingEnemyScan() {
|
||||
// This patches the variables that eventually will turn into a RECT to be used in a IDirect3DDevice9::SetScissorRect call.
|
||||
// The game incorrectly uses the same values here regardless of the resolution.
|
||||
|
||||
PrintLog("Patching libra info box instructions to take in account the game resolution...");
|
||||
|
||||
const float resolutionFactor = (float)context.backbufferWidth / 1280.0F;
|
||||
|
||||
const uint32_t rectHeight = (uint32_t)ceil(130.0F * resolutionFactor);
|
||||
const uint32_t rectWidth = context.backbufferWidth;
|
||||
const uint32_t rectPosY = (uint32_t)(496.0F * resolutionFactor);
|
||||
|
||||
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 boxWidth
|
||||
*(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;
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
void MainContext::FF13_AddHookIngameFrameRateLimitSetter() {
|
||||
PrintLog("Using the ingame the instruction that sets the frame rate to get the frame rate address.");
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
bool MainContext::FF13_SetFrameRateVariables() {
|
||||
if (framePacerTargetPtr) {
|
||||
PrintLog("Frame pacer target frame rate is at address %x", framePacerTargetPtr);
|
||||
|
||||
float* ingameFrameRateFramePacerTarget = framePacerTargetPtr;
|
||||
*ingameFrameRateFramePacerTarget = MAX_FRAME_RATE_LIMIT;
|
||||
PrintLog("Frame pacer disabled.");
|
||||
|
||||
const float frameRateConfig = (float)context.config.GetFFXIIIIngameFrameRateLimit();
|
||||
const bool unlimitedFrameRate = AreAlmostTheSame(frameRateConfig, -1.0f);
|
||||
const bool shouldSetFrameRateLimit = !AreAlmostTheSame(frameRateConfig, 0.0f);
|
||||
|
||||
float frameRateLimit = 0;
|
||||
|
||||
if (unlimitedFrameRate) {
|
||||
frameRateLimit = MAX_FRAME_RATE_LIMIT;
|
||||
}
|
||||
else {
|
||||
frameRateLimit = frameRateConfig;
|
||||
}
|
||||
|
||||
if (shouldSetFrameRateLimit) {
|
||||
float* ingameFrameRateLimitPtr = framePacerTargetPtr + 1;
|
||||
*ingameFrameRateLimitPtr = frameRateLimit;
|
||||
PrintLog("Target frame rate set to %f", frameRateLimit);
|
||||
}
|
||||
}
|
||||
else {
|
||||
PrintLog("Unable to find frame rate pattern. This is normal if the game still hasn't completely started yet.");
|
||||
}
|
||||
|
||||
return framePacerTargetPtr;
|
||||
}
|
||||
|
||||
void MainContext::FF13_2_OneTimeFixes() {
|
||||
|
||||
if (*ff13_2_frame_pacer_ptr_address) {
|
||||
**ff13_2_frame_pacer_ptr_address = MAX_FRAME_RATE_LIMIT;
|
||||
PrintLog("Frame pacer disabled");
|
||||
|
||||
context.FF13_2_AddHookIngameFrameRateLimitSetter();
|
||||
context.FF13_2_RemoveContinuousControllerScan();
|
||||
context.didOneTimeFixes = true;
|
||||
}
|
||||
}
|
||||
|
||||
void MainContext::FF13_2_RemoveContinuousControllerScan() {
|
||||
// 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;
|
||||
}
|
||||
|
||||
void MainContext::FF13_2_AddHookIngameFrameRateLimitSetter() {
|
||||
if (context.AreAlmostTheSame(context.config.GetFFXIIIIngameFrameRateLimit(), 0.0F)) {
|
||||
PrintLog("Frame rate should not be changed (config = 0)");
|
||||
return;
|
||||
}
|
||||
|
||||
PrintLog("Hooking the instruction that sets the frame rate...");
|
||||
|
||||
context.ChangeMemoryProtectionToReadWriteExecute(ff13_2_set_frame_rate_address, 5);
|
||||
|
||||
// patching to: jmp FF13_2_SET_FRAME_RATE_INJECTED_CODE
|
||||
*ff13_2_set_frame_rate_address = 0xE9;
|
||||
*((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::ChangeMemoryProtectionToReadWriteExecute(void* address, const int size) {
|
||||
DWORD oldProtection;
|
||||
VirtualProtect(address, size, PAGE_EXECUTE_READWRITE, &oldProtection);
|
||||
}
|
||||
|
||||
bool MainContext::AreAlmostTheSame(float a, float b) {
|
||||
return fabs(a - b) < 0.01f;
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
#include "stdafx.h"
|
||||
#include <windows.h>
|
||||
|
||||
#include "Wrapper.h"
|
||||
|
||||
|
@ -175,6 +176,16 @@ 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) {
|
||||
PrintLog("Starting FFXIII one time RAM patches.");
|
||||
context.FF13_OneTimeFixes();
|
||||
}
|
||||
else if (context.autofix == FINAL_FANTASY_XIII2 && wcscmp(windowName.get(), L"DIEmWin") == 0) {
|
||||
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();
|
||||
|
@ -298,11 +309,6 @@ HWND WINAPI MainContext::HookCreateWindowExA(DWORD dwExStyle, LPCSTR lpClassName
|
|||
return hWnd;
|
||||
}
|
||||
|
||||
if (context.autofix == FINAL_FANTASY_XIII && !context.didOneTimeFixes) {
|
||||
PrintLog("Starting FFXIII one time RAM patches. (HookCreateWindowExA)");
|
||||
context.FFXIIIOneTimeFixes();
|
||||
}
|
||||
|
||||
if (context.CheckWindow(hWnd))
|
||||
{
|
||||
context.ApplyWndProc(hWnd);
|
||||
|
@ -321,11 +327,6 @@ HWND WINAPI MainContext::HookCreateWindowExW(DWORD dwExStyle, LPCWSTR lpClassNam
|
|||
return hWnd;
|
||||
}
|
||||
|
||||
if (context.autofix == FINAL_FANTASY_XIII && !context.didOneTimeFixes) {
|
||||
PrintLog("Starting FFXIII one time RAM patches. (HookCreateWindowExW)");
|
||||
context.FFXIIIOneTimeFixes();
|
||||
}
|
||||
|
||||
if (context.CheckWindow(hWnd))
|
||||
{
|
||||
context.ApplyWndProc(hWnd);
|
||||
|
@ -334,114 +335,3 @@ HWND WINAPI MainContext::HookCreateWindowExW(DWORD dwExStyle, LPCWSTR lpClassNam
|
|||
|
||||
return hWnd;
|
||||
}
|
||||
|
||||
void MainContext::FFXIIIOneTimeFixes() {
|
||||
|
||||
bool successSoFar = true;
|
||||
// The game repeatedly sets the frame rate limit. Disable the instruction that does it.
|
||||
successSoFar &= MainContext::FFXIIINOPIngameFrameRateLimitSetter();
|
||||
|
||||
successSoFar &= MainContext::FFXIIISetFrameRateVariables();
|
||||
|
||||
if (successSoFar) {
|
||||
context.RemoveContinuousControllerScan();
|
||||
context.FixMissingEnemyScan();
|
||||
context.didOneTimeFixes = true;
|
||||
}
|
||||
}
|
||||
|
||||
void MainContext::ChangeMemoryProtectionToReadWriteExecute(void* address, const int size) {
|
||||
DWORD oldProtection;
|
||||
VirtualProtect(address, size, PAGE_EXECUTE_READWRITE, &oldProtection);
|
||||
}
|
||||
|
||||
void MainContext::RemoveContinuousControllerScan() {
|
||||
// Disable continuous controller scanning.
|
||||
|
||||
PrintLog("Removing game slow and synchronous controller continuous controller scanning...");
|
||||
context.ChangeMemoryProtectionToReadWriteExecute(CONTINUOUS_SCAN_INSTRUCTION_ADDRESS, 1);
|
||||
// change a jne to jmp
|
||||
*(byte*)CONTINUOUS_SCAN_INSTRUCTION_ADDRESS = 0xEB;
|
||||
}
|
||||
|
||||
void MainContext::FixMissingEnemyScan() {
|
||||
// This patches the variables that eventually will turn into a RECT to be used in a IDirect3DDevice9::SetScissorRect call.
|
||||
// The game incorrectly uses the same values here regardless of the resolution.
|
||||
|
||||
PrintLog("Patching libra info box instructions to take in account the game resolution...");
|
||||
|
||||
const float resolutionFactor = (float)context.backbufferWidth / 1280.0F;
|
||||
|
||||
const uint32_t rectHeight = (uint32_t)ceil(130.0F * resolutionFactor);
|
||||
const uint32_t rectWidth = context.backbufferWidth;
|
||||
const uint32_t rectPosY = (uint32_t)(496.0F * resolutionFactor);
|
||||
|
||||
context.ChangeMemoryProtectionToReadWriteExecute(ENEMY_SCAN_BOX_CODE_ADDRESS, 18);
|
||||
|
||||
//push boxHeight
|
||||
*(byte*)(ENEMY_SCAN_BOX_CODE_ADDRESS + 0) = 0x68;
|
||||
*(uint32_t*)(ENEMY_SCAN_BOX_CODE_ADDRESS + 1) = rectHeight;
|
||||
|
||||
// push boxWidth
|
||||
*(byte*)(ENEMY_SCAN_BOX_CODE_ADDRESS + 5) = 0x68;
|
||||
*(uint32_t*)(ENEMY_SCAN_BOX_CODE_ADDRESS + 6) = rectWidth;
|
||||
|
||||
// push boxPosY
|
||||
*(byte*)(ENEMY_SCAN_BOX_CODE_ADDRESS + 10) = 0x68;
|
||||
*(uint32_t*)(ENEMY_SCAN_BOX_CODE_ADDRESS + 11) = rectPosY;
|
||||
|
||||
// NOP NOP NOP
|
||||
*(byte*)(ENEMY_SCAN_BOX_CODE_ADDRESS + 15) = 0x90;
|
||||
*(byte*)(ENEMY_SCAN_BOX_CODE_ADDRESS + 16) = 0x90;
|
||||
*(byte*)(ENEMY_SCAN_BOX_CODE_ADDRESS + 17) = 0x90;
|
||||
}
|
||||
|
||||
bool MainContext::FFXIIINOPIngameFrameRateLimitSetter() {
|
||||
PrintLog("Using the ingame the instruction that sets the frame rate to get the frame rate address.");
|
||||
|
||||
context.ChangeMemoryProtectionToReadWriteExecute(SET_FRAMERATE_INGAME_INSTRUCTION_ADDRESS, 5);
|
||||
|
||||
// patching to: mov [framePacerTargetPtr], eax
|
||||
*SET_FRAMERATE_INGAME_INSTRUCTION_ADDRESS = 0xA3;
|
||||
*((uint32_t*)(SET_FRAMERATE_INGAME_INSTRUCTION_ADDRESS + 1)) = (uint32_t)(&framePacerTargetPtr);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MainContext::FFXIIISetFrameRateVariables() {
|
||||
if (framePacerTargetPtr) {
|
||||
PrintLog("Frame pacer target frame rate is at address %x", framePacerTargetPtr);
|
||||
|
||||
float* ingameFrameRateFramePacerTarget = framePacerTargetPtr;
|
||||
*ingameFrameRateFramePacerTarget = MAX_FRAME_RATE_LIMIT;
|
||||
PrintLog("Frame pacer disabled.");
|
||||
|
||||
const float frameRateConfig = (float)context.config.GetFFXIIIIngameFrameRateLimit();
|
||||
bool unlimitedFrameRate = areAlmostTheSame(frameRateConfig, -1.0f);
|
||||
bool shouldSetFrameRateLimit = !areAlmostTheSame(frameRateConfig, 0.0f);
|
||||
|
||||
float frameRateLimit = 0;
|
||||
|
||||
if(unlimitedFrameRate){
|
||||
frameRateLimit = MAX_FRAME_RATE_LIMIT;
|
||||
}
|
||||
else {
|
||||
frameRateLimit = frameRateConfig;
|
||||
}
|
||||
|
||||
if (shouldSetFrameRateLimit) {
|
||||
float* ingameFrameRateLimitPtr = framePacerTargetPtr + 1;
|
||||
*ingameFrameRateLimitPtr = frameRateLimit;
|
||||
PrintLog("Target frame rate set to %f", frameRateLimit);
|
||||
}
|
||||
}
|
||||
else {
|
||||
PrintLog("Unable to find frame rate pattern. This is normal if the game still hasn't completely started yet.");
|
||||
}
|
||||
|
||||
return framePacerTargetPtr;
|
||||
}
|
||||
|
||||
bool MainContext::areAlmostTheSame(float a, float b) {
|
||||
return fabs(a - b) < 0.01f;
|
||||
}
|
|
@ -64,18 +64,30 @@ private:
|
|||
NONE = 0,
|
||||
RESIDENT_EVIL_4,
|
||||
KINGS_BOUNTY_LEGEND,
|
||||
FINAL_FANTASY_XIII
|
||||
FINAL_FANTASY_XIII,
|
||||
FINAL_FANTASY_XIII2,
|
||||
};
|
||||
|
||||
void EnableAutoFix();
|
||||
void FF13_2_CreateSetFrameRateCodeBlock();
|
||||
void FF13_2_InitializeGameAddresses();
|
||||
AutoFixes autofix = AutoFixes::NONE;
|
||||
|
||||
bool didOneTimeFixes = false;
|
||||
|
||||
const float MAX_FRAME_RATE_LIMIT = 250000.0F;
|
||||
byte* SET_FRAMERATE_INGAME_INSTRUCTION_ADDRESS = (byte*)0x00E8D65F;
|
||||
byte* CONTINUOUS_SCAN_INSTRUCTION_ADDRESS = (byte*)0x00820868;
|
||||
byte* ENEMY_SCAN_BOX_CODE_ADDRESS = (byte*)0x0094C920;
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
const float FF13_2_30_FPS = 30.0F;
|
||||
const float FF13_2_MAX_FRAME_CAP = 1000.0F;
|
||||
|
||||
float* framePacerTargetPtr = NULL;
|
||||
UINT backbufferWidth = 0;
|
||||
|
@ -86,13 +98,18 @@ private:
|
|||
static LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||
WNDPROC oldWndProc;
|
||||
|
||||
void FFXIIIOneTimeFixes();
|
||||
bool FFXIIINOPIngameFrameRateLimitSetter();
|
||||
bool FFXIIISetFrameRateVariables();
|
||||
void ChangeMemoryProtectionToReadWriteExecute(void* address, const int size);
|
||||
void FixMissingEnemyScan();
|
||||
void RemoveContinuousControllerScan();
|
||||
bool areAlmostTheSame(float a, float b);
|
||||
|
||||
void FF13_OneTimeFixes();
|
||||
void FF13_AddHookIngameFrameRateLimitSetter();
|
||||
bool FF13_SetFrameRateVariables();
|
||||
void FF13_FixMissingEnemyScan();
|
||||
void FF13_RemoveContinuousControllerScan();
|
||||
|
||||
void FF13_2_RemoveContinuousControllerScan();
|
||||
void FF13_2_AddHookIngameFrameRateLimitSetter();
|
||||
void FF13_2_OneTimeFixes();
|
||||
bool AreAlmostTheSame(float a, float b);
|
||||
};
|
||||
|
||||
extern MainContext context;
|
Loading…
Reference in a new issue