@@ -27,7 +27,7 @@ HMODULE thisModule;
2727
2828// Fix details
2929std::string sFixName = " PrisonerOfWarWidescreenFix" ;
30- std::string sFixVersion = " 1.2 " ;
30+ std::string sFixVersion = " 1.3 " ;
3131std::filesystem::path sFixPath ;
3232
3333// Ini
@@ -43,6 +43,7 @@ std::string sExeName;
4343// Constants
4444constexpr float fOldAspectRatio = 4 .0f / 3 .0f ;
4545constexpr float fNewAspectRatio2 = 0 .75f ;
46+ constexpr float fNewFrustumCullingFOV = 3 .1f ;
4647
4748// Ini variables
4849bool bFixActive;
@@ -53,8 +54,7 @@ float fFOVFactor;
5354// Variables
5455float fNewAspectRatio ;
5556float fAspectRatioScale ;
56- float fNewCameraFOV1 ;
57- float fNewCameraFOV2 ;
57+ float fNewGameplayFOV ;
5858float fNewCameraHFOV ;
5959
6060// Game detection
@@ -67,6 +67,20 @@ enum class Game
6767 Unknown
6868};
6969
70+ enum AspectRatioInstructionsIndices
71+ {
72+ AR1,
73+ Codecave,
74+ AR2,
75+ HFOV
76+ };
77+
78+ enum CameraFOVInstructionsIndices
79+ {
80+ GameplayFOV,
81+ FrustumCullingFOV
82+ };
83+
7084struct GameInfo
7185{
7286 std::string GameTitle;
@@ -197,8 +211,8 @@ bool DetectGame()
197211 return false ;
198212}
199213
200- static SafetyHookMid CameraFOVInstruction1Hook {};
201- static SafetyHookMid CameraFOVInstruction2Hook {};
214+ static SafetyHookMid GameplayCameraFOVInstructionHook {};
215+ static SafetyHookMid FrustumCullingFOVInstructionHook {};
202216static SafetyHookMid AspectRatioInstruction1Hook{};
203217static SafetyHookMid CameraHFOVInstructionHook{};
204218
@@ -238,141 +252,67 @@ void FOVFix()
238252
239253 fAspectRatioScale = fNewAspectRatio / fOldAspectRatio ;
240254
241- std::uint8_t * AspectRatioInstruction1ScanResult = Memory::PatternScan (exeModule, " DB 05 ?? ?? ?? ?? 8B C1" );
242- if (AspectRatioInstruction1ScanResult )
255+ std::vector<std:: uint8_t *> AspectRatioInstructionsScansResult = Memory::PatternScan (exeModule, " DB 05 ?? ?? ?? ?? 8B C1" , " 7A 2E 65 78 65 " , " E8 ?? ?? ?? ?? D9 05 ?? ?? ?? ?? D8 4E " , " D8 3D ?? ?? ?? ?? D9 18 " );
256+ if (Memory::AreAllSignaturesValid (AspectRatioInstructionsScansResult) == true )
243257 {
244- spdlog::info (" Aspect Ratio Instruction 1: Address is {:s}+{:x}" , sExeName .c_str (), AspectRatioInstruction1ScanResult - (std::uint8_t *)exeModule);
258+ spdlog::info (" Aspect Ratio Instruction 1: Address is {:s}+{:x}" , sExeName .c_str (), AspectRatioInstructionsScansResult[AR1] - (std::uint8_t *)exeModule);
245259
246- Memory::PatchBytes (AspectRatioInstruction1ScanResult, " \x90\x90\x90\x90\x90\x90 " , 6 );
260+ spdlog::info ( " Camera HFOV Instruction: Address is {:s}+{:x} " , sExeName . c_str (), AspectRatioInstructionsScansResult[HFOV] - (std:: uint8_t *)exeModule );
247261
248- AspectRatioInstruction1Hook = safetyhook::create_mid (AspectRatioInstruction1ScanResult, [](SafetyHookContext& ctx)
262+ Memory::WriteNOPs (AspectRatioInstructionsScansResult[AR1], 6 );
263+
264+ AspectRatioInstruction1Hook = safetyhook::create_mid (AspectRatioInstructionsScansResult[AR1], [](SafetyHookContext& ctx)
249265 {
250266 FPU::FLD (fNewAspectRatio2 );
251267 });
252268
253- Memory::PatchBytes (AspectRatioInstruction1ScanResult + 10 , " \x90\x90\x90\x90\x90\x90 " , 6 );
254- }
255- else
256- {
257- spdlog::error (" Failed to locate aspect ratio instruction 1 memory address." );
258- return ;
259- }
260-
261- std::uint8_t * CameraFOVInstruction1ScanResult = Memory::PatternScan (exeModule, " 8B 90 E0 00 00 00 89 88 DC 00 00 00 52 8B 54 24 08 8D 48 4C 8B 80 D8 00 00 00 52 50" );
262- if (CameraFOVInstruction1ScanResult)
263- {
264- spdlog::info (" Camera FOV Instruction 1: Address is {:s}+{:x}" , sExeName .c_str (), CameraFOVInstruction1ScanResult - (std::uint8_t *)exeModule);
265-
266- Memory::PatchBytes (CameraFOVInstruction1ScanResult, " \x90\x90\x90\x90\x90\x90 " , 6 );
269+ Memory::WriteNOPs (AspectRatioInstructionsScansResult[AR1] + 10 , 6 );
267270
268- CameraFOVInstruction1Hook = safetyhook::create_mid (CameraFOVInstruction1ScanResult, [](SafetyHookContext& ctx )
271+ if (eGameType == Game::POWGAME_EN )
269272 {
270- float & fCurrentCameraFOV1 = *reinterpret_cast <float *>(ctx.eax + 0xE0 );
271-
272- if (fCurrentCameraFOV1 == 0 .959931492805481f )
273- {
274- fNewCameraFOV1 = fCurrentCameraFOV1 * fFOVFactor ;
275- }
276- else
277- {
278- fNewCameraFOV1 = fCurrentCameraFOV1 ;
279- }
280-
281- ctx.edx = std::bit_cast<uintptr_t >(fNewCameraFOV1 );
282- });
283- }
284- else
285- {
286- spdlog::error (" Failed to locate camera FOV instruction 1 memory address." );
287- return ;
288- }
289-
290- std::uint8_t * CameraFOVInstruction2ScanResult = Memory::PatternScan (exeModule, " 90 90 90 90 90 90 D9 81 E0 00 00 00" );
291- if (CameraFOVInstruction2ScanResult)
292- {
293- spdlog::info (" Camera FOV Instruction 2: Address is {:s}+{:x}" , sExeName .c_str (), CameraFOVInstruction2ScanResult + 6 - (std::uint8_t *)exeModule);
294-
295- Memory::PatchBytes (CameraFOVInstruction2ScanResult + 6 , " \x90\x90\x90\x90\x90\x90 " , 6 );
296-
297- CameraFOVInstruction2Hook = safetyhook::create_mid (CameraFOVInstruction2ScanResult + 6 , [](SafetyHookContext& ctx)
273+ Memory::PatchBytes (AspectRatioInstructionsScansResult[Codecave] + 6 , " \xDB\x05\xC8\x70\x66\x00\x8B\xC1\x33\xC9\xDA\x35\xC4\x70\x66\x00\xC7\x40\x2C\x00\x00\x80\x3F\x89\x48\x3C\x89\x48\x34\x89\x48\x30\x89\x48\x24\x89\x48\x20\x89\x48\x1C\x89\x48\x18\x89\x48\x10\x89\x48\x0C\x89\x48\x08\x89\x48\x04\xD8\x4C\x24\x0C\xD8\x0D\xCC\xC2\x60\x00\xD9\xF2\xDD\xD8\xD8\x3D\x44\xC4\x60\x00\xD9\x44\x24\x08\xD8\x64\x24\x04\xD8\x7C\x24\x08\xD9\x44\x24\x0C\xD8\x0D\xCC\xC2\x60\x00\xD9\xF2\xDD\xD8\xD8\x3D\x44\xC4\x60\x00\xD9\x18\xD9\xC9\xD9\x58\x14\xD9\x50\x28\xD8\x4C\x24\x04\xD9\xE0\xD9\x58\x38\xC2\x0C\x00 " );
274+ }
275+ else if (eGameType == Game::POWGAME_RU)
298276 {
299- float & fCurrentCameraFOV2 = *reinterpret_cast <float *>(ctx.ecx + 0xE0 );
300-
301- if (fCurrentCameraFOV2 == 0 .959931492805481f )
302- {
303- fNewCameraFOV2 = Maths::CalculateNewFOV_RadBased (fCurrentCameraFOV2 , fAspectRatioScale ) * fFOVFactor ;
304- }
305- else
306- {
307- fNewCameraFOV2 = Maths::CalculateNewFOV_RadBased (fCurrentCameraFOV2 , fAspectRatioScale );
308- }
309-
310- FPU::FLD (fNewCameraFOV2 );
311- });
312- }
313- else
314- {
315- spdlog::error (" Failed to locate camera FOV instruction 2 memory address." );
316- return ;
317- }
277+ Memory::PatchBytes (AspectRatioInstructionsScansResult[Codecave] + 6 , " \xDB\x05\x00\xDA\x66\x00\x8B\xC1\x33\xC9\xDA\x35\xFC\xD9\x66\x00\xC7\x40\x2C\x00\x00\x80\x3F\x89\x48\x3C\x89\x48\x34\x89\x48\x30\x89\x48\x24\x89\x48\x20\x89\x48\x1C\x89\x48\x18\x89\x48\x10\x89\x48\x0C\x89\x48\x08\x89\x48\x04\xD8\x4C\x24\x0C\xD8\x0D\xCC\xD2\x60\x00\xD9\xF2\xDD\xD8\xD8\x3D\x44\xD4\x60\x00\xD9\x44\x24\x08\xD8\x64\x24\x04\xD8\x7C\x24\x08\xD9\x44\x24\x0C\xD8\x0D\xCC\xD2\x60\x00\xD9\xF2\xDD\xD8\xD8\x3D\x44\xD4\x60\x00\xD9\x18\xD9\xC9\xD9\x58\x14\xD9\x50\x28\xD8\x4C\x24\x04\xD9\xE0\xD9\x58\x38\xC2\x0C\x00 " );
278+ }
318279
319- std::uint8_t * CameraHFOVInstructionScanResult = Memory::PatternScan (exeModule, " D8 3D ?? ?? ?? ?? D9 18 D9 C9 D9 58 14 D9 50 28 D8 4C 24 04 D9 E0 D9 58 38 C2 0C 00" );
320- if (CameraHFOVInstructionScanResult)
321- {
322- spdlog::info (" Camera HFOV Instruction: Address is {:s}+{:x}" , sExeName .c_str (), CameraHFOVInstructionScanResult - (std::uint8_t *)exeModule);
280+ Memory::PatchCALL (AspectRatioInstructionsScansResult[AR2], AspectRatioInstructionsScansResult[Codecave] + 6 , Memory::CallType::Relative);
323281
324- Memory::PatchBytes (CameraHFOVInstructionScanResult, " \x90\x90\x90\x90\x90\x90 " , 6 );
282+ Memory::WriteNOPs (AspectRatioInstructionsScansResult[HFOV] , 6 );
325283
326284 fNewCameraHFOV = 1 .0f / fAspectRatioScale ;
327285
328- CameraHFOVInstructionHook = safetyhook::create_mid (CameraHFOVInstructionScanResult , [](SafetyHookContext& ctx)
286+ CameraHFOVInstructionHook = safetyhook::create_mid (AspectRatioInstructionsScansResult[HFOV] , [](SafetyHookContext& ctx)
329287 {
330288 FPU::FDIVR (fNewCameraHFOV );
331289 });
332290 }
333- else
334- {
335- spdlog::error (" Failed to locate camera HFOV instruction memory address." );
336- return ;
337- }
338291
339- std::uint8_t * CodecaveScanResult = Memory::PatternScan (exeModule, " 7A 2E 65 78 65 " );
340- if (CodecaveScanResult )
292+ std::vector<std:: uint8_t *> CameraFOVInstructionsScansResult = Memory::PatternScan (exeModule, " D9 06 D8 0D ?? ?? ?? ?? 51 " , " D9 81 ?? ?? ?? ?? C3 90 90 90 90 90 90 90 90 90 8B 44 24 ?? 8B 54 24 " );
293+ if (Memory::AreAllSignaturesValid (CameraFOVInstructionsScansResult) == true )
341294 {
342- spdlog::info (" Codecave Scan : Address is {:s}+{:x}" , sExeName .c_str (), CodecaveScanResult - (std::uint8_t *)exeModule);
295+ spdlog::info (" Gameplay Camera FOV Instruction : Address is {:s}+{:x}" , sExeName .c_str (), CameraFOVInstructionsScansResult[GameplayFOV] - (std::uint8_t *)exeModule);
343296
344- if (eGameType == Game::POWGAME_EN)
345- {
346- Memory::PatchBytes (CodecaveScanResult + 6 , " \xDB\x05\xC8\x70\x66\x00\x8B\xC1\x33\xC9\xDA\x35\xC4\x70\x66\x00\xC7\x40\x2C\x00\x00\x80\x3F\x89\x48\x3C\x89\x48\x34\x89\x48\x30\x89\x48\x24\x89\x48\x20\x89\x48\x1C\x89\x48\x18\x89\x48\x10\x89\x48\x0C\x89\x48\x08\x89\x48\x04\xD8\x4C\x24\x0C\xD8\x0D\xCC\xC2\x60\x00\xD9\xF2\xDD\xD8\xD8\x3D\x44\xC4\x60\x00\xD9\x44\x24\x08\xD8\x64\x24\x04\xD8\x7C\x24\x08\xD9\x44\x24\x0C\xD8\x0D\xCC\xC2\x60\x00\xD9\xF2\xDD\xD8\xD8\x3D\x44\xC4\x60\x00\xD9\x18\xD9\xC9\xD9\x58\x14\xD9\x50\x28\xD8\x4C\x24\x04\xD9\xE0\xD9\x58\x38\xC2\x0C\x00 " , 130 );
347- }
348- else if (eGameType == Game::POWGAME_RU)
349- {
350- Memory::PatchBytes (CodecaveScanResult + 6 , " \xDB\x05\x00\xDA\x66\x00\x8B\xC1\x33\xC9\xDA\x35\xFC\xD9\x66\x00\xC7\x40\x2C\x00\x00\x80\x3F\x89\x48\x3C\x89\x48\x34\x89\x48\x30\x89\x48\x24\x89\x48\x20\x89\x48\x1C\x89\x48\x18\x89\x48\x10\x89\x48\x0C\x89\x48\x08\x89\x48\x04\xD8\x4C\x24\x0C\xD8\x0D\xCC\xD2\x60\x00\xD9\xF2\xDD\xD8\xD8\x3D\x44\xD4\x60\x00\xD9\x44\x24\x08\xD8\x64\x24\x04\xD8\x7C\x24\x08\xD9\x44\x24\x0C\xD8\x0D\xCC\xD2\x60\x00\xD9\xF2\xDD\xD8\xD8\x3D\x44\xD4\x60\x00\xD9\x18\xD9\xC9\xD9\x58\x14\xD9\x50\x28\xD8\x4C\x24\x04\xD9\xE0\xD9\x58\x38\xC2\x0C\x00 " , 130 );
351- }
352- }
353- else
354- {
355- spdlog::error (" Failed to locate codecave scan memory address." );
356- return ;
357- }
297+ spdlog::info (" Frustum Culling Camera FOV Instruction: Address is {:s}+{:x}" , sExeName .c_str (), CameraFOVInstructionsScansResult[FrustumCullingFOV] - (std::uint8_t *)exeModule);
358298
359- std::uint8_t * AspectRatioInstruction2ScanResult = Memory::PatternScan (exeModule, " E8 ?? ?? ?? ?? D9 05 ?? ?? ?? ?? D8 4E" );
360- if (AspectRatioInstruction2ScanResult)
361- {
362- spdlog::info (" Aspect Ratio Instruction 2: Address is {:s}+{:x}" , sExeName .c_str (), AspectRatioInstruction2ScanResult - (std::uint8_t *)exeModule);
299+ Memory::WriteNOPs (CameraFOVInstructionsScansResult[GameplayFOV], 2 );
363300
364- uint8_t * codecaveTarget = CodecaveScanResult + 6 ;
301+ GameplayCameraFOVInstructionHook = safetyhook::create_mid (CameraFOVInstructionsScansResult[GameplayFOV], [](SafetyHookContext& ctx)
302+ {
303+ float & fCurrentGameplayFOV = *reinterpret_cast <float *>(ctx.esi );
365304
366- std::array<uint8_t , 5 > saved{};
305+ fNewGameplayFOV = fCurrentGameplayFOV * fFOVFactor ;
306+
307+ FPU::FLD (fNewGameplayFOV );
308+ });
367309
368- if (Memory::PatchCallRel32 (AspectRatioInstruction2ScanResult, codecaveTarget, &saved) == false )
369- {
370- spdlog::error (" PatchCallRel32 failed (rel32 overflow or not a call)." );
371- }
372- else
310+ Memory::WriteNOPs (CameraFOVInstructionsScansResult[FrustumCullingFOV], 6 );
311+
312+ FrustumCullingFOVInstructionHook = safetyhook::create_mid (CameraFOVInstructionsScansResult[FrustumCullingFOV], [](SafetyHookContext& ctx)
373313 {
374- spdlog::info ( " Successfully patched the CALL instruction located at {:s}+{:x} to the patched codecave located at {:s}+{:x} " , sExeName . c_str (), AspectRatioInstruction2ScanResult - ( uint8_t *)exeModule, sExeName . c_str (), ( uintptr_t )codecaveTarget );
375- }
314+ FPU::FLD ( fNewFrustumCullingFOV );
315+ });
376316 }
377317 }
378318 }
0 commit comments