summaryrefslogtreecommitdiffstats
path: root/src/hl2h.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/hl2h.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/hl2h.cpp44
1 files changed, 19 insertions, 25 deletions
diff --git a/src/hl2h.cpp b/src/hl2h.cpp
index 6697778..354b3e6 100644
--- a/src/hl2h.cpp
+++ b/src/hl2h.cpp
@@ -1125,20 +1125,17 @@ static bool hkdCreateMove(void *self, int seq, float frametime, bool active) {
1125 // DrawPrintText (slot 22) hooked as a fallback text-draw trigger. 1125 // DrawPrintText (slot 22) hooked as a fallback text-draw trigger.
1126 static int isurface_hooked = 0; 1126 static int isurface_hooked = 0;
1127 if (!isurface_hooked && g_surface) { 1127 if (!isurface_hooked && g_surface) {
1128 void **svt = VTABLE(g_surface); 1128 VtablePatch patches[] = {
1129 constexpr size_t VT_SIZE = 256; 1129 {22, (void *)&hkdDrawPrintText,
1130 void **newsvt = vtable_clone(g_surface, VT_SIZE); 1130 reinterpret_cast<void **>(&oDrawPrintText)},
1131 if (!newsvt) { 1131 {114, (void *)&hkdPaintTraverseEx,
1132 isurface_hooked = 1; // don't retry every tick 1132 reinterpret_cast<void **>(&oPaintTraverseEx)},
1133 logf("ISurface hook: vtable unavailable"); 1133 };
1134 isurface_hooked = 1; // one attempt only
1135 if (!hooks_install_vtable(g_surface, 256, patches, 2)) {
1136 logf("ISurface hook: vtable patch failed");
1134 return ret; 1137 return ret;
1135 } 1138 }
1136 oDrawPrintText = (DrawPrintTextFn)svt[22];
1137 newsvt[22] = (void *)&hkdDrawPrintText;
1138 oPaintTraverseEx = (PaintTraverseExFn)svt[114];
1139 newsvt[114] = (void *)&hkdPaintTraverseEx;
1140 VTABLE(g_surface) = newsvt;
1141 isurface_hooked = 1;
1142 logf("ISurface hooked: DrawPrintText slot 22 orig=%p, PaintTraverseEx slot 114 orig=%p", 1139 logf("ISurface hooked: DrawPrintText slot 22 orig=%p, PaintTraverseEx slot 114 orig=%p",
1143 (void *)oDrawPrintText, (void *)oPaintTraverseEx); 1140 (void *)oDrawPrintText, (void *)oPaintTraverseEx);
1144 } 1141 }
@@ -1147,21 +1144,18 @@ static bool hkdCreateMove(void *self, int seq, float frametime, bool active) {
1147} 1144}
1148 1145
1149static void install_hook() { 1146static void install_hook() {
1150 void **vt = VTABLE(g_iface.client); 1147 VtablePatch patches[] = {
1151 constexpr size_t SLOTS = 256; 1148 {21, (void *)&hkdCreateMove, reinterpret_cast<void **>(&oCreateMove)},
1152 void **newvt = vtable_clone(g_iface.client, SLOTS); 1149 {35, (void *)&hkdFrameStageNotify,
1153 if (!newvt) { 1150 reinterpret_cast<void **>(&oFrameStageNotify)},
1154 logf("hook install: client vtable unavailable"); 1151 };
1152 if (!hooks_install_vtable(g_iface.client, 256, patches, 2)) {
1153 logf("hook install: client vtable patch failed");
1155 return; 1154 return;
1156 } 1155 }
1157 oCreateMove = (CreateMoveFn)vt[21]; 1156 logf("hook installed: CreateMove -> %p (orig %p), FrameStageNotify -> %p "
1158 newvt[21] = (void *)&hkdCreateMove; 1157 "(orig %p)",
1159 oFrameStageNotify = (FrameStageFn)vt[35]; 1158 (void *)&hkdCreateMove, (void *)oCreateMove,
1160 newvt[35] = (void *)&hkdFrameStageNotify;
1161 VTABLE(g_iface.client) = newvt;
1162 logf("hook installed: CreateMove %p -> %p (orig %p), FrameStageNotify %p "
1163 "-> %p (orig %p)",
1164 vt[21], (void *)&hkdCreateMove, (void *)oCreateMove, vt[35],
1165 (void *)&hkdFrameStageNotify, (void *)oFrameStageNotify); 1159 (void *)&hkdFrameStageNotify, (void *)oFrameStageNotify);
1166} 1160}
1167 1161