[FF13] Allow usage of 4GB memory patch
This commit is contained in:
parent
511e343535
commit
240ee9a015
12
README.md
12
README.md
|
@ -43,11 +43,19 @@ This considerably improves the frame rate when 2D elements are being disabled on
|
||||||
## Fix the enemy scan text on resolutions over 720p (FFXIII only)
|
## Fix the enemy scan text on resolutions over 720p (FFXIII only)
|
||||||
The game calls [SetScissorRect](https://docs.microsoft.com/en-us/windows/win32/api/d3d9helper/nf-d3d9helper-idirect3ddevice9-setscissorrect) using a rectangle hardcoded with the 720p coordenates. This correct the coordenates and rectangle size in order to fix it.
|
The game calls [SetScissorRect](https://docs.microsoft.com/en-us/windows/win32/api/d3d9helper/nf-d3d9helper-idirect3ddevice9-setscissorrect) using a rectangle hardcoded with the 720p coordenates. This correct the coordenates and rectangle size in order to fix it.
|
||||||
|
|
||||||
## Reporting issues
|
# Usage with the 4GB Large Address Aware patch
|
||||||
|
You may wish to patch the games to allow them to access more than 4GB of RAM. This seems to avoid crashes in FF13-2 (and may help FF13 under some configurations).
|
||||||
|
## FF13:
|
||||||
|
* Create a copy of the unpatched ```ffxiiiimg.exe``` to the folder ```FINAL FANTASY XIII\white_data\prog\win\bin```. Name it ```untouched.exe```.
|
||||||
|
* Patch the original ```ffxiiiimg.exe``` (you can use https://ntcore.com/?page_id=371)
|
||||||
|
## FF13-2:
|
||||||
|
* Patch ```ffxiii2img.exe``` (you can use https://ntcore.com/?page_id=371)
|
||||||
|
|
||||||
|
# Reporting issues
|
||||||
* Please specify what game are you talking about, which mods are you using (dxvk?) post system specs, and post FF13Fix.log
|
* Please specify what game are you talking about, which mods are you using (dxvk?) post system specs, and post FF13Fix.log
|
||||||
* Add a save file and steps to reproduce the issue if possible
|
* Add a save file and steps to reproduce the issue if possible
|
||||||
|
|
||||||
## Other notes
|
# Other notes
|
||||||
* This is currently not compatible with GeDoSaTo.
|
* This is currently not compatible with GeDoSaTo.
|
||||||
* I strongly recommend forcing anisotropic filtering on your GPU driver to improve the quality of the textures.
|
* I strongly recommend forcing anisotropic filtering on your GPU driver to improve the quality of the textures.
|
||||||
* Using "Maximum Performance" power management in the GPU driver can also help keeping the frame rate smooth.
|
* Using "Maximum Performance" power management in the GPU driver can also help keeping the frame rate smooth.
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
#include "MemPatch.h"
|
#include "MemPatch.h"
|
||||||
|
|
||||||
#include "Context.h"
|
#include "Context.h"
|
||||||
//#include "IDirect3DVertexBuffer9.h"
|
#include <MinHook.h>
|
||||||
|
|
||||||
void MainContext::EnableAutoFix()
|
void MainContext::EnableAutoFix()
|
||||||
{
|
{
|
||||||
|
@ -16,6 +16,7 @@ void MainContext::EnableAutoFix()
|
||||||
autofix = AutoFixes::FINAL_FANTASY_XIII;
|
autofix = AutoFixes::FINAL_FANTASY_XIII;
|
||||||
PrintLog("AutoFix for \"Final Fantasy XIII\" enabled");
|
PrintLog("AutoFix for \"Final Fantasy XIII\" enabled");
|
||||||
FF13_InitializeGameAddresses();
|
FF13_InitializeGameAddresses();
|
||||||
|
FF13_HandleLargeAddressAwarePatch();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (exe_name == "ffxiii2img.exe")
|
if (exe_name == "ffxiii2img.exe")
|
||||||
|
@ -38,6 +39,67 @@ const std::map<const MainContext::AutoFixes, const uint32_t> MainContext::behavi
|
||||||
//{ AutoFixes::FINAL_FANTASY_XIII2, D3DCREATE_PUREDEVICE }
|
//{ AutoFixes::FINAL_FANTASY_XIII2, D3DCREATE_PUREDEVICE }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
HANDLE WINAPI MainContext::HookCreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile) {
|
||||||
|
const char* ffxiiiimgPrt = strstr(lpFileName, "ffxiiiimg.exe");
|
||||||
|
if (ffxiiiimgPrt) {
|
||||||
|
PrintLog("HookCreateFileA Before Replacement: %s", lpFileName);
|
||||||
|
|
||||||
|
int arrayPosition = ffxiiiimgPrt - lpFileName;
|
||||||
|
int len = strlen(lpFileName);
|
||||||
|
char* newFileName = new char[len + 1];
|
||||||
|
strcpy_s(newFileName, len + 1, lpFileName);
|
||||||
|
const char* untouched = "untouched"; // needs to have the size of "ffxiiiimg"
|
||||||
|
|
||||||
|
memcpy(newFileName + arrayPosition, untouched, strlen(untouched));
|
||||||
|
PrintLog("HookCreateFileA After Replacement: %s", newFileName);
|
||||||
|
MH_STATUS disableHookCreateFileA = MH_DisableHook(CreateFileA);
|
||||||
|
PrintLog("disableHookCreateFileA = %d", disableHookCreateFileA);
|
||||||
|
MH_STATUS disableHookCreateFileW = MH_DisableHook(CreateFileW);
|
||||||
|
PrintLog("disableHookCreateFileW = %d", disableHookCreateFileW);
|
||||||
|
if (GetFileAttributesA(newFileName) == INVALID_FILE_ATTRIBUTES) {
|
||||||
|
PrintLog("ERROR: Unable to get attributes of %s. Does the file exist?", newFileName);
|
||||||
|
}
|
||||||
|
HANDLE fileHandle = context.TrueCreateFileA(newFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);;
|
||||||
|
delete[] newFileName;
|
||||||
|
PrintLog("Returning File Handle");
|
||||||
|
return fileHandle;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return context.TrueCreateFileA(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HANDLE WINAPI MainContext::HookCreateFileW(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile) {
|
||||||
|
const wchar_t* ffxiiiimgPrt = wcsstr(lpFileName, L"ffxiiiimg.exe");;
|
||||||
|
|
||||||
|
if (ffxiiiimgPrt) {
|
||||||
|
PrintLog("HookCreateFileW Before Replacement: %s", lpFileName);
|
||||||
|
|
||||||
|
int arrayPosition = ffxiiiimgPrt - lpFileName;
|
||||||
|
int len = wcslen(lpFileName);
|
||||||
|
wchar_t* newFileName = new wchar_t[len + 1];
|
||||||
|
wcscpy_s(newFileName, len + 1, lpFileName);
|
||||||
|
const wchar_t* untouched = L"untouched"; //needs to have the size of L"ffxiiiimg"
|
||||||
|
wmemcpy(newFileName + arrayPosition, untouched, wcslen(untouched));
|
||||||
|
PrintLog("HookCreateFileW After Replacement: %s", newFileName);
|
||||||
|
MH_STATUS disableHookCreateFileA = MH_DisableHook(CreateFileA);
|
||||||
|
PrintLog("disableHookCreateFileA = %d", disableHookCreateFileA);
|
||||||
|
MH_STATUS disableHookCreateFileW = MH_DisableHook(CreateFileW);
|
||||||
|
PrintLog("disableHookCreateFileW = %d", disableHookCreateFileW);
|
||||||
|
if (GetFileAttributesW(newFileName) == INVALID_FILE_ATTRIBUTES) {
|
||||||
|
PrintLog("ERROR: Unable to get attributes of %s. Does the file exist?", newFileName);
|
||||||
|
}
|
||||||
|
HANDLE fileHandle = context.TrueCreateFileW(newFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);;
|
||||||
|
delete[] newFileName;
|
||||||
|
PrintLog("Returning File Handle");
|
||||||
|
return fileHandle;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return context.TrueCreateFileW(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void MainContext::FixBehaviorFlagConflict(const DWORD flags_in, DWORD* flags_out)
|
void MainContext::FixBehaviorFlagConflict(const DWORD flags_in, DWORD* flags_out)
|
||||||
{
|
{
|
||||||
if (flags_in & D3DCREATE_SOFTWARE_VERTEXPROCESSING)
|
if (flags_in & D3DCREATE_SOFTWARE_VERTEXPROCESSING)
|
||||||
|
@ -199,6 +261,38 @@ void MainContext::FF13_InitializeGameAddresses()
|
||||||
ff13_party_screen_scissor_scaling_factor_4 = baseAddr + 0x668E91;
|
ff13_party_screen_scissor_scaling_factor_4 = baseAddr + 0x668E91;
|
||||||
ff13_message_box_call_address = baseAddr + 0xA8A98F;
|
ff13_message_box_call_address = baseAddr + 0xA8A98F;
|
||||||
ff13_message_box_stack_push_address = baseAddr + 0xA8A982;
|
ff13_message_box_stack_push_address = baseAddr + 0xA8A982;
|
||||||
|
ff13_exe_large_address_aware_flag_address = baseAddr + 0x126;
|
||||||
|
ff13_exe_checksum_address = baseAddr + 0x168;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainContext::FF13_HandleLargeAddressAwarePatch() {
|
||||||
|
const uint8_t laaMask = 0x20;
|
||||||
|
if (*ff13_exe_large_address_aware_flag_address && laaMask) {
|
||||||
|
PrintLog("LargeAddressAwarePatch found. Make sure untouched.exe is an unmodified copy of ffxiiiimg.exe");
|
||||||
|
const MH_STATUS createHookCreateFileA = MH_CreateHook(CreateFileA, HookCreateFileA, reinterpret_cast<void**>(&TrueCreateFileA));
|
||||||
|
PrintLog("createHookCreateFileA = %d", createHookCreateFileA);
|
||||||
|
const MH_STATUS enableHookCreateFileA = MH_EnableHook(CreateFileA);
|
||||||
|
PrintLog("enableHookCreateFileA = %d", enableHookCreateFileA);
|
||||||
|
|
||||||
|
const MH_STATUS createHookCreateFileW = MH_CreateHook(CreateFileW, HookCreateFileW, reinterpret_cast<void**>(&TrueCreateFileW));
|
||||||
|
PrintLog("createHookCreateFileW = %d", createHookCreateFileW);
|
||||||
|
const MH_STATUS enableHookCreateFileW = MH_EnableHook(CreateFileW);
|
||||||
|
PrintLog("enableHookCreateFileW = %d", enableHookCreateFileW);
|
||||||
|
|
||||||
|
uint8_t new_ff13_exe_large_address_aware_flag = *ff13_exe_large_address_aware_flag_address & ~laaMask;
|
||||||
|
MemPatch::Patch(ff13_exe_large_address_aware_flag_address, &new_ff13_exe_large_address_aware_flag, 1);
|
||||||
|
PrintLog("LargeAddressAware patched back = %d", *ff13_exe_large_address_aware_flag_address);
|
||||||
|
|
||||||
|
uint32_t new_ff13_exe_checksum = 0;
|
||||||
|
MemPatch::Patch(ff13_exe_checksum_address, &new_ff13_exe_checksum, sizeof(uint32_t));
|
||||||
|
PrintLog("Checksum patched back = %d", *ff13_exe_checksum_address);
|
||||||
|
|
||||||
|
PrintLog("LargeAddressAwarePatch handled");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
PrintLog("LargeAddressAwarePatch not found.");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainContext::ForceWindowActivate(const HWND hWnd) {
|
void MainContext::ForceWindowActivate(const HWND hWnd) {
|
||||||
|
|
|
@ -50,8 +50,6 @@ MainContext::MainContext()
|
||||||
LogFile("FF13Fix.log");
|
LogFile("FF13Fix.log");
|
||||||
context.PrintVersionInfo();
|
context.PrintVersionInfo();
|
||||||
|
|
||||||
if (config.GetOptionsAutoFix()) EnableAutoFix();
|
|
||||||
|
|
||||||
PrintLog("Enabling hooks:");
|
PrintLog("Enabling hooks:");
|
||||||
const MH_STATUS initializeHooks = MH_Initialize();
|
const MH_STATUS initializeHooks = MH_Initialize();
|
||||||
PrintLog("initializeHooks = %d", initializeHooks);
|
PrintLog("initializeHooks = %d", initializeHooks);
|
||||||
|
@ -80,6 +78,8 @@ MainContext::MainContext()
|
||||||
PrintLog("createHookSetWindowLongW = %d", createHookSetWindowLongW);
|
PrintLog("createHookSetWindowLongW = %d", createHookSetWindowLongW);
|
||||||
const MH_STATUS enableHookSetWindowLongW = MH_EnableHook(SetWindowLongW);
|
const MH_STATUS enableHookSetWindowLongW = MH_EnableHook(SetWindowLongW);
|
||||||
PrintLog("enableHookSetWindowLongW = %d", enableHookSetWindowLongW);
|
PrintLog("enableHookSetWindowLongW = %d", enableHookSetWindowLongW);
|
||||||
|
|
||||||
|
if (config.GetOptionsAutoFix()) EnableAutoFix();
|
||||||
}
|
}
|
||||||
|
|
||||||
MainContext::~MainContext()
|
MainContext::~MainContext()
|
||||||
|
|
|
@ -41,6 +41,8 @@ class MainContext
|
||||||
DECLARE_HOOK(HWND, WINAPI, CreateWindowExW, DWORD dwExStyle, LPCWSTR lpClassName, LPCWSTR lpWindowName,
|
DECLARE_HOOK(HWND, WINAPI, CreateWindowExW, DWORD dwExStyle, LPCWSTR lpClassName, LPCWSTR lpWindowName,
|
||||||
DWORD dwStyle, int X, int Y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam);
|
DWORD dwStyle, int X, int Y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam);
|
||||||
|
|
||||||
|
DECLARE_HOOK(HANDLE, WINAPI, CreateFileA, LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile);
|
||||||
|
DECLARE_HOOK(HANDLE, WINAPI, CreateFileW, LPCWSTR lpFileName,DWORD dwDesiredAccess,DWORD dwShareMode,LPSECURITY_ATTRIBUTES lpSecurityAttributes,DWORD dwCreationDisposition,DWORD dwFlagsAndAttributes,HANDLE hTemplateFile);
|
||||||
public:
|
public:
|
||||||
MainContext();
|
MainContext();
|
||||||
virtual ~MainContext();
|
virtual ~MainContext();
|
||||||
|
@ -95,6 +97,8 @@ private:
|
||||||
uint8_t* ff13_party_screen_scissor_scaling_factor_4 = NULL;
|
uint8_t* ff13_party_screen_scissor_scaling_factor_4 = NULL;
|
||||||
uint8_t* ff13_message_box_stack_push_address = NULL;
|
uint8_t* ff13_message_box_stack_push_address = NULL;
|
||||||
uint8_t* ff13_message_box_call_address = NULL;
|
uint8_t* ff13_message_box_call_address = NULL;
|
||||||
|
uint8_t* ff13_exe_large_address_aware_flag_address = NULL;
|
||||||
|
uint8_t* ff13_exe_checksum_address = NULL;
|
||||||
uint32_t* ff13_internal_res_w;
|
uint32_t* ff13_internal_res_w;
|
||||||
uint32_t* ff13_internal_res_h;
|
uint32_t* ff13_internal_res_h;
|
||||||
|
|
||||||
|
@ -151,6 +155,7 @@ private:
|
||||||
void FF13_SetFrameRateVariables();
|
void FF13_SetFrameRateVariables();
|
||||||
void FF13_FixScissorRect();
|
void FF13_FixScissorRect();
|
||||||
void FF13_RemoveContinuousControllerScan();
|
void FF13_RemoveContinuousControllerScan();
|
||||||
|
void FF13_HandleLargeAddressAwarePatch();
|
||||||
|
|
||||||
void FF13_2_CreateSetFrameRateCodeBlock();
|
void FF13_2_CreateSetFrameRateCodeBlock();
|
||||||
void FF13_2_InitializeGameAddresses();
|
void FF13_2_InitializeGameAddresses();
|
||||||
|
|
Loading…
Reference in New Issue