summaryrefslogtreecommitdiffstats
path: root/src/cinput.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/cinput.cpp')
-rw-r--r--src/cinput.cpp39
1 files changed, 27 insertions, 12 deletions
diff --git a/src/cinput.cpp b/src/cinput.cpp
index 08686a1..45e2b04 100644
--- a/src/cinput.cpp
+++ b/src/cinput.cpp
@@ -53,23 +53,25 @@ static constexpr size_t VERIFIED_STRIDE = 0x58;
53static constexpr size_t VERIFIED_CRC_OFF = 0x54; 53static constexpr size_t VERIFIED_CRC_OFF = 0x54;
54 54
55CUserCmd *get_usercmd(int seq) { 55CUserCmd *get_usercmd(int seq) {
56 if (!g_input) 56 // Negative sequence numbers would make `seq % 90` negative and the size_t
57 // cast a huge index; reject before forming the pointer.
58 if (!g_input || seq < 0)
57 return nullptr; 59 return nullptr;
58 uintptr_t cmds = *(uintptr_t *)(g_input + CMDOFF_M_PCOMMANDS); 60 uintptr_t cmds = *(uintptr_t *)(g_input + CMDOFF_M_PCOMMANDS);
59 if (!cmds) 61 if (!cmds)
60 return nullptr; 62 return nullptr;
61 auto *cmd = (CUserCmd *)(cmds + (size_t)(seq % 90) * 0x54); 63 auto *cmd = (CUserCmd *)(cmds + (size_t)((unsigned)seq % 90u) * 0x54);
62 if (cmd->command_number != seq) 64 if (cmd->command_number != seq)
63 return nullptr; 65 return nullptr;
64 return cmd; 66 return cmd;
65} 67}
66 68
67void fix_verified_crc(int seq, uint32_t crc) { 69void fix_verified_crc(int seq, uint32_t crc) {
68 if (!g_input) 70 if (!g_input || seq < 0)
69 return; 71 return;
70 uintptr_t verified = *(uintptr_t *)(g_input + CMDOFF_M_PVERIFIED); 72 uintptr_t verified = *(uintptr_t *)(g_input + CMDOFF_M_PVERIFIED);
71 if (verified) 73 if (verified)
72 *(uint32_t *)(verified + (size_t)(seq % 90) * VERIFIED_STRIDE + 74 *(uint32_t *)(verified + (size_t)((unsigned)seq % 90u) * VERIFIED_STRIDE +
73 VERIFIED_CRC_OFF) = crc; 75 VERIFIED_CRC_OFF) = crc;
74} 76}
75 77
@@ -92,6 +94,11 @@ static InputExtraMouseFn oInputExtraMouseSample = nullptr;
92// commands. While the GUI is open it must not touch the view; movement still 94// commands. While the GUI is open it must not touch the view; movement still
93// comes through CreateMove. 95// comes through CreateMove.
94static void hkdInputExtraMouseSample(void *self, float frametime, bool active) { 96static void hkdInputExtraMouseSample(void *self, float frametime, bool active) {
97 if (!init_live()) {
98 if (oInputExtraMouseSample)
99 oInputExtraMouseSample(self, frametime, active);
100 return;
101 }
95 if (gui_is_open()) 102 if (gui_is_open())
96 return; 103 return;
97 if (oInputExtraMouseSample) 104 if (oInputExtraMouseSample)
@@ -109,6 +116,11 @@ void input_clear_mouse_states() {
109 116
110static void hkdInputCreateMove(void *self, int seq, float frametime, 117static void hkdInputCreateMove(void *self, int seq, float frametime,
111 bool active) { 118 bool active) {
119 if (!init_live()) {
120 if (oInputCreateMove)
121 oInputCreateMove(self, seq, frametime, active);
122 return;
123 }
112 // Mouse deltas are accumulated between ticks. With the custom GUI open we 124 // Mouse deltas are accumulated between ticks. With the custom GUI open we
113 // must discard them before CInput::CreateMove applies mouse look, otherwise 125 // must discard them before CInput::CreateMove applies mouse look, otherwise
114 // the view moves for one frame and snaps back when do_move freezes it. 126 // the view moves for one frame and snaps back when do_move freezes it.
@@ -151,8 +163,11 @@ static bool install_input_hook() {
151 if (!vt) 163 if (!vt)
152 return false; 164 return false;
153 constexpr size_t N = 64; 165 constexpr size_t N = 64;
154 void **nvt = new void *[N]; 166 void **nvt = vtable_clone((void *)g_input, N);
155 memcpy(nvt, vt, N * sizeof(void *)); 167 if (!nvt) {
168 logf("CInput vtable clone failed");
169 return false;
170 }
156 oInputCreateMove = (InputCreateMoveFn)vt[3]; 171 oInputCreateMove = (InputCreateMoveFn)vt[3];
157 nvt[3] = (void *)&hkdInputCreateMove; 172 nvt[3] = (void *)&hkdInputCreateMove;
158 if (N > 4) { 173 if (N > 4) {
@@ -173,7 +188,7 @@ static bool install_input_hook() {
173bool find_input_global() { 188bool find_input_global() {
174 void **vt = VTABLE(g_iface.client); 189 void **vt = VTABLE(g_iface.client);
175 uintptr_t cm = (uintptr_t)vt[21]; // CreateMove slot 190 uintptr_t cm = (uintptr_t)vt[21]; // CreateMove slot
176 if (!g_client.contains(cm)) { 191 if (!mod_client().contains(cm)) {
177 logf("CreateMove %p outside client module", (void *)cm); 192 logf("CreateMove %p outside client module", (void *)cm);
178 return false; 193 return false;
179 } 194 }
@@ -189,7 +204,7 @@ bool find_input_global() {
189 break; 204 break;
190 } 205 }
191 } 206 }
192 if (!anchor || !g_client.contains(anchor)) { 207 if (!anchor || !mod_client().contains(anchor)) {
193 logf("PIC anchor not found in CreateMove"); 208 logf("PIC anchor not found in CreateMove");
194 return false; 209 return false;
195 } 210 }
@@ -214,16 +229,16 @@ bool find_input_global() {
214 uint32_t disp; 229 uint32_t disp;
215 memcpy(&disp, b + i + 2, 4); 230 memcpy(&disp, b + i + 2, 4);
216 uintptr_t var = anchor + disp; 231 uintptr_t var = anchor + disp;
217 if (!g_client.contains(var)) 232 if (!mod_client().contains(var))
218 continue; 233 continue;
219 uintptr_t input = *(uintptr_t *)var; 234 uintptr_t input = *(uintptr_t *)var;
220 if (!input || !g_client.contains(input)) 235 if (!input || !mod_client().contains(input))
221 continue; 236 continue;
222 uintptr_t vtbl = *(uintptr_t *)input; 237 uintptr_t vtbl = *(uintptr_t *)input;
223 if (!vtbl || !g_client.contains(vtbl)) 238 if (!vtbl || !mod_client().contains(vtbl))
224 continue; 239 continue;
225 uintptr_t f3 = *(uintptr_t *)(vtbl + 3 * sizeof(void *)); 240 uintptr_t f3 = *(uintptr_t *)(vtbl + 3 * sizeof(void *));
226 if (!g_client.contains(f3)) 241 if (!mod_client().contains(f3))
227 continue; 242 continue;
228 logd("CInput* = %#lx (ptr var %#lx, vfunc[3] %#lx)", (unsigned long)input, 243 logd("CInput* = %#lx (ptr var %#lx, vfunc[3] %#lx)", (unsigned long)input,
229 (unsigned long)var, (unsigned long)f3); 244 (unsigned long)var, (unsigned long)f3);