summaryrefslogtreecommitdiffstats
path: root/src/studio.cpp
diff options
context:
space:
mode:
authorsalmonik <salmonik@tuta.io>2026-11-04 12:52:03 +0100
committersalmonik <salmonik@tuta.io>2026-11-04 12:52:03 +0100
commita83d3c80d3c555490e7545a191a2c09dd74ca13d (patch)
treeaaaab95ba016362a948cd1148229d12047a8a5c0 /src/studio.cpp
parentESP: classify NPC damage immunity/armour/vulnerability (diff)
downloadhl2h-a83d3c80d3c555490e7545a191a2c09dd74ca13d.tar.gz
hl2h-a83d3c80d3c555490e7545a191a2c09dd74ca13d.zip
Props: forward DrawModel's modelOrigin argument
DrawModel takes (this, results, info, boneToWorld, flexWeights, flexDelayedWeights, const Vector &modelOrigin, flags). The hook dropped modelOrigin, so flags landed in its slot and the real flags were read from caller stack garbage. studiorender.so 0x83ad0 reads 0x20(%ebp) as the modelOrigin pointer and 0x24(%ebp) as the flags; passing both restores the engine's normal draw. This is the cause of the intermittent (~50%) checkerboard/error-material props: the draw was being issued with a garbage flag word.
Diffstat (limited to 'src/studio.cpp')
-rw-r--r--src/studio.cpp19
1 files changed, 16 insertions, 3 deletions
diff --git a/src/studio.cpp b/src/studio.cpp
index 485b4fb..2d6c826 100644
--- a/src/studio.cpp
+++ b/src/studio.cpp
@@ -25,8 +25,12 @@ namespace {
25using SetColorFn = void (*)(void *, const float *); 25using SetColorFn = void (*)(void *, const float *);
26using SetAlphaFn = void (*)(void *, float); 26using SetAlphaFn = void (*)(void *, float);
27using DrawStaticFn = void (*)(void *, void *, void *, int); 27using DrawStaticFn = void (*)(void *, void *, void *, int);
28// DrawModel takes (this, results, info, boneToWorld, flexWeights,
29// flexDelayedWeights, modelOrigin, flags). The modelOrigin argument is a
30// `const Vector &`, so it arrives as a pointer; omitting it shifts flags into
31// modelOrigin and leaves flags as caller stack garbage.
28using DrawModelFn = void (*)(void *, void *, void *, void *, void *, void *, 32using DrawModelFn = void (*)(void *, void *, void *, void *, void *, void *,
29 int); 33 const void *, int);
30using DrawArrayFn = void (*)(void *, void *, int, void *, int, int); 34using DrawArrayFn = void (*)(void *, void *, int, void *, int, int);
31 35
32SetColorFn g_orig_set_color = nullptr; 36SetColorFn g_orig_set_color = nullptr;
@@ -107,16 +111,25 @@ void hook_set_alpha(void *self, float alpha) {
107 111
108 112
109void hook_draw_model(void *self, void *results, void *info, void *bone, 113void hook_draw_model(void *self, void *results, void *info, void *bone,
110 void *flex, void *flex_delayed, int flags) { 114 void *flex, void *flex_delayed, const void *model_origin,
115 int flags) {
111 const char *model = info_model_name(info); 116 const char *model = info_model_name(info);
112 bool prop = prop_tint_on() && is_prop_model(model); 117 bool prop = prop_tint_on() && is_prop_model(model);
118 static int prop_logs = 0;
119 if (prop && prop_logs < 12) {
120 prop_logs++;
121 void *client = info ? *(void **)((uintptr_t)info + 24) : nullptr;
122 logf("studio: prop draw model=\"%s\" client=%p origin=%p flags=%d",
123 model ? model : "?", client, model_origin, flags);
124 }
113 if (prop) { 125 if (prop) {
114 float c[4]; 126 float c[4];
115 prop_color(c); 127 prop_color(c);
116 g_orig_set_color(self, c); 128 g_orig_set_color(self, c);
117 g_prop_depth++; 129 g_prop_depth++;
118 } 130 }
119 g_orig_draw_model(self, results, info, bone, flex, flex_delayed, flags); 131 g_orig_draw_model(self, results, info, bone, flex, flex_delayed,
132 model_origin, flags);
120 if (prop) 133 if (prop)
121 g_prop_depth--; 134 g_prop_depth--;
122} 135}