2016-01-29 06:17:43 +13:00
|
|
|
#include "stdafx.h"
|
|
|
|
|
2021-03-13 15:51:58 +13:00
|
|
|
#include "Logger.h"
|
|
|
|
#include "MemPatch.h"
|
|
|
|
|
2016-01-29 06:17:43 +13:00
|
|
|
#include "Context.h"
|
2021-03-13 15:51:58 +13:00
|
|
|
//#include "IDirect3DVertexBuffer9.h"
|
2016-01-29 06:17:43 +13:00
|
|
|
|
|
|
|
void MainContext::EnableAutoFix()
|
|
|
|
{
|
|
|
|
std::string exe_name = ModuleNameA(NULL);
|
|
|
|
std::transform(exe_name.begin(), exe_name.end(), exe_name.begin(), std::tolower);
|
|
|
|
|
|
|
|
if (exe_name == "ffxiiiimg.exe")
|
|
|
|
{
|
2021-03-03 06:45:13 +13:00
|
|
|
autofix = AutoFixes::FINAL_FANTASY_XIII;
|
2016-01-29 06:17:43 +13:00
|
|
|
PrintLog("AutoFix for \"Final Fantasy XIII\" enabled");
|
2020-01-23 11:34:48 +13:00
|
|
|
FF13_InitializeGameAddresses();
|
2016-01-29 06:17:43 +13:00
|
|
|
}
|
2020-01-05 16:25:35 +13:00
|
|
|
|
|
|
|
if (exe_name == "ffxiii2img.exe")
|
|
|
|
{
|
2021-03-03 06:45:13 +13:00
|
|
|
autofix = AutoFixes::FINAL_FANTASY_XIII2;
|
2020-01-05 16:25:35 +13:00
|
|
|
PrintLog("AutoFix for \"Final Fantasy XIII-2\" enabled");
|
|
|
|
FF13_2_InitializeGameAddresses();
|
|
|
|
FF13_2_CreateSetFrameRateCodeBlock();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-13 15:51:58 +13:00
|
|
|
const std::map<const MainContext::AutoFixes, const uint32_t> MainContext::behaviorflags_add =
|
2016-01-29 06:17:43 +13:00
|
|
|
{
|
2021-03-03 06:45:13 +13:00
|
|
|
|
2016-01-29 06:17:43 +13:00
|
|
|
};
|
|
|
|
|
2021-03-13 15:51:58 +13:00
|
|
|
const std::map<const MainContext::AutoFixes, const uint32_t> MainContext::behaviorflags_sub =
|
|
|
|
{
|
|
|
|
//{ AutoFixes::FINAL_FANTASY_XIII, D3DCREATE_PUREDEVICE },
|
|
|
|
//{ AutoFixes::FINAL_FANTASY_XIII2, D3DCREATE_PUREDEVICE }
|
|
|
|
};
|
|
|
|
|
2016-01-29 06:17:43 +13:00
|
|
|
void MainContext::FixBehaviorFlagConflict(const DWORD flags_in, DWORD* flags_out)
|
|
|
|
{
|
|
|
|
if (flags_in & D3DCREATE_SOFTWARE_VERTEXPROCESSING)
|
|
|
|
{
|
|
|
|
*flags_out &= ~(D3DCREATE_PUREDEVICE | D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_MIXED_VERTEXPROCESSING);
|
|
|
|
*flags_out |= D3DCREATE_SOFTWARE_VERTEXPROCESSING;
|
|
|
|
}
|
|
|
|
else if (flags_in & D3DCREATE_MIXED_VERTEXPROCESSING)
|
|
|
|
{
|
|
|
|
*flags_out &= ~(D3DCREATE_PUREDEVICE | D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_SOFTWARE_VERTEXPROCESSING);
|
|
|
|
*flags_out |= D3DCREATE_MIXED_VERTEXPROCESSING;
|
|
|
|
}
|
|
|
|
else if (flags_in & D3DCREATE_HARDWARE_VERTEXPROCESSING)
|
|
|
|
{
|
|
|
|
*flags_out &= ~(D3DCREATE_MIXED_VERTEXPROCESSING | D3DCREATE_SOFTWARE_VERTEXPROCESSING);
|
|
|
|
*flags_out |= D3DCREATE_HARDWARE_VERTEXPROCESSING;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-13 15:51:58 +13:00
|
|
|
void MainContext::ApplyBehaviorFlagsFix(DWORD* flags)
|
2016-01-29 06:17:43 +13:00
|
|
|
{
|
2021-03-13 15:51:58 +13:00
|
|
|
if (autofix == AutoFixes::NONE) return;
|
|
|
|
|
|
|
|
auto&& add = behaviorflags_add.find(autofix);
|
|
|
|
if (add != behaviorflags_add.end())
|
|
|
|
FixBehaviorFlagConflict(add->second, flags);
|
2016-01-29 06:17:43 +13:00
|
|
|
|
2021-03-13 15:51:58 +13:00
|
|
|
auto&& sub = behaviorflags_sub.find(autofix);
|
|
|
|
if (sub != behaviorflags_sub.end())
|
2016-01-29 06:17:43 +13:00
|
|
|
{
|
2021-03-13 15:51:58 +13:00
|
|
|
*flags = *flags & ~sub->second;
|
|
|
|
FixBehaviorFlagConflict(sub->second, flags);
|
2016-01-29 06:17:43 +13:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-03 06:45:13 +13:00
|
|
|
HRESULT MainContext::SetScissorRect(IDirect3DDevice9* pIDirect3DDevice9, CONST RECT* rect)
|
|
|
|
{
|
|
|
|
if (rect)
|
2021-03-13 15:51:58 +13:00
|
|
|
{
|
2021-03-03 06:45:13 +13:00
|
|
|
RECT* r = const_cast<RECT*>(rect);
|
|
|
|
r->left = (LONG)(r->left * scissor_scaling_factor_w);
|
|
|
|
r->top = (LONG)(r->top * scissor_scaling_factor_h);
|
|
|
|
r->right = (LONG)(r->right * scissor_scaling_factor_w);
|
|
|
|
r->bottom = (LONG)(r->bottom * scissor_scaling_factor_h);
|
|
|
|
return pIDirect3DDevice9->SetScissorRect(r);
|
|
|
|
}
|
|
|
|
return pIDirect3DDevice9->SetScissorRect(rect);
|
2020-05-04 07:29:06 +12:00
|
|
|
}
|
|
|
|
|
2021-03-13 15:51:58 +13:00
|
|
|
// hate this workaround but we cant directly mix d3d9 include with and without defined CINTERFACE
|
|
|
|
namespace cinterface {
|
|
|
|
void VertexBufferFix(IDirect3DVertexBuffer9* pVertexBuffer);
|
|
|
|
}
|
|
|
|
|
2021-03-03 06:45:13 +13:00
|
|
|
HRESULT MainContext::CreateVertexBuffer(IDirect3DDevice9* pIDirect3DDevice9, UINT Length, DWORD Usage, DWORD FVF, D3DPOOL Pool, IDirect3DVertexBuffer9** ppVertexBuffer, HANDLE* pSharedHandle)
|
|
|
|
{
|
2021-03-13 15:51:58 +13:00
|
|
|
if (autofix == AutoFixes::FINAL_FANTASY_XIII ||
|
|
|
|
autofix == AutoFixes::FINAL_FANTASY_XIII2)
|
2021-03-03 06:45:13 +13:00
|
|
|
{
|
2020-01-12 04:13:04 +13:00
|
|
|
// Both games lock a vertex buffer 358400 before drawing any 2D element on screen (sometimes multiple times per frame)
|
|
|
|
if (Length == 358400 && Pool == D3DPOOL_MANAGED) {
|
2019-09-06 06:52:45 +12:00
|
|
|
Usage = D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY;
|
|
|
|
Pool = D3DPOOL_SYSTEMMEM;
|
2021-03-13 15:51:58 +13:00
|
|
|
HRESULT hr = pIDirect3DDevice9->CreateVertexBuffer(Length, Usage, FVF, Pool, ppVertexBuffer, pSharedHandle);
|
2019-09-01 06:58:56 +12:00
|
|
|
|
2021-03-13 15:51:58 +13:00
|
|
|
if (config.GetFFXIIIDiscardUIVertexBuffer() && ppVertexBuffer && *ppVertexBuffer)
|
|
|
|
{
|
|
|
|
//Pool = D3DPOOL_DEFAULT;
|
|
|
|
cinterface::VertexBufferFix(*ppVertexBuffer);
|
|
|
|
}
|
|
|
|
return hr;
|
|
|
|
}
|
2016-01-29 06:17:43 +13:00
|
|
|
}
|
2020-01-12 04:13:04 +13:00
|
|
|
|
2019-09-01 06:58:56 +12:00
|
|
|
return pIDirect3DDevice9->CreateVertexBuffer(Length, Usage, FVF, Pool, ppVertexBuffer, pSharedHandle);
|
2020-01-05 16:25:35 +13:00
|
|
|
}
|
2021-03-17 03:16:55 +13:00
|
|
|
HRESULT MainContext::DrawPrimitiveUP(IDirect3DDevice9* pIDirect3DDevice9, D3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount, const void* pVertexStreamZeroData, UINT VertexStreamZeroStride)
|
|
|
|
{
|
|
|
|
if (PrimitiveType == D3DPT_TRIANGLEFAN && PrimitiveCount == 2 && VertexStreamZeroStride == 20 && MatchesExpectedVertexStream((const float*)pVertexStreamZeroData)) {
|
|
|
|
return pIDirect3DDevice9->DrawPrimitiveUP(PrimitiveType, PrimitiveCount, fixedDrawPrimitiveUpVertexData, VertexStreamZeroStride);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return pIDirect3DDevice9->DrawPrimitiveUP(PrimitiveType, PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool MainContext::MatchesExpectedVertexStream(const float* pVertexStreamZeroData) {
|
|
|
|
for (int i = 0; i < 4 * 5; i++) {
|
|
|
|
if (fabs(expectedDrawPrimitiveUpVertexData[i] - pVertexStreamZeroData[i]) > 0.000001f) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2021-03-14 05:54:49 +13:00
|
|
|
bool MainContext::OneTimeFixInit(std::unique_ptr<wchar_t[]>& className, HWND hWnd)
|
2021-03-03 06:45:13 +13:00
|
|
|
{
|
|
|
|
if (wcscmp(className.get(), L"SQEX.CDev.Engine.Framework.MainWindow") == 0) {
|
2021-03-13 15:51:58 +13:00
|
|
|
otf_init = true;
|
2021-03-14 05:54:49 +13:00
|
|
|
hWndFF13 = hWnd;
|
|
|
|
return true;
|
2021-03-13 15:51:58 +13:00
|
|
|
}
|
2021-03-14 05:54:49 +13:00
|
|
|
return false;
|
2021-03-13 15:51:58 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
void MainContext::OneTimeFix()
|
|
|
|
{
|
|
|
|
if (otf_init)
|
|
|
|
{
|
|
|
|
otf_init = false;
|
2021-03-03 06:45:13 +13:00
|
|
|
std::thread fix(&context.Fix_Thread);
|
|
|
|
fix.detach();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void MainContext::Fix_Thread()
|
|
|
|
{
|
2021-03-13 15:51:58 +13:00
|
|
|
auto start = std::chrono::high_resolution_clock::now();
|
2020-02-09 09:55:23 +13:00
|
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(2000));
|
2021-03-13 15:51:58 +13:00
|
|
|
auto end = std::chrono::high_resolution_clock::now();
|
|
|
|
std::chrono::duration<double, std::milli> elapsed = end - start;
|
|
|
|
PrintLog("Waited %f ms", elapsed.count());
|
2021-03-03 06:45:13 +13:00
|
|
|
|
|
|
|
std::lock_guard<std::mutex> lock(context.fix_mutex);
|
|
|
|
if (context.autofix == AutoFixes::FINAL_FANTASY_XIII) {
|
|
|
|
PrintLog("Starting FFXIII one time RAM patches.");
|
|
|
|
context.FF13_OneTimeFixes();
|
|
|
|
}
|
|
|
|
else if (context.autofix == AutoFixes::FINAL_FANTASY_XIII2) {
|
|
|
|
PrintLog("Starting FFXIII-2 one time RAM patches.");
|
|
|
|
context.FF13_2_OneTimeFixes();
|
|
|
|
}
|
|
|
|
MessageBeep(MB_ICONASTERISK);
|
2020-02-09 09:55:23 +13:00
|
|
|
}
|
|
|
|
|
2020-01-23 11:34:48 +13:00
|
|
|
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...
|
2020-02-02 09:03:46 +13:00
|
|
|
uint8_t* baseAddr = (uint8_t*)GetModuleHandle(NULL); // Should be 400000
|
2020-01-23 11:34:48 +13:00
|
|
|
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;
|
2020-02-02 09:03:46 +13:00
|
|
|
ff13_base_controller_input_address_ptr = (uint8_t**)(baseAddr + 0x02411220);
|
2020-01-23 11:34:48 +13:00
|
|
|
ff13_vibration_low_set_zero_address = baseAddr + 0x4210DF;
|
|
|
|
ff13_vibration_high_set_zero_address = baseAddr + 0x4210F3;
|
2020-01-25 15:08:40 +13:00
|
|
|
ff13_internal_res_w = (uint32_t*)(baseAddr + 0x22E5168);
|
|
|
|
ff13_internal_res_h = ff13_internal_res_w + 1;
|
2020-05-04 07:29:06 +12:00
|
|
|
ff13_loading_screen_scissor_scaling_factor_1 = baseAddr + 0x616596;
|
|
|
|
ff13_loading_screen_scissor_scaling_factor_2 = baseAddr + 0x6165BB;
|
2020-05-04 10:00:06 +12:00
|
|
|
ff13_loading_screen_scissor_scaling_factor_3 = baseAddr + 0x61654C;
|
|
|
|
ff13_loading_screen_scissor_scaling_factor_4 = baseAddr + 0x616571;
|
2020-05-04 07:29:06 +12:00
|
|
|
ff13_settings_screen_scissor_scaling_factor = baseAddr + 0x572B26;
|
|
|
|
ff13_party_screen_scissor_scaling_factor_1 = baseAddr + 0x668DE9;
|
|
|
|
ff13_party_screen_scissor_scaling_factor_2 = baseAddr + 0x668E1E;
|
|
|
|
ff13_party_screen_scissor_scaling_factor_3 = baseAddr + 0x668E56;
|
|
|
|
ff13_party_screen_scissor_scaling_factor_4 = baseAddr + 0x668E91;
|
2021-03-17 03:17:01 +13:00
|
|
|
ff13_message_box_call_address = baseAddr + 0xA8A98F;
|
2021-03-17 04:00:04 +13:00
|
|
|
ff13_message_box_stack_push_address = baseAddr + 0xA8A982;
|
2021-03-17 03:17:01 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
void MainContext::ForceWindowActivate(const HWND hWnd) {
|
|
|
|
PostMessage(hWnd, WM_ACTIVATE, WA_INACTIVE, NULL);
|
|
|
|
PostMessage(hWnd, WM_ACTIVATE, WA_CLICKACTIVE, NULL);
|
2020-01-23 11:34:48 +13:00
|
|
|
}
|
2020-01-05 16:25:35 +13:00
|
|
|
|
2020-01-23 11:34:48 +13:00
|
|
|
void MainContext::FF13_OneTimeFixes() {
|
2021-03-14 05:54:49 +13:00
|
|
|
|
2021-03-17 03:17:01 +13:00
|
|
|
if (IsDXVK()) {
|
2021-03-17 04:00:04 +13:00
|
|
|
FF13_PatchMessageBox();
|
2021-03-17 03:17:01 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
ForceWindowActivate(hWndFF13);
|
2021-03-14 05:54:49 +13:00
|
|
|
|
2021-03-03 06:45:13 +13:00
|
|
|
FF13_NOPIngameFrameRateLimitSetter();
|
|
|
|
FF13_RemoveContinuousControllerScan();
|
|
|
|
FF13_FixScissorRect();
|
|
|
|
FF13_EnableControllerVibration();
|
|
|
|
FF13_SetFrameRateVariables();
|
2021-03-17 03:16:55 +13:00
|
|
|
AdjustVertexData(*ff13_internal_res_w, *ff13_internal_res_h);
|
2020-02-09 09:55:23 +13:00
|
|
|
|
2020-01-23 11:34:48 +13:00
|
|
|
PrintLog("Finished FF13 One Time Fixes");
|
2020-02-10 13:10:17 +13:00
|
|
|
}
|
|
|
|
|
2021-03-17 04:00:04 +13:00
|
|
|
void MainContext::FF13_PatchMessageBox()
|
|
|
|
{
|
|
|
|
PrintLog("Removing 'Quit game' textbox");
|
|
|
|
|
|
|
|
MemPatch::Nop(ff13_message_box_stack_push_address, 1);
|
|
|
|
MemPatch::Nop(ff13_message_box_stack_push_address + 1 * 4, 1);
|
|
|
|
MemPatch::Nop(ff13_message_box_stack_push_address + 2 * 4, 1);
|
|
|
|
MemPatch::Nop(ff13_message_box_stack_push_address + 3 * 4, 1);
|
|
|
|
PatchMessageBoxCall(ff13_message_box_call_address);
|
|
|
|
}
|
|
|
|
|
2020-01-23 11:34:48 +13:00
|
|
|
void MainContext::FF13_EnableControllerVibration()
|
|
|
|
{
|
|
|
|
if (!config.GetFFXIIIEnableControllerVibration()) {
|
|
|
|
PrintLog("Vibration should not be enabled (config file)");
|
|
|
|
return;
|
2020-01-05 16:25:35 +13:00
|
|
|
}
|
2020-02-02 09:03:46 +13:00
|
|
|
if (!config.GetFFXIIIDisableIngameControllerHotSwapping()) {
|
|
|
|
PrintLog("Vibration disabled because FFXIIIDisableIngameControllerHotSwapping is set to false (config file)");
|
|
|
|
return;
|
|
|
|
}
|
2020-01-23 11:34:48 +13:00
|
|
|
PrintLog("Enabling controller vibration...");
|
2021-03-03 06:45:13 +13:00
|
|
|
MemPatch::Nop(ff13_vibration_low_set_zero_address, 5);
|
|
|
|
MemPatch::Nop(ff13_vibration_high_set_zero_address, 5);
|
|
|
|
|
2021-03-10 07:43:47 +13:00
|
|
|
xinputManager = new XInputManager(ff13_base_controller_input_address_ptr, config.GetFFXIIIVibrationStrengthFactor());
|
2020-01-05 16:25:35 +13:00
|
|
|
}
|
|
|
|
|
2021-03-03 06:45:13 +13:00
|
|
|
void MainContext::FF13_RemoveContinuousControllerScan()
|
|
|
|
{
|
2020-02-02 09:03:46 +13:00
|
|
|
if (!config.GetFFXIIIDisableIngameControllerHotSwapping()) {
|
|
|
|
PrintLog("Continuous controller scanning not disabled (config)");
|
|
|
|
return;
|
|
|
|
}
|
2020-01-05 16:25:35 +13:00
|
|
|
// Disable continuous controller scanning.
|
|
|
|
|
|
|
|
PrintLog("Removing game slow and synchronous controller continuous controller scanning...");
|
|
|
|
// change a jne to jmp
|
2021-03-03 06:45:13 +13:00
|
|
|
MemPatch::Fill(ff13_continuous_scan_instruction_address, 0xEB, 1);
|
2020-01-05 16:25:35 +13:00
|
|
|
}
|
|
|
|
|
2021-03-03 06:45:13 +13:00
|
|
|
void MainContext::FF13_FixScissorRect()
|
|
|
|
{
|
2020-05-04 07:29:06 +12:00
|
|
|
PrintLog("Fixing ScissorRect...");
|
2020-05-04 10:00:06 +12:00
|
|
|
const float originalWidth = 1280.0F;
|
|
|
|
const float resolutionFactorW = (float)*ff13_internal_res_w / originalWidth;
|
|
|
|
scissor_scaling_factor_w = resolutionFactorW;
|
|
|
|
|
2020-01-25 15:08:40 +13:00
|
|
|
const float originalHeight = 720.0F;
|
|
|
|
const float resolutionFactorH = (float)*ff13_internal_res_h / originalHeight;
|
2020-05-04 10:00:06 +12:00
|
|
|
scissor_scaling_factor_h = resolutionFactorH;
|
2020-05-04 07:29:06 +12:00
|
|
|
|
|
|
|
// The game scales some scissor rects, but not all of them.
|
|
|
|
// It seems easier to neuter its internal scaling process and scale everything on our own...
|
|
|
|
|
2021-03-03 06:45:13 +13:00
|
|
|
MemPatch::Nop(ff13_loading_screen_scissor_scaling_factor_1, 3);
|
|
|
|
MemPatch::Nop(ff13_loading_screen_scissor_scaling_factor_2, 3);
|
|
|
|
MemPatch::Nop(ff13_loading_screen_scissor_scaling_factor_3, 3);
|
|
|
|
MemPatch::Nop(ff13_loading_screen_scissor_scaling_factor_4, 3);
|
|
|
|
MemPatch::Nop(ff13_settings_screen_scissor_scaling_factor, 5);
|
|
|
|
MemPatch::Nop(ff13_party_screen_scissor_scaling_factor_1, 4);
|
|
|
|
MemPatch::Nop(ff13_party_screen_scissor_scaling_factor_2, 7);
|
|
|
|
MemPatch::Nop(ff13_party_screen_scissor_scaling_factor_3, 7);
|
2021-03-11 19:31:54 +13:00
|
|
|
MemPatch::Nop(ff13_party_screen_scissor_scaling_factor_4, 7);
|
2020-01-05 16:25:35 +13:00
|
|
|
}
|
|
|
|
|
2021-03-03 06:45:13 +13:00
|
|
|
void MainContext::FF13_NOPIngameFrameRateLimitSetter()
|
|
|
|
{
|
2020-01-23 11:34:48 +13:00
|
|
|
PrintLog("NOPing the in-game instruction that sets the frame rate.");
|
2021-03-03 06:45:13 +13:00
|
|
|
MemPatch::Nop(ff13_set_framerate_ingame_instruction_address, 5);
|
2020-01-05 16:25:35 +13:00
|
|
|
}
|
|
|
|
|
2021-03-03 06:45:13 +13:00
|
|
|
void MainContext::FF13_SetFrameRateVariables()
|
|
|
|
{
|
2020-01-23 11:34:48 +13:00
|
|
|
float* framePacerTargetPtr = *ff13_frame_pacer_ptr;
|
2020-01-05 16:25:35 +13:00
|
|
|
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.");
|
|
|
|
|
2021-03-03 06:45:13 +13:00
|
|
|
if (config.GetFFXIIIIngameFrameRateLimit() != 0)
|
|
|
|
{
|
|
|
|
const s32 frameRateConfig = config.GetFFXIIIIngameFrameRateLimit();
|
|
|
|
float frameRateLimit = 0;
|
2020-01-05 16:25:35 +13:00
|
|
|
|
2021-03-03 06:45:13 +13:00
|
|
|
if (frameRateConfig == -1) {
|
|
|
|
frameRateLimit = MAX_FRAME_RATE_LIMIT;
|
|
|
|
}
|
|
|
|
else if (frameRateConfig > 0) {
|
|
|
|
frameRateLimit = (float)std::min(frameRateConfig, (s32)MAX_FRAME_RATE_LIMIT);
|
|
|
|
}
|
2020-01-05 16:25:35 +13:00
|
|
|
|
|
|
|
float* ingameFrameRateLimitPtr = framePacerTargetPtr + 1;
|
|
|
|
*ingameFrameRateLimitPtr = frameRateLimit;
|
|
|
|
PrintLog("Target frame rate set to %f", frameRateLimit);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2020-01-23 11:34:48 +13:00
|
|
|
PrintLog("Unable to find frame pacer / frame rate address. This shouldn't happen! Report this.");
|
2020-01-05 16:25:35 +13:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-03 06:45:13 +13:00
|
|
|
void MainContext::FF13_2_OneTimeFixes()
|
|
|
|
{
|
2021-03-17 03:17:01 +13:00
|
|
|
ForceWindowActivate(hWndFF13);
|
|
|
|
if (IsDXVK()) {
|
2021-03-17 04:00:04 +13:00
|
|
|
FF13_2_PatchMessageBox();
|
2021-03-17 03:17:01 +13:00
|
|
|
}
|
2021-03-14 05:54:49 +13:00
|
|
|
|
2020-01-05 16:25:35 +13:00
|
|
|
if (*ff13_2_frame_pacer_ptr_address) {
|
|
|
|
**ff13_2_frame_pacer_ptr_address = MAX_FRAME_RATE_LIMIT;
|
|
|
|
PrintLog("Frame pacer disabled");
|
2020-01-23 11:34:48 +13:00
|
|
|
|
2021-03-03 06:45:13 +13:00
|
|
|
FF13_2_AddHookIngameFrameRateLimitSetter();
|
|
|
|
FF13_2_RemoveContinuousControllerScan();
|
|
|
|
FF13_2_EnableControllerVibration();
|
2021-03-17 03:16:55 +13:00
|
|
|
AdjustVertexData(*ff13_2_internal_res_w, *ff13_2_internal_res_h);
|
2020-01-23 11:34:48 +13:00
|
|
|
PrintLog("Finished FF13-2 One Time Fixes");
|
2020-01-05 16:25:35 +13:00
|
|
|
}
|
2020-02-09 09:55:23 +13:00
|
|
|
else {
|
|
|
|
PrintLog("Unable to apply FF13-2 One Time Fixes. Report this!");
|
|
|
|
}
|
2020-01-05 16:25:35 +13:00
|
|
|
}
|
|
|
|
|
2021-03-17 04:00:04 +13:00
|
|
|
void MainContext::FF13_2_PatchMessageBox()
|
2021-03-17 03:17:01 +13:00
|
|
|
{
|
|
|
|
PrintLog("Removing 'Quit game' textbox");
|
2021-03-17 04:00:04 +13:00
|
|
|
|
|
|
|
// NOP push of registers to call MessageBox
|
|
|
|
MemPatch::Nop(ff13_2_message_box_stack_push_address, 5);
|
|
|
|
PatchMessageBoxCall(ff13_2_message_box_call_address);
|
|
|
|
}
|
|
|
|
|
|
|
|
void MainContext::PatchMessageBoxCall(uint8_t* callInstructionAddress)
|
|
|
|
{
|
2021-03-17 03:17:01 +13:00
|
|
|
const int patchSize = 6;
|
|
|
|
uint8_t patch[patchSize];
|
|
|
|
|
|
|
|
// mov eax, IDYES
|
|
|
|
patch[0] = 0xB8;
|
|
|
|
*((uint32_t*)(patch + 1)) = IDYES;
|
|
|
|
|
|
|
|
// nop
|
|
|
|
patch[5] = 0x90;
|
|
|
|
|
|
|
|
MemPatch::Patch(callInstructionAddress, patch, patchSize);
|
|
|
|
}
|
|
|
|
|
2020-01-23 11:34:48 +13:00
|
|
|
void MainContext::FF13_2_EnableControllerVibration()
|
|
|
|
{
|
|
|
|
if (!config.GetFFXIIIEnableControllerVibration()) {
|
|
|
|
PrintLog("Vibration should not be enabled (config file)");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
PrintLog("Enabling controller vibration...");
|
|
|
|
|
2021-03-03 06:45:13 +13:00
|
|
|
MemPatch::Nop(ff13_2_vibration_low_set_zero_address, 5);
|
|
|
|
MemPatch::Nop(ff13_2_vibration_high_set_zero_address, 5);
|
2020-01-23 11:34:48 +13:00
|
|
|
|
2021-03-10 07:43:47 +13:00
|
|
|
xinputManager = new XInputManager(ff13_2_base_controller_input_address_ptr, config.GetFFXIIIVibrationStrengthFactor());
|
2020-01-23 11:34:48 +13:00
|
|
|
}
|
|
|
|
|
2021-03-17 03:16:55 +13:00
|
|
|
void MainContext::AdjustVertexData(const uint32_t width, const uint32_t height)
|
|
|
|
{
|
|
|
|
const float widthHalfPixelSize = 1.0f / width;
|
|
|
|
const float heightHalfPixelSize = 1.0f / height;
|
|
|
|
for (int i = 0; i < 4; i++) {
|
|
|
|
const unsigned int rowBaseIndex = i * 5;
|
|
|
|
context.fixedDrawPrimitiveUpVertexData[rowBaseIndex] -= widthHalfPixelSize;
|
|
|
|
context.fixedDrawPrimitiveUpVertexData[1 + rowBaseIndex] += heightHalfPixelSize;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-23 11:34:48 +13:00
|
|
|
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
|
2020-02-02 09:03:46 +13:00
|
|
|
uint8_t* baseAddr = (uint8_t*)GetModuleHandle(NULL);
|
2020-01-23 11:34:48 +13:00
|
|
|
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);
|
2020-02-02 09:03:46 +13:00
|
|
|
ff13_2_base_controller_input_address_ptr = (uint8_t**)(baseAddr + 0x212A164);
|
2020-01-23 11:34:48 +13:00
|
|
|
ff13_2_vibration_low_set_zero_address = baseAddr + 0x2A7221;
|
|
|
|
ff13_2_vibration_high_set_zero_address = baseAddr + 0x2A7226;
|
2020-02-10 13:10:17 +13:00
|
|
|
ff13_2_internal_res_w = (uint32_t*)(baseAddr + 0x1FA864C);
|
|
|
|
ff13_2_internal_res_h = ff13_2_internal_res_w + 1;
|
2021-03-17 03:17:01 +13:00
|
|
|
ff13_2_message_box_call_address = baseAddr + 0x8047C0;
|
2021-03-17 04:00:04 +13:00
|
|
|
ff13_2_message_box_stack_push_address = baseAddr + 0x8047B4;
|
2020-01-23 11:34:48 +13:00
|
|
|
}
|
|
|
|
|
2021-03-03 06:45:13 +13:00
|
|
|
void MainContext::FF13_2_RemoveContinuousControllerScan()
|
|
|
|
{
|
2020-02-02 09:03:46 +13:00
|
|
|
if (!config.GetFFXIIIDisableIngameControllerHotSwapping()) {
|
|
|
|
PrintLog("Continuous controller scanning not disabled (config)");
|
|
|
|
return;
|
|
|
|
}
|
2020-01-05 16:25:35 +13:00
|
|
|
// Disable continuous controller scanning.
|
|
|
|
|
|
|
|
PrintLog("Removing game slow and synchronous controller continuous controller scanning...");
|
|
|
|
// change a jne to jmp
|
2021-03-03 06:45:13 +13:00
|
|
|
MemPatch::Fill(ff13_2_continuous_scan_instruction_address, 0xEB, 1);
|
2020-01-05 16:25:35 +13:00
|
|
|
}
|
|
|
|
|
2021-03-03 06:45:13 +13:00
|
|
|
void MainContext::FF13_2_AddHookIngameFrameRateLimitSetter()
|
|
|
|
{
|
|
|
|
if (config.GetFFXIIIIngameFrameRateLimit() == 0) {
|
2020-01-05 16:25:35 +13:00
|
|
|
PrintLog("Frame rate should not be changed (config = 0)");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
PrintLog("Hooking the instruction that sets the frame rate...");
|
|
|
|
|
2021-03-03 06:45:13 +13:00
|
|
|
MemPatch::CUnprotect unp(ff13_2_set_frame_rate_address, 5);
|
2020-01-05 16:25:35 +13:00
|
|
|
|
|
|
|
// 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;
|
|
|
|
}
|
|
|
|
|
2020-01-23 11:34:48 +13:00
|
|
|
void MainContext::FF13_2_CreateSetFrameRateCodeBlock()
|
|
|
|
{
|
|
|
|
const int blockSize = 31;
|
2021-03-03 06:45:13 +13:00
|
|
|
FF13_2_SET_FRAME_RATE_INJECTED_CODE = new(std::nothrow) uint8_t[blockSize];
|
|
|
|
if (!FF13_2_SET_FRAME_RATE_INJECTED_CODE) {
|
|
|
|
PrintLog("Failed to initialize FFXIII-2 code block");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
DWORD oldProtect;
|
|
|
|
VirtualProtect(FF13_2_SET_FRAME_RATE_INJECTED_CODE, blockSize, PAGE_EXECUTE_READWRITE, &oldProtect);
|
|
|
|
|
|
|
|
if (config.GetFFXIIIIngameFrameRateLimit() != 0)
|
|
|
|
{
|
|
|
|
const s32 frameRateConfig = config.GetFFXIIIIngameFrameRateLimit();
|
2020-01-23 11:34:48 +13:00
|
|
|
|
2021-03-03 06:45:13 +13:00
|
|
|
if (frameRateConfig == -1) {
|
|
|
|
ff13_2_targetFrameRate = FF13_2_MAX_FRAME_CAP;
|
|
|
|
}
|
|
|
|
else if (frameRateConfig > 0) {
|
|
|
|
ff13_2_targetFrameRate = (float)std::min(frameRateConfig, (s32)FF13_2_MAX_FRAME_CAP);
|
|
|
|
}
|
2020-01-23 11:34:48 +13:00
|
|
|
|
2021-03-03 06:45:13 +13:00
|
|
|
PrintLog("Target frame rate set to %f", ff13_2_targetFrameRate);
|
2020-01-23 11:34:48 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
// 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;
|
|
|
|
}
|
|
|
|
|
2020-01-12 04:23:50 +13:00
|
|
|
void MainContext::PrintVersionInfo() {
|
2021-03-21 06:05:34 +13:00
|
|
|
PrintLog("FF13Fix 1.6.1 https://github.com/rebtd7/FF13Fix");
|
2020-01-12 04:23:50 +13:00
|
|
|
}
|