summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorMichael Smith <mikesmiffy128@gmail.com>2023-05-05 00:07:39 +0100
committerMichael Smith <mikesmiffy128@gmail.com>2023-05-05 00:07:39 +0100
commit182b36609acc44d3338f64ca3975e1604b50f619 (patch)
treeeea08823a5ce668148154c322c94193df28eb1af /src
parent3ff6d47277fc0e39053584d8889240cab446a72a (diff)
Somewhat expand on WIP ac.c stuff
This still isn't totally complete, or used anywhere yet, but it's been sitting here for literally months, so it might as well get committed so there's one less thing to deal with later.
Diffstat (limited to 'src')
-rw-r--r--src/ac.c73
-rw-r--r--src/ac.h5
2 files changed, 58 insertions, 20 deletions
diff --git a/src/ac.c b/src/ac.c
index 326894a..01b969f 100644
--- a/src/ac.c
+++ b/src/ac.c
@@ -1,5 +1,5 @@
/*
- * Copyright © 2022 Michael Smith <mikesmiffy128@gmail.com>
+ * Copyright © 2023 Michael Smith <mikesmiffy128@gmail.com>
* Copyright © 2022 Willian Henrique <wsimanbrazil@yahoo.com.br>
*
* Permission to use, copy, modify, and/or distribute this software for any
@@ -16,6 +16,9 @@
*/
#include <stdlib.h>
+#ifdef _WIN32
+#include <immintrin.h>
+#endif
#include "bind.h"
#include "con_.h"
@@ -67,29 +70,50 @@ static ssize __stdcall mproc(int code, UINT_PTR wp, ssize lp) {
// this is its own thread to meet the strict timing deadline, otherwise the
// hook gets silently removed. plus, we don't wanna incur latency anyway.
-static ulong __stdcall inhookthrmain(void *unused) {
+static ulong __stdcall inhookthrmain(void *param) {
+ volatile u32 *sig = param;
if (!SetWindowsHookExW(WH_KEYBOARD_LL, &kproc, 0, 0) ||
!SetWindowsHookExW(WH_MOUSE_LL, &mproc, 0, 0)) {
+ *sig = 2;
return -1;
}
+ *sig = 1;
MSG m; int ret;
while ((ret = GetMessageW(&m, inhookwin, 0, 0)) > 0) DispatchMessage(&m);
return ret;
}
+static WNDPROC orig_wndproc;
+static ssize __stdcall hook_wndproc(void *wnd, uint msg, UINT_PTR wp, ssize lp) {
+ if (msg == WM_COPYDATA && lockdown) return DefWindowProcW(wnd, msg, wp, lp);
+ return orig_wndproc(wnd, msg, wp, lp);
+}
+
static bool win32_init(void) {
gamewin = FindWindowW(L"Valve001", 0);
+ // note: error messages here are a bit cryptic on purpose, but easy to find
+ // in the code. in other words, we're hiding in plain sight :-)
if (!gamewin) {
- errmsg_errorsys("failed to get game window handle");
+ errmsg_errorsys("failed to find window");
return false;
}
+ orig_wndproc = (WNDPROC)SetWindowLongPtrW(gamewin, GWLP_WNDPROC,
+ (ssize)hook_wndproc);
+ if (!orig_wndproc) {
+ errmsg_errorsys("failed to attach message handler");
+ }
return true;
}
-static void inhook_start(void) {
- inhookwin = CreateWindowW(L"sst-eventloop", L"sst-eventloop",
- WS_DISABLED, 0, 0, 0, 0, HWND_MESSAGE, 0, 0, 0);
- inhookthr = CreateThread(0, 0, &inhookthrmain, 0, 0, &inhooktid);
+static void win32_end(void) {
+ // no error handling here because we'd crash either way. good luck!
+ SetWindowLongW(gamewin, GWLP_WNDPROC, (ssize)orig_wndproc);
+}
+
+static void inhook_start(volatile u32 *sig) {
+ inhookwin = CreateWindowW(L"sst-eventloop", L"sst-eventloop", WS_DISABLED,
+ 0, 0, 0, 0, HWND_MESSAGE, 0, 0, 0);
+ inhookthr = CreateThread(0, 0, &inhookthrmain, (u32 *)sig, 0, &inhooktid);
}
static void inhook_check(void) {
@@ -120,6 +144,7 @@ static void inhook_stop(void) {
// not much else we can do now!
con_warn("warning: RTA mode message loop had an error during shutdown");
}
+ CloseHandle(inhookthr);
}
#else
@@ -128,20 +153,27 @@ static void inhook_stop(void) {
#endif
-// TODO(rta): call these functions as part of the run lifecycle
-
-static void startlockdown(void) {
- if (lockdown) return;
+bool ac_enable(void) {
+ if (lockdown) return true;
#ifdef _WIN32
- inhook_start();
+ // and now for some frivolously microoptimised spinlocking nonsense
+ volatile u32 sig = 0; // paranoid volatile to ensure no loop misopt...
+ inhook_start(&sig);
+ register u32 x; // avoid double-reading the volatile
+ // pausing in the middle here seems to produce shorter asm with gcc -O2 and
+ // clang -O3 in godbolt (avoids unrolling of head which is unlikely to help)
+ while (x = sig, _mm_pause(), !x);
+ if (x == 2) { // else 1 for success
+ con_warn("** sst: ERROR starting message loop, can't continue! **");
+ CloseHandle(inhookthr);
+ return false;
+ }
#endif
- // FIXME: should really have some semaphore to make sure inhook thread got
- // going okay...
lockdown = true;
- // TODO(rta): start demos, etc
+ return true;
}
-HANDLE_EVENT(Tick) {
+HANDLE_EVENT(Tick, bool simulating) {
#ifdef _WIN32
static uint fewticks = 0;
// just check this every so often (roughly 0.1-0.3s depending on game)
@@ -149,7 +181,7 @@ HANDLE_EVENT(Tick) {
#endif
}
-static void endlockdown(void) {
+void ac_disable(void) {
if (!lockdown) return;
#ifdef _WIN32
inhook_stop();
@@ -262,7 +294,12 @@ INIT {
}
END {
- endlockdown();
+#if defined(_WIN32)
+ win32_end();
+#elif defined(__linux__)
+ // TODO(linux): call cleanup things
+#endif
+ ac_disable();
unhook_inline((void *)orig_DispatchInputEvent);
}
diff --git a/src/ac.h b/src/ac.h
index 7b48cd1..2da6446 100644
--- a/src/ac.h
+++ b/src/ac.h
@@ -1,5 +1,5 @@
/*
- * Copyright © 2022 Michael Smith <mikesmiffy128@gmail.com>
+ * Copyright © 2023 Michael Smith <mikesmiffy128@gmail.com>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -17,7 +17,8 @@
#ifndef INC_AC_H
#define INC_AC_H
-// TODO(rta): keeping this header here as I expect to expose some functions...
+bool ac_enable(void);
+void ac_disable(void);
#endif