Skip to content
This repository was archived by the owner on Aug 23, 2025. It is now read-only.

Commit 9d79c8b

Browse files
committed
Add option to crop FMV letterboxing. Add option to remove cutscene pillarboxing/letterboxing.
1 parent 8588071 commit 9d79c8b

3 files changed

Lines changed: 61 additions & 15 deletions

File tree

ClairObscurFix.ini

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,14 @@ Enabled = true
1515

1616
;;;;;;;;;; Ultrawide/Narrower ;;;;;;;;;;
1717

18+
[Cutscene Aspect Ratio]
19+
; Removes pillarboxing/letterboxing in cutscenes.
20+
Unlocked = true
21+
1822
[Fix FOV]
1923
; Fixes cropped FOV during certain scenes at ultrawide resolutions.
2024
Enabled = true
25+
26+
[Fix Movies]
27+
; Crops letterboxing from pre-rendered movies at ultrawide resolutions.
28+
Enabled = true

src/dllmain.cpp

Lines changed: 52 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88

99
#include "SDK/Basic.hpp"
1010
#include "SDK/Engine_classes.hpp"
11+
#include "SDK/CommonUI_classes.hpp"
12+
#include "SDK/MediaAssets_classes.hpp"
1113

1214
#include "SDK/WBP_SplashScreen_Epilepsy_classes.hpp"
1315
#include "SDK/WBP_SplashScreens_Logos_classes.hpp"
@@ -20,7 +22,7 @@ HMODULE thisModule;
2022

2123
// Fix details
2224
std::string sFixName = "ClairObscurFix";
23-
std::string sFixVersion = "0.0.1";
25+
std::string sFixVersion = "0.0.2";
2426
std::filesystem::path sFixPath;
2527

2628
// Ini
@@ -50,6 +52,7 @@ bool bSkipLogos;
5052
bool bCutsceneFPS;
5153
bool bEnableConsole;
5254
bool bFixFOV;
55+
bool bFixMovies;
5356
bool bCutsceneAspectRatio;
5457

5558
// Variables
@@ -59,6 +62,7 @@ SDK::UEngine* Engine = nullptr;
5962
bool bIntroSkipped;
6063
std::string sWidgetName;
6164
SDK::UObject* WidgetObject = nullptr;
65+
static bool bIsCutscene;
6266

6367
void CalculateAspectRatio(bool bLog)
6468
{
@@ -178,14 +182,16 @@ void Configuration()
178182
inipp::get_value(ini.sections["Skip Intro Logos"], "Enabled", bSkipLogos);
179183
inipp::get_value(ini.sections["Uncap Cutscene FPS"], "Enabled", bCutsceneFPS);
180184
inipp::get_value(ini.sections["Fix FOV"], "Enabled", bFixFOV);
181-
//inipp::get_value(ini.sections["Cutscene Aspect Ratio"], "Unlocked", bCutsceneAspectRatio);
185+
inipp::get_value(ini.sections["Fix Movies"], "Enabled", bFixMovies);
186+
inipp::get_value(ini.sections["Cutscene Aspect Ratio"], "Unlocked", bCutsceneAspectRatio);
182187

183188
// Log ini parse
184189
spdlog_confparse(bEnableConsole);
185190
spdlog_confparse(bSkipLogos);
186191
spdlog_confparse(bCutsceneFPS);
187192
spdlog_confparse(bFixFOV);
188-
//spdlog_confparse(bCutsceneAspectRatio);
193+
spdlog_confparse(bFixMovies);
194+
spdlog_confparse(bCutsceneAspectRatio);
189195

190196
spdlog::info("----------");
191197
}
@@ -256,9 +262,8 @@ void CurrentResolution()
256262
}
257263
}
258264

259-
void AspectRatio()
265+
void AspectRatioFOV()
260266
{
261-
bCutsceneAspectRatio = false;
262267
if (bCutsceneAspectRatio)
263268
{
264269
// Cutscene Aspect Ratio
@@ -268,8 +273,16 @@ void AspectRatio()
268273
static SafetyHookMid CutsceneAspectRatioMidHook{};
269274
CutsceneAspectRatioMidHook = safetyhook::create_mid(CutsceneAspectRatioScanResult,
270275
[](SafetyHookContext& ctx) {
271-
if (fAspectRatio != fCutsceneAspect)
276+
// Check if forced aspect ratio is 2.39~
277+
if (std::fabs(ctx.xmm1.f32[0] - fCutsceneAspect) < 1e-5f) {
272278
ctx.xmm1.f32[0] = fAspectRatio;
279+
// We're in a cutscene now.
280+
bIsCutscene = true;
281+
}
282+
else {
283+
// If no aspect ratio is forced then we're not in a cutscene.
284+
bIsCutscene = false;
285+
}
273286
});
274287
}
275288
else {
@@ -283,23 +296,20 @@ void AspectRatio()
283296
static SafetyHookMid CutsceneFOVMidHook{};
284297
CutsceneFOVMidHook = safetyhook::create_mid(CutsceneFOVScanResult,
285298
[](SafetyHookContext& ctx) {
286-
if (fAspectRatio > fCutsceneAspect)
299+
if (bIsCutscene && fAspectRatio > fCutsceneAspect)
287300
ctx.xmm0.f32[0] = atanf(tanf(ctx.xmm0.f32[0] * (fPi / 360)) / fCutsceneAspect * fAspectRatio) * (360 / fPi);
288301
});
289302
}
290303
else {
291304
spdlog::error("Cutscenes: FOV: Pattern scan failed.");
292305
}
293306
}
294-
}
295307

