@@ -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
181217BOOL 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