summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorMichael Smith <mikesmiffy128@gmail.com>2022-12-26 14:29:53 +0000
committerMichael Smith <mikesmiffy128@gmail.com>2023-01-15 15:17:51 +0000
commita4afb6714f67c029310c0853ff47fdef354e2e72 (patch)
tree918a490474ad71d5b6ac817d409bae5e8ab990d5
parentf28cd3c70fc75114413ce0719e298f30cec407fa (diff)
Fix deferred init for Portal 2 compatibility
Thanks Bill for figuring out what the problem was.
-rw-r--r--TODO/compat2
-rw-r--r--gamedata/engine.kv9
-rw-r--r--src/con_.c1
-rw-r--r--src/engineapi.c3
-rw-r--r--src/engineapi.h2
-rw-r--r--src/fov.c1
-rw-r--r--src/sst.c50
7 files changed, 34 insertions, 34 deletions
diff --git a/TODO/compat b/TODO/compat
index 08d7c7f..7f210e8 100644
--- a/TODO/compat
+++ b/TODO/compat
@@ -1,5 +1,3 @@
Support more games and engine branches
====
Pretty self-explanatory.
-
-*Alert! It seems Portal 2 had some stuff broken! Fix before 1.0 release!*
diff --git a/gamedata/engine.kv b/gamedata/engine.kv
index fdc03ff..72243b4 100644
--- a/gamedata/engine.kv
+++ b/gamedata/engine.kv
@@ -86,6 +86,13 @@ off_SP_offset {
}
// IEngineVGuiInternal/CEngineVGui
-vtidx_VGuiConnect "3 + NVDTOR" // note: real name is Connect, way too generic
+vtidx_VGuiConnect { // note: the actual name is Connect() but that's too generic
+ default "3 + NVDTOR"
+ Portal2 "4 + NVDTOR" // ActivateGameUI added
+}
+vtidx_VGuiIsInitialized { // likewise, function is just called IsInitialized()
+ default "6 + NVDTOR"
+ Portal2 "7 + NVDTOR"
+}
// vi: sw=4 ts=4 noet tw=80 cc=80 ft=plain
diff --git a/src/con_.c b/src/con_.c
index f8b24f6..7a153e0 100644
--- a/src/con_.c
+++ b/src/con_.c
@@ -329,7 +329,6 @@ void con_reg(void *cmd_or_var) {
}
void con_init(void) {
- // FIXME: ConsoleColorPrintf isn't working in Portal 2, possible regression?
_con_colourmsgf = VFUNC(_con_iface, ConsoleColorPrintf);
dllid = AllocateDLLIdentifier(_con_iface);
diff --git a/src/engineapi.c b/src/engineapi.c
index b2272f9..0511c7d 100644
--- a/src/engineapi.c
+++ b/src/engineapi.c
@@ -40,7 +40,7 @@ struct VEngineServer *engserver;
DECL_VFUNC(void *, GetGlobalVars, 1)
void *globalvars;
-void *inputsystem;
+void *inputsystem, *vgui;
DECL_VFUNC_DYN(void *, GetAllServerClasses)
@@ -74,6 +74,7 @@ bool engineapi_init(int pluginver) {
if (pim) globalvars = GetGlobalVars(pim);
inputsystem = factory_inputsystem("InputSystemVersion001", 0);
+ vgui = factory_engine("VEngineVGui001", 0);
void *srvdll;
// TODO(compat): add this back when there's gamedata for 009 (no point atm)
diff --git a/src/engineapi.h b/src/engineapi.h
index 6394ec2..05f47ea 100644
--- a/src/engineapi.h
+++ b/src/engineapi.h
@@ -124,7 +124,7 @@ struct ServerClass {
extern struct VEngineClient *engclient;
extern struct VEngineServer *engserver;
extern void *globalvars;
-extern void *inputsystem;
+extern void *inputsystem, *vgui;
/*
* Called on plugin init to attempt to initialise various core interfaces.
diff --git a/src/fov.c b/src/fov.c
index 8319ed1..1a0874c 100644
--- a/src/fov.c
+++ b/src/fov.c
@@ -1,5 +1,6 @@
/*
* Copyright © 2022 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
* purpose with or without fee is hereby granted, provided that the above
diff --git a/src/sst.c b/src/sst.c
index d159c8e..788a81d 100644
--- a/src/sst.c
+++ b/src/sst.c
@@ -211,15 +211,17 @@ static void do_featureinit(void) {
}
}
-static void *vgui;
-typedef void (*VCALLCONV VGuiConnect_func)(void);
+typedef void (*VCALLCONV VGuiConnect_func)(void *this);
static VGuiConnect_func orig_VGuiConnect;
-static void VCALLCONV hook_VGuiConnect(void) {
- orig_VGuiConnect();
+static void VCALLCONV hook_VGuiConnect(void *this) {
+ orig_VGuiConnect(this);
do_featureinit();
- unhook_vtable(*(void ***)vgui, vtidx_VGuiConnect, (void *)orig_VGuiConnect);
+ unhook_vtable(*(void ***)vgui, vtidx_VGuiConnect,
+ (void *)orig_VGuiConnect);
}
+DECL_VFUNC_DYN(bool, VGuiIsInitialized)
+
// --- Magical deferred load order hack nonsense! ---
// The engine loads VDF plugins basically right after server.dll, but long
// before most other stuff, which makes hooking certain other stuff a pain. We
@@ -227,23 +229,22 @@ static void VCALLCONV hook_VGuiConnect(void) {
// in before config.cfg, which is needed for any kind of configuration to work
// correctly.
//
-// So here, we hook CEngineVGui::Connect() which is pretty much the last thing
-// that gets called on init, and defer feature init till afterwards. That allows
-// us to touch pretty much any engine stuff without worrying about load order
-// nonsense.
-//
-// In do_load() below, we check to see whether we're loading early by checking
-// whether gameui.dll is loaded yet; this is one of several possible arbitrary
-// checks. If it's loaded already, we assume we're getting loaded late via the
-// console and just init everything immediately.
+// So here, we hook CEngineVGui::Connect() which is one the very last things
+// to get called on startup, and use that hook to defer feature init till after
+// most of the rest of the game is up and running. That allows us to touch
+// pretty much any engine stuff without worrying about load order nonsense.
//
// Route credit to Bill for helping figure a lot of this out - mike
-static void deferinit(void) {
- vgui = factory_engine("VEngineVGui001", 0);
+static bool deferinit(void) {
if (!vgui) {
- errmsg_warnx("couldn't get VEngineVGui for deferred feature setup");
+ errmsg_warnx("can't use VEngineVGui for deferred feature setup");
goto e;
}
+ // Arbitrary check to infer whether we've been early- or late-loaded.
+ // We used to just see whether gameui.dll/libgameui.so was loaded, but
+ // Portal 2 does away with the separate gameui library, so now we just call
+ // CEngineVGui::IsInitialized() which works everywhere.
+ if (VGuiIsInitialized(vgui)) return false;
if (!os_mprot(*(void ***)vgui + vtidx_VGuiConnect, sizeof(void *),
PAGE_READWRITE)) {
errmsg_warnsys("couldn't make CEngineVGui vtable writable for deferred "
@@ -252,11 +253,11 @@ static void deferinit(void) {
}
orig_VGuiConnect = (VGuiConnect_func)hook_vtable(*(void ***)vgui,
vtidx_VGuiConnect, (void *)&hook_VGuiConnect);
- return;
+ return true;
e: con_warn("!!! SOME FEATURES MAY BE BROKEN !!!\n");
- // I think this is the lesser of two evils! Unlikely to happen anyway.
- do_featureinit();
+ // Lesser of two evils: just init features now. Unlikely to happen anyway.
+ return false;
}
static bool do_load(ifacefactory enginef, ifacefactory serverf) {
@@ -329,14 +330,7 @@ static bool do_load(ifacefactory enginef, ifacefactory serverf) {
}
}
-#ifdef _WIN32
- bool isvdf = !GetModuleHandleW(L"gameui.dll");
-#else
- void *gameuilib = dlopen("bin/libgameui.so", RTLD_NOW | RLTD_NOLOAD);
- bool isvdf = !gameuilib;
- if (gameuilib) dlclose(gameuilib);
-#endif
- if (isvdf) deferinit(); else do_featureinit();
+ if (!deferinit()) do_featureinit();
return true;
}