summaryrefslogtreecommitdiffhomepage
path: root/src/con_.c
diff options
context:
space:
mode:
authorMichael Smith <mikesmiffy128@gmail.com>2022-05-13 16:01:38 +0100
committerMichael Smith <mikesmiffy128@gmail.com>2022-05-13 16:01:38 +0100
commit831862bec84dde31a0568ec8a2f2b0170e18a973 (patch)
treeee4143dd17412bb44f2b8cc3f999842e169b0a7d /src/con_.c
parent829dece47f305979bd1375300ebc14fc2e264c0a (diff)
Properly finish refactoring con to use gamedata
Diffstat (limited to 'src/con_.c')
-rw-r--r--src/con_.c163
1 files changed, 65 insertions, 98 deletions
diff --git a/src/con_.c b/src/con_.c
index 715872b..27c7745 100644
--- a/src/con_.c
+++ b/src/con_.c
@@ -50,35 +50,21 @@ void *_con_iface;
void (*_con_colourmsgf)(void *this, const struct con_colour *c, const char *fmt,
...) _CON_PRINTF(3, 4);
-// XXX: the const and non-const entries might actually be flipped on windows,
-// not 100% sure, but dunno if it's worth essentially duping most of these when
-// the actual executed machine code is probably identical anyway.
-// XXX: make these use gamedata at some point and avoid all the conditionals,
-// now that gamedata is populated before the rest of console init
-DECL_VFUNC(int, AllocateDLLIdentifier, 5)
-DECL_VFUNC(int, AllocateDLLIdentifier_p2, 8)
-DECL_VFUNC(void, RegisterConCommand, 6, /*ConCommandBase*/ void *)
-DECL_VFUNC(void, RegisterConCommand_p2, 9, /*ConCommandBase*/ void *)
-DECL_VFUNC(void, UnregisterConCommands, 8, int)
-DECL_VFUNC(void, UnregisterConCommands_p2, 11, int)
-// DECL_VFUNC(void *, FindCommandBase, 10, const char *)
+// bootstrap hackery, see "GENIUS HACK" comment below :)
DECL_VFUNC(void *, FindCommandBase_p2, 13, const char *)
-DECL_VFUNC(struct con_var *, FindVar, 12, const char *)
+DECL_VFUNC(void *, FindCommand_nonp2, 14, const char *)
+DECL_VFUNC(void *, FindVar_nonp2, 12, const char *)
+
+// rest of these are figured out from gamedata after initial game detection
+DECL_VFUNC_DYN(int, AllocateDLLIdentifier)
+DECL_VFUNC_DYN(void, RegisterConCommand, /*ConCommandBase*/ void *)
+DECL_VFUNC_DYN(void, UnregisterConCommands, int)
+DECL_VFUNC_DYN(struct con_var *, FindVar, const char *)
// DECL_VFUNC(const struct con_var *, FindVar_const, 13, const char *)
-DECL_VFUNC(struct con_var *, FindVar_p2, 15, const char *)
-DECL_VFUNC(struct con_cmd *, FindCommand, 14, const char *)
-DECL_VFUNC(struct con_cmd *, FindCommand_p2, 17, const char *)
-DECL_VFUNC(void, CallGlobalChangeCallbacks, 20, struct con_var *, const char *,
+DECL_VFUNC_DYN(struct con_cmd *, FindCommand, const char *)
+DECL_VFUNC_DYN(void, CallGlobalChangeCallbacks, struct con_var *, const char *,
float)
-DECL_VFUNC(void, CallGlobalChangeCallbacks_l4d, 18, struct con_var *,
- const char *, float)
-DECL_VFUNC(void, CallGlobalChangeCallbacks_p2, 21, struct con_var *,
- const char *, float)
-DECL_VFUNC_CDECL(void, ConsoleColorPrintf_004, 23, const struct con_colour *,
- const char *, ...)
-DECL_VFUNC_CDECL(void, ConsoleColorPrintf_l4d, 21, const struct con_colour *,
- const char *, ...)
-DECL_VFUNC_CDECL(void, ConsoleColorPrintf_p2, 24, const struct con_colour *,
+DECL_VFUNC_CDECLDYN(void, ConsoleColorPrintf, const struct con_colour *,
const char *, ...)
static inline void initval(struct con_var *v) {
@@ -95,8 +81,12 @@ static inline void initval(struct con_var *v) {
// required, we call the Internal* virtual functions by actual virtual lookup.
// since the vtables are filled dynamically (below), we store this index; other
// indices are just offset from this one since the 3-or-4 functions are all
-// right next to each other.
+// right next to each other. the #defines allow us to still use the nice VCALL
+// stuff.
static int vtidx_InternalSetValue;
+#define vtidx_InternalSetFloatValue (vtidx_InternalSetValue + 1)
+#define vtidx_InternalSetIntValue (vtidx_InternalSetValue + 2)
+#define vtidx_InternalSetColorValue (vtidx_InternalSetValue + 3)
// implementation of virtual functions for our vars and commands below...
@@ -190,15 +180,7 @@ static void VCALLCONV ChangeStringValue(struct con_var *this, const char *s,
// do need callbacks for at least one feature, so do our own minimal thing
if (this->cb) this->cb(this);
// also call global callbacks, as is polite.
- if (GAMETYPE_MATCHES(Portal2)) {
- VCALL(_con_iface, CallGlobalChangeCallbacks_p2, this, old, oldf);
- }
- else if (GAMETYPE_MATCHES(L4D)) {
- VCALL(_con_iface, CallGlobalChangeCallbacks_l4d, this, old, oldf);
- }
- else {
- VCALL(_con_iface, CallGlobalChangeCallbacks, this, old, oldf);
- }
+ VCALL(_con_iface, CallGlobalChangeCallbacks, this, old, oldf);
}
static void VCALLCONV InternalSetValue(struct con_var *this, const char *v) {
@@ -241,32 +223,32 @@ static void VCALLCONV InternalSetIntValue(struct con_var *this, int v) {
}
}
+DECL_VFUNC_DYN(void, InternalSetValue, const char *)
+DECL_VFUNC_DYN(void, InternalSetFloatValue, float)
+DECL_VFUNC_DYN(void, InternalSetIntValue, int)
+DECL_VFUNC_DYN(void, InternalSetColorValue, struct con_colour)
+
// Hack: IConVar things get this-adjusted pointers, we just reverse the offset
// to get the top pointer.
-// XXX: rewrite these at some point to use the normal VCALL stuff
static void VCALLCONV SetValue_str_thunk(void *thisoff, const char *v) {
struct con_var *this = mem_offset(thisoff,
-offsetof(struct con_var, vtable_iconvar));
- ((void (*VCALLCONV)(void *, const char *))(this->parent->base.vtable[
- vtidx_InternalSetValue]))(this, v);
+ VCALL(&this->parent->base, InternalSetValue, v);
}
static void VCALLCONV SetValue_f_thunk(void *thisoff, float v) {
struct con_var *this = mem_offset(thisoff,
-offsetof(struct con_var, vtable_iconvar));
- ((void (*VCALLCONV)(void *, float))(this->parent->base.vtable[
- vtidx_InternalSetValue + 1]))(this, v);
+ VCALL(&this->parent->base, InternalSetFloatValue, v);
}
static void VCALLCONV SetValue_i_thunk(void *thisoff, int v) {
struct con_var *this = mem_offset(thisoff,
-offsetof(struct con_var, vtable_iconvar));
- ((void (*VCALLCONV)(void *, int))(this->parent->base.vtable[
- vtidx_InternalSetValue + 2]))(this, v);
+ VCALL(&this->parent->base, InternalSetIntValue, v);
}
static void VCALLCONV SetValue_colour_thunk(void *thisoff, struct con_colour v) {
struct con_var *this = mem_offset(thisoff,
-offsetof(struct con_var, vtable_iconvar));
- ((void (*VCALLCONV)(void *, struct con_colour))(this->parent->base.vtable[
- vtidx_InternalSetValue + 3]))(this, v);
+ VCALL(&this->parent->base, InternalSetColorValue, v);
}
// more misc thunks, hopefully these just compile to a sub and a jmp
@@ -339,7 +321,14 @@ void *_con_vtab_iconvar[7] = {
#endif
};
+void con_reg(void *cmd_or_var) {
+ VCALL(_con_iface, RegisterConCommand, cmd_or_var);
+}
+
void con_init(void) {
+ _con_colourmsgf = VFUNC(_con_iface, ConsoleColorPrintf);
+ dllid = VCALL(_con_iface, AllocateDLLIdentifier);
+
void **pc = _con_vtab_cmd + 3 + NVDTOR, **pv = _con_vtab_var + 3 + NVDTOR,
**pi = _con_vtab_iconvar
#ifndef _WIN32
@@ -402,17 +391,19 @@ void con_init(void) {
regcmds();
}
-void con_reg(void *cmd_or_var) {
- if (GAMETYPE_MATCHES(Portal2)) {
- VCALL(_con_iface, RegisterConCommand_p2, cmd_or_var);
- }
- else {
- VCALL(_con_iface, RegisterConCommand, cmd_or_var);
- }
+static void helpuserhelpus(int pluginver, char ifaceverchar) {
+ con_msg("\n");
+ con_msg("-- Please include ALL of the following if asking for help:\n");
+ con_msg("-- plugin: " LONGNAME " v" VERSION "\n");
+ con_msg("-- interfaces: %d/%c\n", pluginver, ifaceverchar);
+ con_msg("\n");
+}
+
+static void warnoe(void) {
+ con_warn("sst: error: this engine version is not yet supported\n");
}
bool con_detect(int pluginver) {
- int ifacever; // for error messages
if (_con_iface = factory_engine("VEngineCvar007", 0)) {
// GENIUS HACK (BUT STILL BAD): Portal 2 has everything in ICvar shifted
// down 3 places due to the extra stuff in IAppSystem. This means that
@@ -421,88 +412,63 @@ bool con_detect(int pluginver) {
// which just happens to still work fine. From there, we can figure out
// the actual ABI to use to avoid spectacular crashes.
if (VCALL(_con_iface, FindCommandBase_p2, "portal2_square_portals")) {
- _con_colourmsgf = VFUNC(_con_iface, ConsoleColorPrintf_p2);
- dllid = VCALL(_con_iface, AllocateDLLIdentifier_p2);
_gametype_tag |= _gametype_tag_Portal2;
+ return true;
}
- else if (VCALL(_con_iface, FindCommand, "l4d2_snd_adrenaline")) {
- _con_colourmsgf = VFUNC(_con_iface, ConsoleColorPrintf_l4d);
- dllid = VCALL(_con_iface, AllocateDLLIdentifier);
+ if (VCALL(_con_iface, FindCommand_nonp2, "l4d2_snd_adrenaline")) {
// while we're here, also distinguish Survivors, the stupid Japanese
// arcade game a few people seem to care about for some reason
// (which for some other reason also has some vtable changes)
- if (VCALL(_con_iface, FindVar, "avatarbasemodel")) {
+ if (VCALL(_con_iface, FindVar_nonp2, "avatarbasemodel")) {
_gametype_tag |= _gametype_tag_L4DS;
}
else {
_gametype_tag |= _gametype_tag_L4D2;
}
+ return true;
}
- else if (VCALL(_con_iface, FindVar, "z_difficulty")) {
- _con_colourmsgf = VFUNC(_con_iface, ConsoleColorPrintf_l4d);
- dllid = VCALL(_con_iface, AllocateDLLIdentifier);
+ if (VCALL(_con_iface, FindVar_nonp2, "z_difficulty")) {
_gametype_tag |= _gametype_tag_L4D1;
+ return true;
}
- else {
- con_warn("sst: error: game is unsupported (using VEngineCvar007)\n");
- ifacever = 7;
- goto e;
- }
- return true;
+ con_warn("sst: error: game is unsupported (using VEngineCvar007)\n");
+ helpuserhelpus(pluginver, '7');
+ return false;
}
if (_con_iface = factory_engine("VEngineCvar004", 0)) {
// TODO(compat): are there any cases where 004 is incompatible? could
// this crash? find out!
- _con_colourmsgf = VFUNC(_con_iface, ConsoleColorPrintf_004);
- dllid = VCALL(_con_iface, AllocateDLLIdentifier);
- // even more spaghetti! we need the plugin interface version to
- // accurately distinguish 2007/2013 branches
if (pluginver == 3) _gametype_tag |= _gametype_tag_2013;
else _gametype_tag |= _gametype_tag_OrangeBox;
return true;
}
if (factory_engine("VEngineCvar003", 0)) {
- ifacever = 3;
- goto warnoe;
+ warnoe();
+ helpuserhelpus(pluginver, '3');
+ return false;
}
+ // I don't suppose there's anything below 002 worth caring about? Shrug.
if (factory_engine("VEngineCvar002", 0)) {
- // I don't suppose there's anything below 002 worth caring about? Shrug.
- ifacever = 2;
-warnoe: con_warn("sst: error: old engine console support is not implemented\n");
- goto e;
+ warnoe();
+ helpuserhelpus(pluginver, '2');
+ return false;
}
con_warn("sst: error: couldn't find a supported console interface\n");
- ifacever = -1; // meh
-e: con_msg("\n\n");
- con_msg("-- Please include ALL of the following if asking for help:\n");
- con_msg("-- plugin: " LONGNAME " v" VERSION "\n");
- con_msg("-- interfaces: %d/%d\n", pluginver, ifacever);
- con_msg("\n\n");
+ helpuserhelpus(pluginver, '?');
return false;
}
void con_disconnect(void) {
- if (GAMETYPE_MATCHES(Portal2)) {
- VCALL(_con_iface, UnregisterConCommands_p2, dllid);
- }
- else {
- VCALL(_con_iface, UnregisterConCommands, dllid);
- }
+ VCALL(_con_iface, UnregisterConCommands, dllid);
freevars();
}
struct con_var *con_findvar(const char *name) {
- if (GAMETYPE_MATCHES(Portal2)) return VCALL(_con_iface, FindVar_p2, name);
- else return VCALL(_con_iface, FindVar, name);
+ return VCALL(_con_iface, FindVar, name);
}
struct con_cmd *con_findcmd(const char *name) {
- if (GAMETYPE_MATCHES(Portal2)) {
- return VCALL(_con_iface, FindCommand_p2, name);
- }
- else {
- return VCALL(_con_iface, FindCommand, name);
- }
+ return VCALL(_con_iface, FindCommand, name);
}
#define GETTER(T, N, M) T N(const struct con_var *v) { return v->parent->M; }
@@ -511,6 +477,7 @@ GETTER(float, con_getvarf, fval)
GETTER(int, con_getvari, ival)
#undef GETTER
+// XXX: move this to vcall/gamedata (will require win/linux conditionals first!)
#define SETTER(T, I, N) \
void N(struct con_var *v, T x) { \
((void (*VCALLCONV)(void *, T))(v->vtable_iconvar[I]))( \