Add FF13 fixes
This commit is contained in:
parent
b129645128
commit
68b6d20da6
|
@ -39,9 +39,9 @@ Config::Config()
|
|||
|
||||
MainContext::MainContext() : oldWndProc(nullptr)
|
||||
{
|
||||
LogFile("OneTweakNG.log");
|
||||
LogFile("FF13Fix.log");
|
||||
|
||||
if(config.GetAutoFix()) EnableAutoFix();
|
||||
if (config.GetAutoFix()) EnableAutoFix();
|
||||
|
||||
MH_Initialize();
|
||||
|
||||
|
@ -66,7 +66,7 @@ MainContext::~MainContext()
|
|||
while (::ShowCursor(TRUE) <= 0);
|
||||
}
|
||||
|
||||
IDirect3D9 * WINAPI MainContext::HookDirect3DCreate9(UINT SDKVersion)
|
||||
IDirect3D9* WINAPI MainContext::HookDirect3DCreate9(UINT SDKVersion)
|
||||
{
|
||||
IDirect3D9* d3d9 = context.TrueDirect3DCreate9(SDKVersion);
|
||||
if (d3d9)
|
||||
|
@ -108,9 +108,17 @@ bool MainContext::ApplyPresentationParameters(D3DPRESENT_PARAMETERS* pPresentati
|
|||
{
|
||||
if (pPresentationParameters)
|
||||
{
|
||||
if (config.GetTrippleBuffering())
|
||||
context.backbufferWidth = pPresentationParameters->BackBufferWidth;
|
||||
if (config.GetTripleBuffering())
|
||||
{
|
||||
pPresentationParameters->BackBufferCount = 3;
|
||||
PrintLog("BackBufferCount: BackBufferCount set to %u", pPresentationParameters->BackBufferCount);
|
||||
}
|
||||
|
||||
if ((s32)config.GetFullScreenRefreshRate() >= 0 && pPresentationParameters->FullScreen_RefreshRateInHz != 0)
|
||||
{
|
||||
PrintLog("Changing refresh rate from %u to %u", pPresentationParameters->FullScreen_RefreshRateInHz, config.GetFullScreenRefreshRate());
|
||||
pPresentationParameters->FullScreen_RefreshRateInHz = config.GetFullScreenRefreshRate();
|
||||
}
|
||||
|
||||
if (config.GetMultisample() > 0)
|
||||
|
@ -128,6 +136,12 @@ bool MainContext::ApplyPresentationParameters(D3DPRESENT_PARAMETERS* pPresentati
|
|||
PrintLog("PresentationInterval: PresentationInterval set to %u", pPresentationParameters->PresentationInterval);
|
||||
}
|
||||
|
||||
if ((s32)config.GetSwapEffect() != -1)
|
||||
{
|
||||
pPresentationParameters->SwapEffect = (D3DSWAPEFFECT)config.GetSwapEffect();
|
||||
PrintLog("SwapEffect: SwapEffect set to %u", pPresentationParameters->SwapEffect);
|
||||
}
|
||||
|
||||
if (config.GetBorderless())
|
||||
{
|
||||
int cx = GetSystemMetrics(SM_CXSCREEN);
|
||||
|
@ -302,6 +316,11 @@ 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.");
|
||||
context.FFXIIIOneTimeFixes();
|
||||
}
|
||||
|
||||
if (context.CheckWindow(hWnd))
|
||||
{
|
||||
context.ApplyWndProc(hWnd);
|
||||
|
@ -310,3 +329,114 @@ 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;
|
||||
}
|
|
@ -7,8 +7,8 @@
|
|||
|
||||
struct hkIDirect3D9;
|
||||
|
||||
static const char* inifilename = "OneTweakNG.ini";
|
||||
#define CONFIG_VERSION 3
|
||||
static const char* inifilename = "FF13Fix.ini";
|
||||
#define CONFIG_VERSION 4
|
||||
|
||||
class Config
|
||||
{
|
||||
|
@ -70,11 +70,29 @@ private:
|
|||
void EnableAutoFix();
|
||||
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;
|
||||
|
||||
float* framePacerTargetPtr = NULL;
|
||||
UINT backbufferWidth = 0;
|
||||
|
||||
void FixBehaviorFlagConflict(const DWORD flags_in, DWORD* flags_out);
|
||||
static const std::map<const AutoFixes, const uint32_t> behaviorflags_fixes;
|
||||
|
||||
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);
|
||||
};
|
||||
|
||||
extern MainContext context;
|
|
@ -1,6 +1,8 @@
|
|||
|
||||
SETTING(u32, LongValue, PresentationInterval, Options, -1);
|
||||
SETTING(bool, BoolValue, TrippleBuffering, Options, false);
|
||||
SETTING(u32, LongValue, PresentationInterval, Options, 1);
|
||||
SETTING(bool, BoolValue, TripleBuffering, Options, true);
|
||||
SETTING(u32, LongValue, FullScreenRefreshRate, Options, 0);
|
||||
SETTING(u32, LongValue, SwapEffect, Options, -1);
|
||||
SETTING(bool, BoolValue, AlwaysActive, Options, false);
|
||||
SETTING(bool, BoolValue, AutoFix, Options, true);
|
||||
SETTING(u32, LongValue, Multisample, Options, 0);
|
||||
|
@ -8,6 +10,8 @@ SETTING(bool, BoolValue, HideCursor, Options, false);
|
|||
SETTING(bool, BoolValue, ForceHideCursor, Options, false);
|
||||
SETTING(u32, LongValue, BehaviorFlags, Options, 0);
|
||||
|
||||
SETTING(double, DoubleValue, FFXIIIIngameFrameRateLimit, Options, -1.0);
|
||||
|
||||
SETTING(bool, BoolValue, Adapter, Adapter, false);
|
||||
SETTING(u32, LongValue, VendorId, Adapter, 0);
|
||||
SETTING(u32, LongValue, DeviceId, Adapter, 0);
|
||||
|
|
Loading…
Reference in a new issue