summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorMichael Smith <mikesmiffy128@gmail.com>2022-04-25 04:24:52 +0100
committerMichael Smith <mikesmiffy128@gmail.com>2022-04-25 04:24:52 +0100
commit117f3ad6ae3fb6df54bc553bd1efbab080d39606 (patch)
tree4afff34653060dd8a15110a10ac4055451f0e448
parent9d1fea271bd823b6dc98feb61992bbe64b95a188 (diff)
Add engine_no_focus_sleep backport, fix codegen
Default gamedata values actually work the way they're supposed to now.
-rwxr-xr-xcompile3
-rw-r--r--compile.bat7
-rw-r--r--gamedata/inputsystem.kv8
-rw-r--r--src/autojump.c2
-rw-r--r--src/build/mkgamedata.c20
-rw-r--r--src/factory.h3
-rw-r--r--src/gamedata.h2
-rw-r--r--src/nosleep.c73
-rw-r--r--src/nosleep.h27
-rw-r--r--src/rinput.c2
-rw-r--r--src/sst.c44
11 files changed, 163 insertions, 28 deletions
diff --git a/compile b/compile
index fdeb843..76dc638 100755
--- a/compile
+++ b/compile
@@ -47,6 +47,7 @@ src="\
gameinfo.c
hook.c
kv.c
+ nosleep.c
sst.c
x86.c"
if [ "$dbg" = 1 ]; then src="$src \
@@ -59,7 +60,7 @@ $HOSTCC -O2 -fuse-ld=lld $warnings -D_FILE_OFFSET_BITS=64 -o .build/codegen \
$HOSTCC -O2 -fuse-ld=lld $warnings -D_FILE_OFFSET_BITS=64 -o .build/mkgamedata \
src/build/mkgamedata.c src/kv.c
.build/codegen `for s in $src; do echo "src/$s"; done`
-.build/mkgamedata gamedata/gamelib.kv gamedata/engine.kv
+.build/mkgamedata gamedata/engine.kv gamedata/gamelib.kv gamedata/inputsystem.kv
for s in $src; do cc "$s"; done
$CC -shared -fpic -fuse-ld=lld -O0 -w -o .build/libtier0.so src/stubs/tier0.c
$CC -shared -fpic -fuse-ld=lld -O0 -w -o .build/libvstdlib.so src/stubs/vstdlib.c
diff --git a/compile.bat b/compile.bat
index c8e2d40..1364b01 100644
--- a/compile.bat
+++ b/compile.bat
@@ -39,9 +39,9 @@ goto :eof
-o .build/codegen.exe src/build/codegen.c src/build/cmeta.c || exit /b
%HOSTCC% -municode -O2 %warnings% -D_CRT_SECURE_NO_WARNINGS -ladvapi32 ^
-o .build/mkgamedata.exe src/build/mkgamedata.c src/kv.c || exit /b
-.build\codegen.exe src/autojump.c src/con_.c src/demorec.c src/extmalloc.c src/fixes.c ^
-src/gamedata.c src/gameinfo.c src/hook.c src/kv.c src/rinput.c src/sst.c src/x86.c || exit /b
-.build\mkgamedata.exe gamedata/engine.kv gamedata/gamelib.kv || exit /b
+.build\codegen.exe src/autojump.c src/con_.c src/demorec.c src/extmalloc.c src/fixes.c src/gamedata.c ^
+src/gameinfo.c src/hook.c src/kv.c src/nosleep.c src/rinput.c src/sst.c src/x86.c || exit /b
+.build\mkgamedata.exe gamedata/engine.kv gamedata/gamelib.kv gamedata/inputsystem.kv || exit /b
llvm-rc /FO .build\dll.res src\dll.rc || exit /b
%CC% -shared -O0 -w -o .build/tier0.dll src/stubs/tier0.c
%CC% -shared -O0 -w -o .build/vstdlib.dll src/stubs/vstdlib.c
@@ -54,6 +54,7 @@ call :cc src/gamedata.c || exit /b
call :cc src/gameinfo.c || exit /b
call :cc src/hook.c || exit /b
call :cc src/kv.c || exit /b
+call :cc src/nosleep.c || exit /b
call :cc src/rinput.c || exit /b
call :cc src/sst.c || exit /b
call :cc src/x86.c || exit /b
diff --git a/gamedata/inputsystem.kv b/gamedata/inputsystem.kv
new file mode 100644
index 0000000..5e242c2
--- /dev/null
+++ b/gamedata/inputsystem.kv
@@ -0,0 +1,8 @@
+// = inputsystem library =
+
+vtidx_SleepUntilInput {
+ default 31 // TODO(compat): don't really know yet if this causes any issues
+ Portal2 34 // IAppSystem changes
+}
+
+// vi: sw=4 ts=4 noet tw=80 cc=80
diff --git a/src/autojump.c b/src/autojump.c
index 6c30df9..a8d7ee2 100644
--- a/src/autojump.c
+++ b/src/autojump.c
@@ -74,7 +74,7 @@ static bool unprot(void *gm) {
bool autojump_init(void) {
// TODO(featgen): auto-check these factories
if (!factory_client || !factory_server) {
- con_warn("autojump: missing required interfaces\n");
+ con_warn("autojump: missing required factories\n");
return false;
}
if (!gamedata_has_vtidx_CheckJumpButton || !gamedata_has_off_mv) {
diff --git a/src/build/mkgamedata.c b/src/build/mkgamedata.c
index e2e59ff..c5f6820 100644
--- a/src/build/mkgamedata.c
+++ b/src/build/mkgamedata.c
@@ -68,6 +68,7 @@ struct ent {
};
struct ent *next;
} *ents_head, **ents_tail = &ents_head;
+const char **curdefval; // dumb hacky afterthought, woopsy
struct parsestate {
const os_char *filename;
@@ -106,15 +107,20 @@ static void kv_cb(enum kv_token type, const char *p, uint len, void *ctxt) {
e->next = 0;
*ents_tail = e;
ents_tail = &e->next;
+ curdefval = &e->defval; // dumb hacky afterthought part 2
break;
case KV_NEST_END:
state->incond = false;
break;
case KV_VAL: case KV_VAL_QUOTED:
if (state->incond) {
- // dumb special case mentioned above
+ // continuation of dumb hackiness
if (!strcmp(state->lastkey, "default")) {
- (*ents_tail)->defval = state->lastkey;
+ char *s = malloc(len + 1);
+ if (!s) die("couldn't allocate default value string");
+ memcpy(s, p, len);
+ s[len] = '\0';
+ *curdefval = s;
break;
}
struct ent_cond *c = malloc(sizeof(*c));
@@ -203,7 +209,7 @@ F( "#define gamedata_has_%s true", e->name)
for (struct ent *e = ents_head; e; e = e->next) {
if (e->iscond) {
if (e->defval) {
-F( "int gamedata_%s = %s", e->name, e->defval);
+F( "int gamedata_%s = %s;", e->name, e->defval);
}
else {
F( "int gamedata_%s;", e->name);
@@ -216,7 +222,10 @@ _( "void gamedata_init(void) {")
for (struct ent *e = ents_head; e; e = e->next) {
if (e->iscond) {
for (struct ent_cond *c = e->cond; c; c = c->next) {
- if (!e->defval) {
+ if (e->defval) {
+F( " if (GAMETYPE_MATCHES(%s)) gamedata_%s = %s;", c->name, e->name, c->expr)
+ }
+ else {
// XXX: not bothering to generate `else`s. technically this
// has different semantics; we hope that the compiler can
// just do the right thing either way.
@@ -225,9 +234,6 @@ F( " gamedata_%s = %s;", e->name, c->expr)
F( " gamedata_has_%s = true;", e->name)
_( " }")
}
- else {
-F( " if (GAMETYPE_MATCHES(%s)) %s = %s;", c->name, e->name, c->expr)
- }
}
}
}
diff --git a/src/factory.h b/src/factory.h
index a72afef..18bf069 100644
--- a/src/factory.h
+++ b/src/factory.h
@@ -6,7 +6,8 @@
/* Access to game and engine factories obtained on plugin load */
typedef void *(*ifacefactory)(const char *name, int *ret);
-extern ifacefactory factory_client, factory_server, factory_engine;
+extern ifacefactory factory_client, factory_server, factory_engine,
+ factory_inputsystem;
#endif
diff --git a/src/gamedata.h b/src/gamedata.h
index e127f7c..b5e4ed7 100644
--- a/src/gamedata.h
+++ b/src/gamedata.h
@@ -17,6 +17,8 @@
#ifndef INC_GAMEDATA_H
#define INC_GAMEDATA_H
+#include <stdbool.h>
+
#ifdef _WIN32
#define NVDTOR 1
#else
diff --git a/src/nosleep.c b/src/nosleep.c
new file mode 100644
index 0000000..db206e0
--- /dev/null
+++ b/src/nosleep.c
@@ -0,0 +1,73 @@
+/*
+ * Copyright © 2022 Michael Smith <mikesmiffy128@gmail.com>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED “AS IS” AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <stdbool.h>
+
+#include "con_.h"
+#include "hook.h"
+#include "factory.h"
+#include "gamedata.h"
+#include "os.h"
+#include "vcall.h"
+
+DEF_CVAR_UNREG(engine_no_focus_sleep,
+ "Delay while tabbed out (SST reimplementation)", 50,
+ CON_ARCHIVE | CON_HIDDEN)
+
+static void **vtable;
+
+typedef void (*VCALLCONV SleepUntilInput_func)(void *this, int timeout);
+static SleepUntilInput_func orig_SleepUntilInput;
+static void VCALLCONV hook_SleepUntilInput(void *this, int timeout) {
+ orig_SleepUntilInput(this, con_getvari(engine_no_focus_sleep));
+}
+
+bool nosleep_init(void) {
+ struct con_var *v = con_findvar("engine_no_focus_sleep");
+ if (v) return false; // no need!
+ con_reg(engine_no_focus_sleep);
+ // TODO(featgen): auto-check these factories
+ if (!factory_inputsystem) {
+ con_warn("nosleep: missing required factories\n");
+ return false;
+ }
+ if (!gamedata_has_vtidx_SleepUntilInput) {
+ con_warn("nosleep: missing gamedata entries for this engine\n");
+ return false;
+ }
+ void *insys = factory_inputsystem("InputSystemVersion001", 0);
+ if (!insys) {
+ con_warn("nosleep: couldn't get intput system interface\n");
+ return false;
+ }
+ vtable = *(void ***)insys;
+ if (!os_mprot(vtable + gamedata_vtidx_SleepUntilInput,
+ sizeof(void *), PAGE_EXECUTE_READWRITE)) {
+ con_warn("nosleep: couldn't make memory writeable\n");
+ return false;
+ }
+ orig_SleepUntilInput = (SleepUntilInput_func)hook_vtable(vtable,
+ gamedata_vtidx_SleepUntilInput, (void *)&hook_SleepUntilInput);
+ engine_no_focus_sleep->base.flags &= ~CON_HIDDEN;
+ return true;
+}
+
+void nosleep_end(void) {
+ unhook_vtable(vtable, gamedata_vtidx_SleepUntilInput,
+ (void *)orig_SleepUntilInput);
+}
+
+// vi: sw=4 ts=4 noet tw=80 cc=80
diff --git a/src/nosleep.h b/src/nosleep.h
new file mode 100644
index 0000000..4d5237f
--- /dev/null
+++ b/src/nosleep.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright © 2022 Michael Smith <mikesmiffy128@gmail.com>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED “AS IS” AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef INC_NOSLEEP_H
+#define INC_NOSLEEP_H
+
+#include <stdbool.h>
+
+bool nosleep_init(void);
+void nosleep_end(void);
+
+#endif
+
+// vi: sw=4 ts=4 noet tw=80 cc=80
diff --git a/src/rinput.c b/src/rinput.c
index 867b5be..8d94b36 100644
--- a/src/rinput.c
+++ b/src/rinput.c
@@ -31,7 +31,7 @@
// loaded. If m_rawinput already exists, we do nothing; people should use the
// game's native raw input instead in that case.
-#define ERR "sst: rinput: error: "
+#define ERR "rinput: error: "
#define USAGEPAGE_MOUSE 1
#define USAGE_MOUSE 2
diff --git a/src/sst.c b/src/sst.c
index 0a31796..733e127 100644
--- a/src/sst.c
+++ b/src/sst.c
@@ -30,6 +30,7 @@
#include "gameinfo.h"
#include "gametype.h"
#include "hook.h"
+#include "nosleep.h"
#include "os.h"
#include "rinput.h"
#include "vcall.h"
@@ -72,7 +73,8 @@ static void *clientlib = 0;
// more source spaghetti wow!
static void VCALLCONV SetCommandClient(void *this, int i) { con_cmdclient = i; }
-ifacefactory factory_client = 0, factory_server = 0, factory_engine = 0;
+ifacefactory factory_client = 0, factory_server = 0, factory_engine = 0,
+ factory_inputsystem = 0;
// TODO(featgen): I wanted some nice fancy automatic feature system that
// figures out the dependencies at build time and generates all the init glue
@@ -81,6 +83,7 @@ ifacefactory factory_client = 0, factory_server = 0, factory_engine = 0;
static bool has_autojump = false;
static bool has_demorec = false;
static bool has_demorec_custom = false;
+static bool has_nosleep = false;
#ifdef _WIN32
static bool has_rinput = false;
#endif
@@ -205,9 +208,9 @@ DEF_CCMD_HERE(sst_autoload_enable, "Register SST to load on game startup", 0) {
// XXX: oh, crap, we're clobbering unicode again. welp, let's hope the
// theory that the engine is just as bad if not worse is true so that it
// doesn't matter.
- if (fprintf(f, "Plugin { file \"%" fS "\" }\n", relpath) < 0) {
+ if (fprintf(f, "Plugin { file \"%" fS "\" }\n", relpath) < 0 ||
+ fflush(f) == -1) {
con_warn("error: couldn't write to %" fS ": %s", path, strerror(errno));
- // XXX: ?????? now what
}
fclose(f);
}
@@ -230,9 +233,6 @@ DEF_CCMD_HERE(sst_autoload_disable, "Stop loading SST on game startup", 0) {
static bool do_load(ifacefactory enginef, ifacefactory serverf) {
factory_engine = enginef; factory_server = serverf;
-#ifndef __linux__
- void *clientlib = 0;
-#endif
if (!con_init(enginef, ifacever)) return false;
if (!gameinfo_init(enginef)) { con_disconnect(); return false; }
const void **p = vtable_firstdiff;
@@ -250,28 +250,43 @@ static bool do_load(ifacefactory enginef, ifacefactory serverf) {
*p = (void *)&nop_p_v; // OnEdictFreed
#ifdef _WIN32
- //if (gameinfo_serverlib) serverlib = GetModuleHandleW(gameinfo_serverlib);
- if (gameinfo_clientlib) clientlib = GetModuleHandleW(gameinfo_clientlib);
+ //serverlib = GetModuleHandleW(gameinfo_serverlib);
+ void *clientlib = GetModuleHandleW(gameinfo_clientlib);
#else
// Linux Source load order seems to be different to the point where if we
// +plugin_load or use a vdf then RTLD_NOLOAD won't actually find these, so
// we have to just dlopen them normally - and then remember to decrement the
// refcount again later in do_unload() so nothing gets leaked
- //if (gameinfo_serverlib) serverlib = dlopen(gameinfo_serverlib, 0);
- if (gameinfo_clientlib) clientlib = dlopen(gameinfo_clientlib, 0);
+ //serverlib = dlopen(gameinfo_serverlib, RTLD_NOW);
+ clientlib = dlopen(gameinfo_clientlib, RTLD_NOW);
#endif
if (!clientlib) {
con_warn("sst: warning: couldn't get the game's client library\n");
- goto nc;
}
- factory_client = (ifacefactory)os_dlsym(clientlib, "CreateInterface");
- if (!factory_client) {
+ else if (!(factory_client = (ifacefactory)os_dlsym(clientlib,
+ "CreateInterface"))) {
con_warn("sst: warning: couldn't get client's CreateInterface\n");
}
+#ifdef _WIN32
+ void *inputsystemlib = GetModuleHandleW(L"inputsystem.dll");
+#else
+ // TODO(linux): assuming the above doesn't apply to this; check if it does!
+ void *inputsystemlib = dlopen("bin/libinputsystem.so",
+ RTLD_NOW | RLTD_NOLOAD);
+ if (inputsystemlib) dlclose(inputsystemlib); // blegh
+#endif
+ if (!inputsystemlib) {
+ con_warn("sst: warning: couldn't get the input system library\n");
+ }
+ else if (!(factory_inputsystem = (ifacefactory)os_dlsym(inputsystemlib,
+ "CreateInterface"))) {
+ con_warn("sst: warning: couldn't get input system's CreateInterface\n");
+ }
-nc: gamedata_init();
+ gamedata_init();
has_autojump = autojump_init();
has_demorec = demorec_init();
+ has_nosleep = nosleep_init();
#ifdef _WIN32
has_rinput = rinput_init();
#endif
@@ -320,6 +335,7 @@ static void do_unload(void) {
if (has_autojump) autojump_end();
if (has_demorec) demorec_end();
+ if (has_nosleep) nosleep_end();
#ifdef _WIN32
if (has_rinput) rinput_end();
#endif