296-
void FOV()
297-
{
298308
if (bFixFOV) {
299309
// AspectRatioAxisConstraint
300310
std::uint8_t* AspectRatioAxisConstraintScanResult = Memory::PatternScan(exeModule, "41 ?? ?? ?? ?? ?? 00 00 48 ?? ?? ?? ?? 00 00 4C ?? ?? 4D ?? ?? E8 ?? ?? ?? ??");
301311
if (AspectRatioAxisConstraintScanResult) {
302-
spdlog::info("AspectRatioAxisConstraint: Address is {:s}+{:x}", sExeName.c_str(), AspectRatioAxisConstraintScanResult - reinterpret_cast<std::uint8_t*>(exeModule));
312+
spdlog::info("FOV: AspectRatioAxisConstraint: Address is {:s}+{:x}", sExeName.c_str(), AspectRatioAxisConstraintScanResult - reinterpret_cast<std::uint8_t*>(exeModule));
303313
static SafetyHookMid AspectRatioAxisConstraintMidHook{};
304314
AspectRatioAxisConstraintMidHook = safetyhook::create_mid(AspectRatioAxisConstraintScanResult + 0x8,
305315
[](SafetyHookContext& ctx) {
@@ -308,7 +318,7 @@ void FOV()
308318
});
309319
}
310320
else {
311-
spdlog::error("AspectRatioAxisConstraint: Pattern scan failed.");
321+
spdlog::error("FOV: AspectRatioAxisConstraint: Pattern scan failed.");
312322
}
313323
}
314324
}
@@ -342,6 +352,35 @@ void Framerate()
342352

343353
void HUD()
344354
{
355+
if (bFixMovies) {
356+
// Video player
357+
std::uint8_t* VideoPlayerScanResult = Memory::PatternScan(exeModule, "48 89 ?? ?? 48 8B ?? 0F ?? ?? ?? 33 ?? 48 8B ?? 89 ?? ?? ?? ?? ?? ?? 0F 29 ?? ??");
358+
if (VideoPlayerScanResult) {
359+
spdlog::info("Video Player: Address is {:s}+{:x}", sExeName.c_str(), VideoPlayerScanResult - reinterpret_cast<std::uint8_t*>(exeModule));
360+
static SafetyHookMid VideoPlayerMidHook{};
361+
VideoPlayerMidHook = safetyhook::create_mid(VideoPlayerScanResult,
362+
[](SafetyHookContext& ctx) {
363+
if (!ctx.rsi) return;
364+
365+
auto videoPlayer = reinterpret_cast<SDK::UCommonVideoPlayer*>(ctx.rsi);
366+
367+
spdlog::debug("Video Player: Address is 0x{}", reinterpret_cast<uintptr_t>(videoPlayer));
368+
spdlog::debug("Video Player: Playback status changed on video: {}", videoPlayer->MediaPlayer->GetUrl().ToString());
369+
370+
// All videos except for the credits are at an aspect ratio of 2.39
371+
if (!videoPlayer->MediaPlayer->GetUrl().ToString().contains("Credit") && videoPlayer->VideoBrush.ImageSize.Y == 1088.00f) {
372+
if (fAspectRatio > fNativeAspect) {
373+
videoPlayer->VideoBrush.ImageSize.X = 1920.00f * (fCutsceneAspect / fNativeAspect);
374+
videoPlayer->VideoBrush.ImageSize.Y = 1088.00f * (fCutsceneAspect / fNativeAspect);
375+
}
376+
}
377+
});
378+
}
379+
else {
380+
spdlog::error("Video Player: Pattern scan failed.");
381+
}
382+
}
383+
345384
// Widgets
346385
std::uint8_t* UWigetAddToViewportScanResult = Memory::PatternScan(exeModule, "48 8B ?? ?? 48 8B ?? 48 85 ?? 40 0F ?? ?? 48 ?? ?? 48 89 ?? ?? 48 8B ?? 8B ?? ?? ?? ?? ?? ?? FF 90 ?? ?? ?? ??");
347386
if (UWigetAddToViewportScanResult) {
@@ -433,8 +472,7 @@ DWORD __stdcall Main(void*)
433472
Configuration();
434473
UpdateOffsets();
435474
CurrentResolution();
436-
AspectRatio();
437-
FOV();
475+
AspectRatioFOV();
438476
Framerate();
439477
HUD();
440478
EnableConsole();

xmake.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ set_optimize("smallest")
55

66
target("ClairObscurFix")
77
set_kind("shared")
8-
add_files("src/*.cpp", "src/SDK/WBP_SplashScreen_SaveWarning_functions.cpp", "src/SDK/WBP_SplashScreens_Logos_functions.cpp", "src/SDK/WBP_SplashScreen_Epilepsy_functions.cpp", "src/SDK/Engine_functions.cpp", "src/SDK/CoreUObject_functions.cpp", "src/SDK/Basic.cpp", "external/safetyhook/safetyhook.cpp", "external/safetyhook/Zydis.c")
8+
add_files("src/*.cpp", "src/SDK/MediaAssets_functions.cpp", "src/SDK/WBP_SplashScreen_SaveWarning_functions.cpp", "src/SDK/WBP_SplashScreens_Logos_functions.cpp", "src/SDK/WBP_SplashScreen_Epilepsy_functions.cpp", "src/SDK/Engine_functions.cpp", "src/SDK/CoreUObject_functions.cpp", "src/SDK/Basic.cpp", "external/safetyhook/safetyhook.cpp", "external/safetyhook/Zydis.c")
99
add_syslinks("user32")
1010
add_includedirs("external/spdlog/include", "external/inipp", "external/safetyhook")
1111
set_prefixname("")

0 commit comments

Comments
 (0)