summaryrefslogtreecommitdiffstats
path: root/src/studio.cpp
diff options
context:
space:
mode:
authorsalmonik <salmonik@tuta.io>2026-11-06 16:19:25 +0100
committersalmonik <salmonik@tuta.io>2026-11-06 16:19:25 +0100
commit9f0724dcd25a06c5674d30d045dc485a341253b1 (patch)
treee7587dd03c0b164113d3b879b18d81fccf332c05 /src/studio.cpp
parentChams: leave engine-forced material passes alone (diff)
downloadhl2h-9f0724dcd25a06c5674d30d045dc485a341253b1.tar.gz
hl2h-9f0724dcd25a06c5674d30d045dc485a341253b1.zip
Hooks: central vtable install with restore support
Move vtable patching into hooks.cpp: one call clones the table, validates every slot, records the originals and installs the clone. Installs happen from the setup, game and paint threads, so the bookkeeping is mutex-protected. Client, CInput, IVModelRender, IStudioRender and ISurface all use it, and hooks_restore_all() can now put every interface back (previously impossible).
Diffstat (limited to '')
-rw-r--r--src/studio.cpp44
1 files changed, 22 insertions, 22 deletions
diff --git a/src/studio.cpp b/src/studio.cpp
index 8b0a710..275bfba 100644
--- a/src/studio.cpp
+++ b/src/studio.cpp
@@ -597,15 +597,17 @@ void chams_init() {
597 (void *)g_force_override, (void *)g_orig_model_exec); 597 (void *)g_force_override, (void *)g_orig_model_exec);
598 return; 598 return;
599 } 599 }
600 void **nvt = vtable_clone(g_iface.modelrender, 32); 600 VtablePatch patches[] = {
601 if (!nvt) { 601 {1, (void *)&hkdForceOverride,
602 logf("chams: vtable clone failed"); 602 reinterpret_cast<void **>(&g_real_force_override)}, // track forced passes
603 {19, (void *)&hkdModelExecute,
604 reinterpret_cast<void **>(&g_orig_model_exec)},
605 };
606 if (!hooks_install_vtable(g_iface.modelrender, 32, patches, 2)) {
607 logf("chams: vtable patch failed");
603 return; 608 return;
604 } 609 }
605 nvt[1] = (void *)&hkdForceOverride; // track engine-forced passes
606 nvt[19] = (void *)&hkdModelExecute;
607 g_modelrender = g_iface.modelrender; 610 g_modelrender = g_iface.modelrender;
608 *(void ***)g_modelrender = nvt;
609 logf("chams: IVModelRender %p hooked (draw=%p override=%p)", g_modelrender, 611 logf("chams: IVModelRender %p hooked (draw=%p override=%p)", g_modelrender,
610 (void *)g_orig_model_exec, (void *)g_force_override); 612 (void *)g_orig_model_exec, (void *)g_force_override);
611} 613}
@@ -641,24 +643,22 @@ void studio_props_init() {
641 logf("studio: interface has no vtable"); 643 logf("studio: interface has no vtable");
642 return; 644 return;
643 } 645 }
644 void **vt = vtable_clone(sr, 49); 646 VtablePatch patches[] = {
645 if (!vt) { 647 {27, (void *)&hook_set_color,
646 logf("studio: vtable clone failed"); 648 reinterpret_cast<void **>(&g_orig_set_color)},
649 {28, (void *)&hook_set_alpha,
650 reinterpret_cast<void **>(&g_orig_set_alpha)},
651 {29, (void *)&hook_draw_model,
652 reinterpret_cast<void **>(&g_orig_draw_model)},
653 {30, (void *)&hook_draw_static_prop,
654 reinterpret_cast<void **>(&g_orig_draw_static)},
655 {46, (void *)&hook_draw_array,
656 reinterpret_cast<void **>(&g_orig_draw_array)},
657 };
658 if (!hooks_install_vtable(sr, 49, patches, 5)) {
659 logf("studio: vtable patch failed");
647 return; 660 return;
648 } 661 }
649
650 g_orig_set_color = (SetColorFn)vt[27];
651 g_orig_set_alpha = (SetAlphaFn)vt[28];
652 g_orig_draw_model = (DrawModelFn)vt[29];
653 g_orig_draw_static = (DrawStaticFn)vt[30];
654 g_orig_draw_array = (DrawArrayFn)vt[46];
655 vt[27] = (void *)&hook_set_color;
656 vt[28] = (void *)&hook_set_alpha;
657 vt[29] = (void *)&hook_draw_model;
658 vt[30] = (void *)&hook_draw_static_prop;
659 vt[46] = (void *)&hook_draw_array;
660
661 *(void ***)sr = vt;
662 g_installed = true; 662 g_installed = true;
663 logf("studio: IStudioRender %p hooked (color=%p draw=%p static=%p " 663 logf("studio: IStudioRender %p hooked (color=%p draw=%p static=%p "
664 "array=%p)", sr, (void *)g_orig_set_color, (void *)g_orig_draw_model, 664 "array=%p)", sr, (void *)g_orig_set_color, (void *)g_orig_draw_model,