Skip to content

Commit 0608fd6

Browse files
committed
ThePolarExpress:
- Fixed the bink videos playing with a black screen when a high enough resolution is used - Fixed the cropped videos
1 parent e5e1276 commit 0608fd6

1 file changed

Lines changed: 66 additions & 32 deletions

File tree

source/fixes/ThePolarExpressWidescreenFix/dllmain.cpp

Lines changed: 66 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ class PolarExpressFix final : public FixBase
2424

2525
const char* FixVersion() const override
2626
{
27-
return "1.2";
27+
return "1.3";
2828
}
2929

3030
const char* TargetName() const override
@@ -74,24 +74,59 @@ class PolarExpressFix final : public FixBase
7474

7575
if (Util::stringcmp_caseless(ExeName(), "PolarExpress.exe"))
7676
{
77-
auto ResolutionScanResult = Memory::PatternScan(ExeModule(), "8B 08 89 0D ?? ?? ?? ?? 8B 50");
78-
if (ResolutionScanResult)
77+
auto ResolutionScansResult = Memory::PatternScan(ExeModule(), "8B 08 89 0D ?? ?? ?? ?? 8B 50", "89 46 ?? 5E 5D 74");
78+
if (Memory::AreAllSignaturesValid(ResolutionScansResult) == true)
7979
{
80-
spdlog::info("Resolution Instructions Scan: Address is {:s}+{:x}", ExeName().c_str(), ResolutionScanResult - (std::uint8_t*)ExeModule());
80+
spdlog::info("Resolution Instructions Scan: Address is {:s}+{:x}", ExeName().c_str(), ResolutionScansResult[Resolution] - (std::uint8_t*)ExeModule());
81+
spdlog::info("Bink Video Rectangle Instruction: Address is {:s}+{:x}", ExeName().c_str(), ResolutionScansResult[BinkVideoRect] - (std::uint8_t*)ExeModule());
8182

82-
m_resolutionHook = safetyhook::create_mid(ResolutionScanResult, [](SafetyHookContext& ctx)
83+
m_resolutionHook = safetyhook::create_mid(ResolutionScansResult[Resolution], [](SafetyHookContext & ctx)
8384
{
8485
s_instance_->m_newResX = Memory::ReadMem(ctx.eax);
8586
s_instance_->m_newResY = Memory::ReadMem(ctx.eax + 0x4);
8687
s_instance_->m_newAspectRatio = static_cast<float>(s_instance_->m_newResX) / static_cast<float>(s_instance_->m_newResY);
8788
s_instance_->m_aspectRatioScale = s_instance_->m_newAspectRatio / m_oldAspectRatio;
8889
s_instance_->m_resolutionHook.disable();
8990
});
90-
}
91-
else
92-
{
93-
spdlog::error("Failed to locate resolution instructions scan memory address.");
94-
return;
91+
92+
m_binkVideoRectHook = safetyhook::create_mid(ResolutionScansResult[BinkVideoRect], [](SafetyHookContext & ctx)
93+
{
94+
const uintptr_t binkHandle = Memory::ReadMem(ctx.esi);
95+
96+
if (binkHandle == 0 || s_instance_->m_newResX <= 0 || s_instance_->m_newResY <= 0)
97+
{
98+
return;
99+
}
100+
101+
const auto videoWidth = *reinterpret_cast<uint32_t*>(binkHandle);
102+
const auto videoHeight = *reinterpret_cast<uint32_t*>(binkHandle + 0x4);
103+
104+
if (videoWidth == 0 || videoHeight == 0)
105+
{
106+
return;
107+
}
108+
109+
std::int32_t drawWidth = 0;
110+
std::int32_t drawHeight = 0;
111+
112+
if (static_cast<std::int64_t>(s_instance_->m_newResX) * videoHeight <= static_cast<std::int64_t>(s_instance_->m_newResY) * videoWidth)
113+
{
114+
drawWidth = s_instance_->m_newResX;
115+
drawHeight = static_cast<std::int32_t>(static_cast<std::int64_t>(drawWidth) * videoHeight / videoWidth);
116+
}
117+
else
118+
{
119+
drawHeight = s_instance_->m_newResY;
120+
drawWidth = static_cast<std::int32_t>(static_cast<std::int64_t>(drawHeight) * videoWidth / videoHeight);
121+
}
122+
123+
RECT& destinationRect = Memory::ReadMem(ctx.esi + 0x174);
124+
125+
destinationRect.left = (s_instance_->m_newResX - drawWidth) / 2;
126+
destinationRect.top = (s_instance_->m_newResY - drawHeight) / 2;
127+
destinationRect.right = destinationRect.left + drawWidth;
128+
destinationRect.bottom = destinationRect.top + drawHeight;
129+
});
95130
}
96131

97132
auto AspectRatioScansResult = Memory::PatternScan(ExeModule(), "8B 50 ?? 8B 4C 24 ?? 83 C0 ?? 89 11 8B 40",
@@ -155,15 +190,16 @@ class PolarExpressFix final : public FixBase
155190
float m_newGameplayAspectRatio = 0.0f;
156191

157192
SafetyHookMid m_resolutionHook{};
193+
SafetyHookMid m_binkVideoRectHook{};
158194
SafetyHookMid m_cutscenesAspectRatioHook{};
159195
SafetyHookMid m_gameplayAspectRatioHook{};
160196
SafetyHookMid m_pauseMenuAspectRatioHook{};
161197
SafetyHookMid m_cameraFOVHook{};
162198

163-
enum ResolutionInstructionsIndex
199+
enum ResolutionInstructionsIndices
164200
{
165-
ListUnlock1,
166-
ListUnlock2
201+
Resolution,
202+
BinkVideoRect
167203
};
168204

169205
enum AspectRatioInstructionsIndices
@@ -180,29 +216,27 @@ static std::unique_ptr<PolarExpressFix> g_fix;
180216

181217
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
182218
{
183-
UNREFERENCED_PARAMETER(lpReserved);
184-
185219
switch (ul_reason_for_call)
186220
{
187-
case DLL_PROCESS_ATTACH:
188-
{
189-
DisableThreadLibraryCalls(hModule);
190-
g_fix = std::make_unique<PolarExpressFix>(hModule);
191-
g_fix->Start();
192-
break;
193-
}
221+
case DLL_PROCESS_ATTACH:
222+
{
223+
DisableThreadLibraryCalls(hModule);
224+
g_fix = std::make_unique<PolarExpressFix>(hModule);
225+
g_fix->Start();
226+
break;
227+
}
194228

195-
case DLL_PROCESS_DETACH:
196-
{
197-
g_fix->Shutdown();
198-
g_fix.reset();
199-
break;
200-
}
229+
case DLL_PROCESS_DETACH:
230+
{
231+
g_fix->Shutdown();
232+
g_fix.reset();
233+
break;
234+
}
201235

202-
case DLL_THREAD_ATTACH:
203-
case DLL_THREAD_DETACH:
204-
default:
205-
break;
236+
case DLL_THREAD_ATTACH:
237+
case DLL_THREAD_DETACH:
238+
default:
239+
break;
206240
}
207241

208242
return TRUE;

0 commit comments

Comments
 (0)