Files

190 lines
7.3 KiB
C++
Raw Permalink Normal View History

2026-03-01 19:06:48 +01:00
#include "CommonHeaders.h"
#include "UEngine.hpp"
#include "Logger.hpp"
// Constants
const std::string PLUGIN_NAME = "TalesOfBerseria";
const std::string PLUGIN_LOG = PLUGIN_NAME + ".log";
// Logger
std::shared_ptr<spdlog::logger> logger;
// Screen informations
static int g_CurrentWidth = 1;
static int g_CurrentHeight = 1;
static float aspectRatio = 1.77778;
// Plugin states
static bool AOBScanDone = false;
static bool g_fix_enabled = false;
static bool g_fov_fix_enabled = false;
static bool g_ultrawide_fix_enabled = false;
static int g_AdditionalFOVValue = 0;
static std::atomic<bool> g_coreReady = false;
// Shared values
static float g_FOV_In = 45.f;
static float g_FOV_Out = 45.f;
// AOB Scan pointers
static uint8_t* FOVaddress = nullptr;
static uint8_t* UltraWideaddress = nullptr;
static uint8_t* Resolutionaddress = nullptr;
static uint8_t* pluginDLLModule = nullptr;
static uint8_t* GameAssemblyDLLModule = nullptr;
2026-03-01 19:06:48 +01:00
// Hooking
static SafetyHookMid FOVHook{};
static SafetyHookMid UWHook{};
static SafetyHookMid ResolutionHook1{};
static SafetyHookMid ResolutionHook2{};
// Prototypes
static void FOVFixEnabled();
static void UltraWideFixEnabled();
static void GetGameResolution();
extern "C" __declspec(dllexport) void SetFixEnabled(bool enabled, bool init) {
if (!pluginDLLModule) return;
g_fix_enabled = enabled;
if (!AOBScanDone) { // Unity Engine
logger->info("--------------- AOB scan started ---------------");
constexpr auto FOVStringObfuscated = make_obfuscated<0x5E>("F3 0F 59 ?? ?? ?? ?? ?? F3 0F 5E ?? ?? ?? ?? ?? F3 0F 11 ?? ?? ?? ?? ?? 48 8B ?? ?? ?? 48 ?? ?? E8");
constexpr auto UWStringObfuscated = make_obfuscated<0x41>("F3 0F 10 ?? ?? F3 0F 10 ?? ?? 0F 2E ?? 7A ?? 74 ?? F3 0F 11 ?? ?? C6 41 ?? ?? F3 0F 10");
constexpr auto ResolutionStringObfuscated = make_obfuscated<0x57>("F3 0F 11 ?? ?? ?? ?? ?? E8 ?? ?? ?? ?? 8B C0 0F 57 ?? 0F 57 ?? 0F 11");
logger->info("Scanning region: {} - {}", (void*)pluginDLLModule, (void*)(pluginDLLModule + MAXINT));
FOVaddress = Memory::AOBScanRange(pluginDLLModule, "FOV", MAXINT, FOVStringObfuscated, PAGE_EXECUTE_READ, logger);
UltraWideaddress = Memory::AOBScanRange(pluginDLLModule, "Ultrawide", MAXINT, UWStringObfuscated, PAGE_EXECUTE_READ, logger);
Resolutionaddress = Memory::AOBScanRange(pluginDLLModule, "Screen resolution", MAXINT, ResolutionStringObfuscated, PAGE_EXECUTE_READ, logger);
if (FOVaddress && UltraWideaddress)
logger->info("All AOB signatures found. Ready to patch...");
logger->info("-------------- Fixes initialisation -------------");
AOBScanDone = true;
}
if (!init && FOVaddress) FOVFixEnabled();
if (!init && UltraWideaddress) UltraWideFixEnabled();
GetGameResolution();
}
extern "C" __declspec(dllexport) bool IsCoreReady() {
return g_coreReady;
}
extern "C" __declspec(dllexport) void InitializeCore() {
logger->info("---------- Unity IL2CPP intializating ----------");
std::thread([]() {
HMODULE hModule = nullptr;
for (int i = 0; i < 100; ++i) { // gives 10 seconds to find UE Engine
std::this_thread::sleep_for(std::chrono::milliseconds(100));
hModule = GetModuleHandleA("TLSampleViewerTO12.dll");
if (hModule) break;
}
if (hModule) {
pluginDLLModule = reinterpret_cast<uint8_t*>(hModule);
g_coreReady = true;
logger->info("Core ready.");
}
}).detach();
std::thread([]() {
HMODULE hModule = nullptr;
for (int i = 0; i < 100; ++i) { // gives 10 seconds to find Unity GameAssembly.dll
std::this_thread::sleep_for(std::chrono::milliseconds(100));
hModule = GetModuleHandleA("GameAssembly.dll");
if (hModule) break;
}
if (hModule) {
GameAssemblyDLLModule = reinterpret_cast<uint8_t*>(hModule);
logger->debug("GameAssembly loaded @ {}", (void*)GameAssemblyDLLModule);
}
}).detach();
2026-03-01 19:06:48 +01:00
}
// Setters for Reshade addon call
extern "C" __declspec(dllexport) void SetFixesEnabled(GameFixes fix, bool enabled) { // Set each fix individually
if (fix == GameFixes::FOV) { g_fov_fix_enabled = enabled; FOVFixEnabled(); }
if (fix == GameFixes::UltraWide) { g_ultrawide_fix_enabled = enabled; UltraWideFixEnabled(); }
if (fix == GameFixes::None) { logger->info("------------------ User inputs ------------------"); }
}
extern "C" __declspec(dllexport) void SetValues(GameSetting setting, float value) {
if (setting == GameSetting::FOV) g_AdditionalFOVValue = (int)(value);
}
// Getters for Reshade addon call
extern "C" __declspec(dllexport) void GetGameInfos(GameInfos* infos) {
if (!infos) return;
infos->FOVIn = g_FOV_In;
infos->FOVOut = g_FOV_Out;
infos->screenWidth = g_CurrentWidth;
infos->screenHeight = g_CurrentHeight;
infos->aspectRatio = aspectRatio;
}
// Hook injections
static void GetGameResolution() {
if (Resolutionaddress && !ResolutionHook1 && !ResolutionHook2) {
ResolutionHook1 = safetyhook::create_mid(Resolutionaddress,
[](SafetyHookContext& ctx) {
g_CurrentWidth = (int)ctx.xmm0.f32[0];
});
ResolutionHook2 = safetyhook::create_mid(Resolutionaddress + 0x1f,
[](SafetyHookContext& ctx) {
g_CurrentHeight = (int)ctx.xmm0.f32[0];
});
}
}
static void FOVFixEnabled() {
if (g_fix_enabled && g_fov_fix_enabled && FOVaddress) {
if (!FOVHook) { // Hook only once
FOVHook = safetyhook::create_mid(FOVaddress,
[](SafetyHookContext& ctx) {
aspectRatio = (float)g_CurrentWidth / g_CurrentHeight;
g_FOV_In = Maths::FOVVToH(ctx.xmm1.f32[0], aspectRatio);
float targetFovH = g_FOV_In + (g_fix_enabled && g_fov_fix_enabled ? g_AdditionalFOVValue : 0.f);
float targetFovV = Maths::FOVHToV(targetFovH, aspectRatio);
ctx.xmm1.f32[0] = targetFovV;
g_FOV_Out = targetFovH;
});
}
else FOVHook.enable();
}
if (!(g_fix_enabled && g_fov_fix_enabled) && FOVaddress)
if (FOVHook) FOVHook.disable();
logger->info("FOV fix {}", g_fix_enabled && g_fov_fix_enabled ? "enabled" : "disabled");
}
static void UltraWideFixEnabled() {
if (g_fix_enabled && g_ultrawide_fix_enabled && UltraWideaddress) {
if (!UWHook) {
UWHook = safetyhook::create_mid(UltraWideaddress + 0x5,
[](SafetyHookContext& ctx) {
ctx.xmm1.f32[0] = aspectRatio;
});
}
else UWHook.enable();
}
if (!(g_fix_enabled && g_ultrawide_fix_enabled) && UltraWideaddress)
if (UWHook) UWHook.disable();
logger->info("Ultrawide fix {}", g_fix_enabled && g_ultrawide_fix_enabled ? "enabled" : "disabled");
}
// Standard dll entry
BOOL APIENTRY DllMain(HMODULE hModule, DWORD reason, LPVOID) {
if (reason == DLL_PROCESS_ATTACH) {
logger = InitializeLogger("Tales Of Berseria", PLUGIN_LOG);
logger->info("Plugin {} loaded.", PLUGIN_NAME);
}
else if (reason == DLL_PROCESS_DETACH) {
logger->info("Plugin {} unloaded.", PLUGIN_NAME);
spdlog::drop_all();
}
return TRUE;
}