aboutsummaryrefslogtreecommitdiff
path: root/src/demorec.c
diff options
context:
space:
mode:
authorGravatar Michael Smith <mikesmiffy128@gmail.com> 2025-08-02 16:15:15 +0100
committerGravatar Michael Smith <mikesmiffy128@gmail.com> 2025-08-02 20:43:12 +0100
commit3cce0e5621dc118b32c4143b42ced51c5328f7c7 (patch)
treee1f6fe636818999b72fe6913c8ec50fdff7583a1 /src/demorec.c
parent0d905d7998a031c2d7a1cdc5d0d1148b55b610a2 (diff)
downloadsst-3cce0e5621dc118b32c4143b42ced51c5328f7c7.tar.gz
sst-3cce0e5621dc118b32c4143b42ced51c5328f7c7.zip
Add an abstraction for hooking v1 and v2 commands
This is a step towards making command hooks work in OE, once OE is supported. Not the most ideal or efficient thing in the world, but it works okay until we come up with something better, I suppose. Not a fan of the argv copying but avoiding that would make the API a lot less ergonomic. Not the easiest problem to solve, really...
Diffstat (limited to 'src/demorec.c')
-rw-r--r--src/demorec.c35
1 files changed, 14 insertions, 21 deletions
diff --git a/src/demorec.c b/src/demorec.c
index 6f1b2a7..a763176 100644
--- a/src/demorec.c
+++ b/src/demorec.c
@@ -101,16 +101,15 @@ static void VCALLCONV hook_StopRecording(struct CDemoRecorder *this) {
DECL_VFUNC_DYN(struct CDemoRecorder, void, StartRecording)
static struct con_cmd *cmd_record, *cmd_stop;
-static con_cmdcbv2 orig_record_cb, orig_stop_cb;
-static void hook_record_cb(const struct con_cmdargs *args) {
+DEF_CCMD_COMPAT_HOOK(record) {
if_cold (!CHECK_DemoControlAllowed()) return;
bool was = *recording;
- if (!was && args->argc == 2 || args->argc == 3) {
+ if (!was && argc == 2 || argc == 3) {
// safety check: make sure a directory exists, otherwise recording
// silently fails. this is necessarily TOCTOU, but in practice it's
// way better than not doing it - just to have a sanity check.
- const char *arg = args->argv[1];
+ const char *arg = argv[1];
const char *lastslash = 0;
for (const char *p = arg; *p; ++p) {
#ifdef _WIN32
@@ -155,7 +154,7 @@ static void hook_record_cb(const struct con_cmdargs *args) {
}
}
}
- orig_record_cb(args);
+ orig_record_cb(argc, argv);
if (!was && *recording) {
*demonum = 0; // see SetSignonState comment above
// For UX, make it more obvious we're recording, in particular when not
@@ -166,16 +165,15 @@ static void hook_record_cb(const struct con_cmdargs *args) {
EMIT_DemoRecordStarting();
}
-static void hook_stop_cb(const struct con_cmdargs *args) {
+DEF_CCMD_COMPAT_HOOK(stop) {
if_cold (!CHECK_DemoControlAllowed()) return;
wantstop = true;
- orig_stop_cb(args);
+ orig_stop_cb(argc, argv);
wantstop = false;
}
-static inline bool find_demorecorder() {
+static inline bool find_demorecorder(const uchar *insns) {
#ifdef _WIN32
- const uchar *insns = (const uchar *)orig_stop_cb;
// The stop command loads `demorecorder` into ECX to call IsRecording()
for (const uchar *p = insns; p - insns < 32;) {
if (p[0] == X86_MOVRMW && p[1] == X86_MODRM(0, 1, 5)) {
@@ -238,8 +236,8 @@ bool demorec_start(const char *name) {
if (was) return false;
// dumb but easy way to do this: call the record command callback. note:
// this args object is very incomplete by enough to make the command work
- struct con_cmdargs args = {.argc = 2, .argv = {0, name, 0}};
- orig_record_cb(&args);
+ // TODO(compat): will this be a problem for OE with the global argc/argv?
+ orig_record_cb(2, (const char *[]){0, name});
if (!was && *recording) *demonum = 0; // same logic as in the hook
EMIT_DemoRecordStarting();
return *recording;
@@ -260,10 +258,8 @@ int demorec_demonum() {
INIT {
cmd_record = con_findcmd("record");
- orig_record_cb = con_getcmdcbv2(cmd_record);
cmd_stop = con_findcmd("stop");
- orig_stop_cb = con_getcmdcbv2(cmd_stop);
- if_cold (!find_demorecorder()) {
+ if_cold (!find_demorecorder(cmd_stop->cb_insns)) {
errmsg_errorx("couldn't find demo recorder instance");
return FEAT_INCOMPAT;
}
@@ -281,15 +277,12 @@ INIT {
errmsg_errorx("couldn't find demo basename variable");
return FEAT_INCOMPAT;
}
-
orig_SetSignonState = (SetSignonState_func)hook_vtable(vtable,
vtidx_SetSignonState, (void *)&hook_SetSignonState);
orig_StopRecording = (StopRecording_func)hook_vtable(vtable,
vtidx_StopRecording, (void *)&hook_StopRecording);
-
- cmd_record->cb_v2 = &hook_record_cb;
- cmd_stop->cb_v2 = &hook_stop_cb;
-
+ hook_record_cb(cmd_record);
+ hook_stop_cb(cmd_stop);
return FEAT_OK;
}
@@ -300,8 +293,8 @@ END {
void **vtable = demorecorder->vtable;
unhook_vtable(vtable, vtidx_SetSignonState, (void *)orig_SetSignonState);
unhook_vtable(vtable, vtidx_StopRecording, (void *)orig_StopRecording);
- cmd_record->cb_v2 = orig_record_cb;
- cmd_stop->cb_v2 = orig_stop_cb;
+ unhook_record_cb(cmd_record);
+ unhook_stop_cb(cmd_stop);
}
// vi: sw=4 ts=4 noet tw=80 cc=80