diff options
author | 2025-04-17 01:39:10 +0100 | |
---|---|---|
committer | 2025-04-17 20:02:18 +0100 | |
commit | 8a669bc96ffdb9d0f6f54e464da11e3375c80a55 (patch) | |
tree | 569dac0cd082ad25e779a69f0bcceff5ca212bb1 /src/demorec.c | |
parent | 0b40d4d9ea1cbfbb92795e0d6f26cf108f2dec5f (diff) | |
download | sst-8a669bc96ffdb9d0f6f54e464da11e3375c80a55.tar.gz sst-8a669bc96ffdb9d0f6f54e464da11e3375c80a55.zip |
Add type-safety to virtual calls and accessors
This probably should have been the design from the start.
It's still possible to use void pointers, and this is done in a couple
of places for simplicity, but wherever possible, we have actual structs
for things now.
Additionally, in places where vtables are fiddled with, e.g. vtable
hooks, we have actual struct definitions with vtable pointers so there's
need for pointer-casting horror.
Diffstat (limited to 'src/demorec.c')
-rw-r--r-- | src/demorec.c | 21 |
1 files changed, 10 insertions, 11 deletions
diff --git a/src/demorec.c b/src/demorec.c index 5aacf06..7bdc517 100644 --- a/src/demorec.c +++ b/src/demorec.c @@ -18,6 +18,7 @@ #include <string.h> #include "con_.h" +#include "demorec.h" #include "engineapi.h" #include "errmsg.h" #include "event.h" @@ -29,7 +30,6 @@ #include "langext.h" #include "mem.h" #include "os.h" -#include "ppmagic.h" #include "sst.h" #include "vcall.h" #include "x86.h" @@ -44,7 +44,7 @@ REQUIRE_GAMEDATA(vtidx_RecordPacket) DEF_FEAT_CVAR(sst_autorecord, "Continuously record demos even after reconnecting", 1, CON_ARCHIVE) -void *demorecorder; +struct CDemoRecorder *demorecorder; static int *demonum; static bool *recording; const char *demorec_basename; @@ -59,12 +59,11 @@ DEF_PREDICATE(DemoControlAllowed) DEF_EVENT(DemoRecordStarting) DEF_EVENT(DemoRecordStopped, int) -DECL_VCALL_DYN(SetSignonState, int) +struct CDemoRecorder; -//typedef void (*VCALLCONV SetSignonState_func)(void *, int); +typedef void (*VCALLCONV SetSignonState_func)(struct CDemoRecorder *, int); static SetSignonState_func orig_SetSignonState; -static void VCALLCONV hook_SetSignonState(void *this_, int state) { - struct CDemoRecorder *this = this_; +static void VCALLCONV hook_SetSignonState(struct CDemoRecorder *this, int state) { // NEW fires once every map or save load, but only bumps number if demo file // was left open (i.e. every transition). bump it unconditionally instead! if (state == SIGNONSTATE_NEW) { @@ -81,9 +80,9 @@ static void VCALLCONV hook_SetSignonState(void *this_, int state) { orig_SetSignonState(this, state); } -typedef void (*VCALLCONV StopRecording_func)(void *); +typedef void (*VCALLCONV StopRecording_func)(struct CDemoRecorder *); static StopRecording_func orig_StopRecording; -static void VCALLCONV hook_StopRecording(void *this) { +static void VCALLCONV hook_StopRecording(struct CDemoRecorder *this) { bool wasrecording = *recording; int lastnum = *demonum; orig_StopRecording(this); @@ -99,7 +98,7 @@ static void VCALLCONV hook_StopRecording(void *this) { } } -DECL_VFUNC_DYN(void, StartRecording) +DECL_VFUNC_DYN(struct CDemoRecorder, void, StartRecording) static struct con_cmd *cmd_record, *cmd_stop; static con_cmdcb orig_record_cb, orig_stop_cb; @@ -268,7 +267,7 @@ INIT { errmsg_errorx("couldn't find demo recorder instance"); return FEAT_INCOMPAT; } - void **vtable = mem_loadptr(demorecorder); + void **vtable = demorecorder->vtable; // XXX: 16 is totally arbitrary here! figure out proper bounds later if_cold (!os_mprot(vtable, 16 * sizeof(void *), PAGE_READWRITE)) { errmsg_errorsys("couldn't make virtual table writable"); @@ -298,7 +297,7 @@ END { if_hot (!sst_userunloaded) return; // avoid dumb edge case if someone somehow records and immediately unloads if (*recording && *demonum == 0) *demonum = 1; - void **vtable = mem_loadptr(demorecorder); + void **vtable = demorecorder->vtable; unhook_vtable(vtable, vtidx_SetSignonState, (void *)orig_SetSignonState); unhook_vtable(vtable, vtidx_StopRecording, (void *)orig_StopRecording); cmd_record->cb = orig_record_cb; |