diff options
author | 2025-04-17 01:39:10 +0100 | |
---|---|---|
committer | 2025-04-17 20:02:18 +0100 | |
commit | 8a669bc96ffdb9d0f6f54e464da11e3375c80a55 (patch) | |
tree | 569dac0cd082ad25e779a69f0bcceff5ca212bb1 /src/ac.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/ac.c')
-rw-r--r-- | src/ac.c | 16 |
1 files changed, 10 insertions, 6 deletions
@@ -281,8 +281,11 @@ struct inputevent { int data, data2, data3; }; -DECL_VFUNC_DYN(void, GetDesktopResolution, int *, int *) -DECL_VFUNC_DYN(void, DispatchAllStoredGameMessages) +struct IGameUIFuncs { void **vtable; }; +struct IGame { void **vtable; }; + +DECL_VFUNC_DYN(struct IGameUIFuncs, void, GetDesktopResolution, int *, int *) +DECL_VFUNC_DYN(struct IGame, void, DispatchAllStoredGameMessages) typedef void (*Key_Event_func)(struct inputevent *); static Key_Event_func orig_Key_Event; @@ -314,13 +317,14 @@ static bool find_Key_Event() { // -> IGame/CGame (first mov into ECX) // -> CGame::DispatchAllStoredGameMessages vfunc // -> First call instruction (either DispatchInputEvent or Key_Event) - void *gameuifuncs = factory_engine("VENGINE_GAMEUIFUNCS_VERSION005", 0); + struct IGameUIFuncs *gameuifuncs = factory_engine( + "VENGINE_GAMEUIFUNCS_VERSION005", 0); if_cold (!gameuifuncs) { errmsg_errorx("couldn't get engine game UI interface"); return false; } - void *cgame; - const uchar *insns = (const uchar *)VFUNC(gameuifuncs, GetDesktopResolution); + struct IGame *cgame; + const uchar *insns = gameuifuncs->vtable[vtidx_GetDesktopResolution]; for (const uchar *p = insns; p - insns < 16;) { if (p[0] == X86_MOVRMW && p[1] == X86_MODRM(0, 1, 5)) { void **indirect = mem_loadptr(p + 2); @@ -332,7 +336,7 @@ static bool find_Key_Event() { errmsg_errorx("couldn't find pointer to CGame instance"); return false; -ok: insns = (const uchar *)VFUNC(cgame, DispatchAllStoredGameMessages); +ok: insns = cgame->vtable[vtidx_DispatchAllStoredGameMessages]; for (const uchar *p = insns; p - insns < 128;) { if (p[0] == X86_CALL) { orig_Key_Event = (Key_Event_func)(p + 5 + mem_loads32(p + 1)); |