diff options
| author | salmonik <salmonik@tuta.io> | 2026-11-06 16:19:25 +0100 |
|---|---|---|
| committer | salmonik <salmonik@tuta.io> | 2026-11-06 16:19:25 +0100 |
| commit | 9f0724dcd25a06c5674d30d045dc485a341253b1 (patch) | |
| tree | e7587dd03c0b164113d3b879b18d81fccf332c05 /src/hl2h.cpp | |
| parent | Chams: leave engine-forced material passes alone (diff) | |
| download | hl2h-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 'src/hl2h.cpp')
| -rw-r--r-- | src/hl2h.cpp | 44 |
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 | ||
| 1149 | static void install_hook() { | 1146 | static 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 | ||
