@@ -17,13 +17,49 @@ namespace RainSplashFix
1717 float * pMaxSizeC75z = nullptr ;
1818 float * pMaxSizeC75w = nullptr ;
1919 float fOrigC73z = 0 .0f , fOrigC75y = 0 .0f , fOrigC75z = 0 .0f , fOrigC75w = 0 .0f ;
20+ uint32_t * pDoneFlag = nullptr ; // retail only
21+
22+ // Retail builds c73 on the stack and lazily stores c74/c75 as immediates
23+ void InitRetail ()
24+ {
25+ auto pat = hook::module_pattern (GetModuleHandle (L" D3DDrv" ), " F6 05 ? ? ? ? 02 75 ? 83 0D ? ? ? ? 02 C7 05 ? ? ? ? 00 00 00 41 C7 05 ? ? ? ? 00 40 9C 45 C7 05 ? ? ? ? 00 00 C0 41 C7 05 ? ? ? ? 00 00 F0 41" );
26+ auto pat2 = hook::module_pattern (GetModuleHandle (L" D3DDrv" ), " 8B 0D ? ? ? ? DC 08 D9 05" );
27+ if (pat.empty () || pat2.empty ())
28+ return ;
29+
30+ uint32_t * doneFlag = *pat.get_first <uint32_t *>(2 );
31+ float * c73z = *pat2.get_first <float *>(2 );
32+ if (!doneFlag || !c73z || *reinterpret_cast <uint32_t *>(c73z) != 0x46EA6000u )
33+ return ;
34+
35+ pDoneFlag = doneFlag;
36+ pSizeScaleC73z = c73z;
37+ pSizeScaleC75y = pat.get_first <float >(32 );
38+ pMaxSizeC75z = pat.get_first <float >(42 );
39+ pMaxSizeC75w = pat.get_first <float >(52 );
40+
41+ if (*reinterpret_cast <uint32_t *>(pSizeScaleC75y) != 0x459C4000u ||
42+ *reinterpret_cast <uint32_t *>(pMaxSizeC75z) != 0x41C00000u ||
43+ *reinterpret_cast <uint32_t *>(pMaxSizeC75w) != 0x41F00000u )
44+ return ;
45+
46+ fOrigC73z = *pSizeScaleC73z;
47+ fOrigC75y = *pSizeScaleC75y;
48+ fOrigC75z = *pMaxSizeC75z;
49+ fOrigC75w = *pMaxSizeC75w;
50+
51+ bInitialized = true ;
52+ }
2053
2154 void Init ()
2255 {
2356 // Rain splash constant block (c73–c75)
2457 auto pattern = hook::module_pattern (GetModuleHandle (L" D3DDrv" ), " 6A 01 68 ? ? ? ? 6A 4B 8B 80 94 46 00 00" );
2558 if (pattern.empty ())
59+ {
60+ InitRetail ();
2661 return ;
62+ }
2763
2864 float * c75 = *pattern.get_first <float *>(3 );
2965 if (!c75)
@@ -71,6 +107,9 @@ namespace RainSplashFix
71107 injector::WriteMemory<float >(pSizeScaleC75y, fOrigC75y * scale, true );
72108 injector::WriteMemory<float >(pMaxSizeC75z, fOrigC75z * scale, true );
73109 injector::WriteMemory<float >(pMaxSizeC75w, fOrigC75w * scale, true );
110+
111+ if (pDoneFlag) // retail: re-run the patched lazy initialiser
112+ injector::WriteMemory<uint32_t >(pDoneFlag, *pDoneFlag & ~2u , true );
74113 }
75114}
76115
@@ -324,15 +363,13 @@ export void InitD3DDrv()
324363 pattern = find_module_pattern (GetModuleHandle (L" D3DDrv" ), " 55 8B EC 6A ? 68 ? ? ? ? 64 A1 ? ? ? ? 50 64 89 25 ? ? ? ? 81 EC ? ? ? ? 53 56 57 8B 7D ? 8B F1" , " 55 8B EC 6A ? 68 ? ? ? ? 64 A1 ? ? ? ? 50 81 EC ? ? ? ? A1 ? ? ? ? 33 C5 89 45 ? 56 57 50 8D 45 ? 64 A3 ? ? ? ? 8B F1 89 75" );
325364 shUD3DRenderDeviceSetRes = safetyhook::create_inline (pattern.get_first (), UD3DRenderDeviceSetRes);
326365
327- bool bRetailVersion = false ;
366+ bool bRetailVersion = GetProcAddress ( GetModuleHandle ( L" D3DDrv " ), " ?Exec@UD3DRenderDevice@@UAEHPBGAAVFOutputDevice@@@Z " ) != nullptr ;
328367
329368 // Water Blend Fix
330369 static DWORD OriginalAlphaBlendEnable = 0 ;
331370 static DWORD OriginalSrcBlend = 0 ;
332371 static DWORD OriginalDestBlend = 0 ;
333372
334- pattern = find_module_pattern (GetModuleHandle (L" D3DDrv" ), " FF B5 ? ? ? ? 8B 07 6A ? FF B5" );
335- if (!pattern.empty ())
336373 {
337374 static DWORD WaterBlendPS = 0 ;
338375 static thread_local bool bWaterFixApplied = false ;
@@ -451,46 +488,86 @@ export void InitD3DDrv()
451488 }
452489 };
453490
454- static auto WaterPreDrawPrimitiveHook1 = safetyhook::create_mid (pattern. get_first (), [](SafetyHookContext& regs )
491+ if (!bRetailVersion )
455492 {
456- IDirect3DDevice8* pDevice = (IDirect3DDevice8*)(regs.edi );
457- WaterPreDraw (regs, pDevice);
458- });
493+ pattern = find_module_pattern (GetModuleHandle (L" D3DDrv" ), " FF B5 ? ? ? ? 8B 07 6A ? FF B5" );
494+ static auto WaterPreDrawPrimitiveHook1 = safetyhook::create_mid (pattern.get_first (), [](SafetyHookContext& regs)
495+ {
496+ IDirect3DDevice8* pDevice = (IDirect3DDevice8*)(regs.edi );
497+ WaterPreDraw (regs, pDevice);
498+ });
459499
460- pattern = find_module_pattern (GetModuleHandle (L" D3DDrv" ), " F3 0F 10 9D ? ? ? ? 8B 95 ? ? ? ? F3 0F 10 25" );
461- static auto WaterPostDrawPrimitiveHook1 = safetyhook::create_mid (pattern.get_first (), [](SafetyHookContext& regs)
462- {
463- IDirect3DDevice8* pDevice = (IDirect3DDevice8*)(regs.edi );
464- WaterPostDraw (regs, pDevice);
465- });
500+ pattern = find_module_pattern (GetModuleHandle (L" D3DDrv" ), " F3 0F 10 9D ? ? ? ? 8B 95 ? ? ? ? F3 0F 10 25" );
501+ static auto WaterPostDrawPrimitiveHook1 = safetyhook::create_mid (pattern.get_first (), [](SafetyHookContext& regs)
502+ {
503+ IDirect3DDevice8* pDevice = (IDirect3DDevice8*)(regs.edi );
504+ WaterPostDraw (regs, pDevice);
505+ });
466506
467- pattern = find_module_pattern (GetModuleHandle (L" D3DDrv" ), " FF B5 ? ? ? ? 8B 06 6A ? FF B5 ? ? ? ? 6A ? 6A ? 56 FF 90 ? ? ? ? F3 0F 10 9D" );
468- static auto WaterPreDrawPrimitiveHook2 = safetyhook::create_mid (pattern.get_first (), [](SafetyHookContext& regs)
469- {
470- IDirect3DDevice8* pDevice = (IDirect3DDevice8*)(regs.esi );
471- WaterPreDraw (regs, pDevice);
472- });
507+ pattern = find_module_pattern (GetModuleHandle (L" D3DDrv" ), " FF B5 ? ? ? ? 8B 06 6A ? FF B5 ? ? ? ? 6A ? 6A ? 56 FF 90 ? ? ? ? F3 0F 10 9D" );
508+ static auto WaterPreDrawPrimitiveHook2 = safetyhook::create_mid (pattern.get_first (), [](SafetyHookContext& regs)
509+ {
510+ IDirect3DDevice8* pDevice = (IDirect3DDevice8*)(regs.esi );
511+ WaterPreDraw (regs, pDevice);
512+ });
473513
474- pattern = find_module_pattern (GetModuleHandle (L" D3DDrv" ), " F3 0F 10 9D ? ? ? ? 8B 95 ? ? ? ? 8B 8F" );
475- static auto WaterPostDrawPrimitiveHook2 = safetyhook::create_mid (pattern.get_first (), [](SafetyHookContext& regs)
514+ pattern = find_module_pattern (GetModuleHandle (L" D3DDrv" ), " F3 0F 10 9D ? ? ? ? 8B 95 ? ? ? ? 8B 8F" );
515+ static auto WaterPostDrawPrimitiveHook2 = safetyhook::create_mid (pattern.get_first (), [](SafetyHookContext& regs)
516+ {
517+ IDirect3DDevice8* pDevice = (IDirect3DDevice8*)(regs.esi );
518+ WaterPostDraw (regs, pDevice);
519+ });
520+ }
521+ else
476522 {
477- IDirect3DDevice8* pDevice = (IDirect3DDevice8*)(regs.esi );
478- WaterPostDraw (regs, pDevice);
479- });
523+ // retail: device is in EBP at all four sites
524+ pattern = find_module_pattern (GetModuleHandle (L" D3DDrv" ), " 8B 4C 24 ? 8B 45 00 51 6A 00 57 6A 00 6A 05 55 FF 90 1C 01 00 00 8B 83 EC 03 00 00" );
525+ if (!pattern.empty ())
526+ {
527+ static auto WaterPreDrawPrimitiveHook1Retail = safetyhook::create_mid (pattern.get_first (7 ), [](SafetyHookContext& regs)
528+ {
529+ IDirect3DDevice8* pDevice = (IDirect3DDevice8*)(regs.ebp );
530+ WaterPreDraw (regs, pDevice);
531+ });
480532
481- pattern = find_module_pattern (GetModuleHandle (L" D3DDrv" ), " 68 ? ? ? ? 50 8B 08 FF 51 ? 8B 07" );
482- static auto DeviceResetHook = safetyhook::create_mid (pattern.get_first (), [](SafetyHookContext& regs)
483- {
484- IDirect3DDevice8* pDevice = *(IDirect3DDevice8**)(regs.edi );
485- if (WaterBlendPS)
533+ static auto WaterPostDrawPrimitiveHook1Retail = safetyhook::create_mid (pattern.get_first (22 ), [](SafetyHookContext& regs)
534+ {
535+ IDirect3DDevice8* pDevice = (IDirect3DDevice8*)(regs.ebp );
536+ WaterPostDraw (regs, pDevice);
537+ });
538+ }
539+
540+ pattern = find_module_pattern (GetModuleHandle (L" D3DDrv" ), " 8B 44 24 ? 8B 4C 24 ? 8B 55 00 50 6A 00 51 6A 00 6A 05 55 FF 92 1C 01 00 00 8B 8B EC 03 00 00" );
541+ if (!pattern.empty ())
486542 {
487- pDevice->DeletePixelShader (WaterBlendPS);
488- WaterBlendPS = 0 ;
543+ static auto WaterPreDrawPrimitiveHook2Retail = safetyhook::create_mid (pattern.get_first (11 ), [](SafetyHookContext& regs)
544+ {
545+ IDirect3DDevice8* pDevice = (IDirect3DDevice8*)(regs.ebp );
546+ WaterPreDraw (regs, pDevice);
547+ });
548+
549+ static auto WaterPostDrawPrimitiveHook2Retail = safetyhook::create_mid (pattern.get_first (26 ), [](SafetyHookContext& regs)
550+ {
551+ IDirect3DDevice8* pDevice = (IDirect3DDevice8*)(regs.ebp );
552+ WaterPostDraw (regs, pDevice);
553+ });
489554 }
490- });
555+ }
556+
557+ pattern = find_module_pattern (GetModuleHandle (L" D3DDrv" ), " 68 ? ? ? ? 50 8B 08 FF 51 ? 8B 07" , " 68 ? ? ? ? 50 FF 51 38 33 C9 3B C1" );
558+ if (!pattern.empty ())
559+ {
560+ static auto DeviceResetHook = safetyhook::create_mid (pattern.get_first (), [](SafetyHookContext& regs)
561+ {
562+ IDirect3DDevice8* pDevice = *(IDirect3DDevice8**)(regs.edi );
563+ if (WaterBlendPS)
564+ {
565+ pDevice->DeletePixelShader (WaterBlendPS);
566+ WaterBlendPS = 0 ;
567+ }
568+ });
569+ }
491570 }
492- else
493- bRetailVersion = true ;
494571
495572 // FMV
496573 UD3DRenderDevice::shDisplayVideo = safetyhook::create_inline (GetProcAddress (GetModuleHandle (L" D3DDrv" ), " ?DisplayVideo@UD3DRenderDevice@@UAEXPAVUCanvas@@PAX@Z" ), UD3DRenderDevice::DisplayVideo);
@@ -594,12 +671,18 @@ export void InitD3DDrv()
594671 }
595672
596673 pattern = find_module_pattern (GetModuleHandle (L" D3DDrv" ), " 68 ? ? ? ? 68 ? ? ? ? 6A ? 6A ? 8B CF" , " 68 ? ? ? ? 68 ? ? ? ? 6A ? 6A ? FF 50 ? 8B 07" );
597- injector::WriteMemory (pattern.get_first (1 ), Screen.nReflectionsResolution , true );
598- injector::WriteMemory (pattern.get_first (6 ), Screen.nReflectionsResolution , true );
674+ if (!pattern.empty ())
675+ {
676+ injector::WriteMemory (pattern.get_first (1 ), Screen.nReflectionsResolution , true );
677+ injector::WriteMemory (pattern.get_first (6 ), Screen.nReflectionsResolution , true );
678+ }
599679
600- pattern = find_module_pattern (GetModuleHandle (L" D3DDrv" ), " 68 ? ? ? ? 68 ? ? ? ? 6A ? 6A ? 8B CB" );
601- injector::WriteMemory (pattern.get_first (1 ), Screen.nReflectionsResolution , true );
602- injector::WriteMemory (pattern.get_first (6 ), Screen.nReflectionsResolution , true );
680+ pattern = find_module_pattern (GetModuleHandle (L" D3DDrv" ), " 68 ? ? ? ? 68 ? ? ? ? 6A ? 6A ? 8B CB FF 50" , " 68 ? ? ? ? 68 ? ? ? ? 6A ? 6A ? 8B CB FF 52 ? 68 ? ? ? ? 68 ? ? ? ? 53 8D 4C 24 ? FF 15 ? ? ? ? 8B 45 ? 85 C0" );
681+ if (!pattern.empty ())
682+ {
683+ injector::WriteMemory (pattern.get_first (1 ), Screen.nReflectionsResolution , true );
684+ injector::WriteMemory (pattern.get_first (6 ), Screen.nReflectionsResolution , true );
685+ }
603686 }
604687
605688 if (Screen.nBloomResolutionMultiplier > 0 )
@@ -614,24 +697,25 @@ export void InitD3DDrv()
614697 injector::WriteMemory (rpattern.get (4 ).get <uint32_t >(1 ), *rpattern.get (3 ).get <uint32_t >(1 ) * Screen.nBloomResolutionMultiplier , true );
615698 injector::WriteMemory (rpattern.get (4 ).get <uint32_t >(6 ), *rpattern.get (3 ).get <uint32_t >(6 ) * Screen.nBloomResolutionMultiplier , true );
616699
617- pattern = find_module_pattern (GetModuleHandle (L" D3DDrv" ), " 50 FF 51 ? 8B 45 ? 81 C6 ? ? ? ? 56 6A ? 6A" );
700+ pattern = find_module_pattern (GetModuleHandle (L" D3DDrv" ), " 50 FF 51 ? 8B 45 ? 81 C6 ? ? ? ? 56 6A ? 6A" , " 50 FF 52 ? 8B 07 8B 10 8D 8B ? ? ? ? 51 6A ? 6A ? 6A ? 6A ? 6A 20 6A 20 50 " );
618701 static auto ResHook1 = safetyhook::create_mid (pattern.get_first (), [](SafetyHookContext& regs)
619702 {
620703 *(uint32_t *)(regs.esp + 0x0 ) *= Screen.nBloomResolutionMultiplier ;
621704 *(uint32_t *)(regs.esp + 0x4 ) *= Screen.nBloomResolutionMultiplier ;
622705 });
623706
624- pattern = find_module_pattern (GetModuleHandle (L" D3DDrv" ), " 50 FF 51 ? 8B 4D ? 6A" );
707+ pattern = find_module_pattern (GetModuleHandle (L" D3DDrv" ), " 50 FF 51 ? 8B 4D ? 6A" , " 50 FF 52 50 6A ? 6A ? 8B CE FF 15 ? ? ? ? 8B 16 8D 8B E4 58 " );
625708 static auto ResHook2 = safetyhook::create_mid (pattern.get_first (), [](SafetyHookContext& regs)
626709 {
627710 *(uint32_t *)(regs.esp + 0x0 ) *= Screen.nBloomResolutionMultiplier ;
628711 *(uint32_t *)(regs.esp + 0x4 ) *= Screen.nBloomResolutionMultiplier ;
629712 });
630713
631- pattern = find_module_pattern (GetModuleHandle (L" D3DDrv" ), " 55 8B EC 6A ? 68 ? ? ? ? 64 A1 ? ? ? ? 50 81 EC ? ? ? ? A1 ? ? ? ? 33 C5 89 45 ? 53 56 57 50 8D 45 ? 64 A3 ? ? ? ? 8B D9 89 9D ? ? ? ? F3 0F 10 45" );
632- shsub_1009D270 = safetyhook::create_inline (pattern.get_first (), sub_1009D270);
714+ pattern = find_module_pattern (GetModuleHandle (L" D3DDrv" ), " 55 8B EC 6A ? 68 ? ? ? ? 64 A1 ? ? ? ? 50 81 EC ? ? ? ? A1 ? ? ? ? 33 C5 89 45 ? 53 56 57 50 8D 45 ? 64 A3 ? ? ? ? 8B D9 89 9D ? ? ? ? F3 0F 10 45" , " 6A FF 68 ? ? ? ? 64 A1 ? ? ? ? 50 64 89 25 ? ? ? ? 81 EC ? ? ? ? 53 55 56 8B B4 24 ? ? ? ? 33 DB 3B F3 8B E9 57" );
715+ if (!pattern.empty ())
716+ shsub_1009D270 = safetyhook::create_inline (pattern.get_first (), sub_1009D270);
633717
634- pattern = find_module_pattern (GetModuleHandle (L" D3DDrv" ), " 55 8B EC 83 EC ? A1 ? ? ? ? 33 C5 89 45 ? 8B 45 ? 8D 55" );
718+ pattern = find_module_pattern (GetModuleHandle (L" D3DDrv" ), " 55 8B EC 83 EC ? A1 ? ? ? ? 33 C5 89 45 ? 8B 45 ? 8D 55" , " 55 8B EC 6A FF 68 ? ? ? ? 64 A1 ? ? ? ? 50 64 89 25 ? ? ? ? 83 EC 24 8B 45 10 53 8B 5D 0C 56 57 8B 7D 08 8B F1 " );
635719 shsub_100A7850 = safetyhook::create_inline (pattern.get_first (), sub_100A7850);
636720 }
637721
@@ -704,7 +788,7 @@ export void InitD3DDrv()
704788 });
705789
706790 // EOceanInfo "Ocean2" culling fix
707- pattern = hook::module_pattern (GetModuleHandle (L" D3DDrv" ), " 3D 2C 01 00 00 77 43 85 C0 0F 84 ? ? ? ? 6A 08 6A 01" );
791+ pattern = find_module_pattern (GetModuleHandle (L" D3DDrv" ), " 3D 2C 01 00 00 77 43 85 C0 0F 84 ? ? ? ? 6A 08 6A 01" , " F9 2C 01 00 00 77 ? 85 C9 0F 86 " );
708792 if (!pattern.empty ())
709793 injector::WriteMemory<uint8_t >(pattern.get_first (5 ), 0xEB , true ); // ja -> jmp
710794
@@ -731,6 +815,28 @@ export void InitD3DDrv()
731815 }
732816 });
733817 }
818+ else
819+ {
820+ pattern = find_module_pattern (GetModuleHandle (L" D3DDrv" ), " DB 45 08 8B 4C 24 1C 8B 11 D9 5C 24 14 FF 52 68 89 44 24 18 DB 44 24 18 8B 4C 24 1C 8B 01 D8 7C 24 14 D9 5C 24 18 DB 45 0C D9 5C 24 20 FF 50 6C 89 44 24 1C DB 44 24 1C D8 7C 24 20 D9 5C 24 1C" );
821+ if (!pattern.empty ())
822+ {
823+ static auto NightVisionGrainHookRetail = safetyhook::create_mid (pattern.get_first (0x40 ), [](SafetyHookContext& regs)
824+ {
825+ if (Screen.fGrainScale == 0 .0f )
826+ return ;
827+
828+ float * pGrainScaleU = reinterpret_cast <float *>(regs.esp + 0x18 );
829+ float * pGrainScaleV = reinterpret_cast <float *>(regs.esp + 0x1C );
830+ float renderWidth = static_cast <float >(*reinterpret_cast <int32_t *>(regs.ebp + 0x8 ));
831+ float renderHeight = static_cast <float >(*reinterpret_cast <int32_t *>(regs.ebp + 0xC ));
832+ if (renderWidth > 0 .0f && renderHeight > 0 .0f )
833+ {
834+ *pGrainScaleU *= 1 .0f + (640 .0f / renderWidth - 1 .0f ) * Screen.fGrainScale ;
835+ *pGrainScaleV *= 1 .0f + (480 .0f / renderHeight - 1 .0f ) * Screen.fGrainScale ;
836+ }
837+ });
838+ }
839+ }
734840
735841 InitShaders ();
736842}
0 commit comments