diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/autojump.c | 2 | ||||
| -rw-r--r-- | src/build/mkgamedata.c | 20 | ||||
| -rw-r--r-- | src/factory.h | 3 | ||||
| -rw-r--r-- | src/gamedata.h | 2 | ||||
| -rw-r--r-- | src/nosleep.c | 73 | ||||
| -rw-r--r-- | src/nosleep.h | 27 | ||||
| -rw-r--r-- | src/rinput.c | 2 | ||||
| -rw-r--r-- | src/sst.c | 44 | 
8 files changed, 149 insertions, 24 deletions
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 @@ -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  | 
