diff options
| -rwxr-xr-x | compile | 1 | ||||
| -rw-r--r-- | compile.bat | 5 | ||||
| -rw-r--r-- | src/autojump.c | 2 | ||||
| -rw-r--r-- | src/demorec.c | 2 | ||||
| -rw-r--r-- | src/nosleep.c | 2 | ||||
| -rw-r--r-- | src/portalcolours.c | 147 | ||||
| -rw-r--r-- | src/portalcolours.h | 27 | ||||
| -rw-r--r-- | src/sst.c | 9 | 
8 files changed, 186 insertions, 9 deletions
| @@ -53,6 +53,7 @@ src="\  	kv.c  	l4dwarp.c  	nosleep.c +	portalcolours.c  	sst.c  	x86.c"  if [ "$dbg" = 1 ]; then src="$src \ diff --git a/compile.bat b/compile.bat index c218816..60372a1 100644 --- a/compile.bat +++ b/compile.bat @@ -42,8 +42,8 @@ goto :eof  -o .build/mkgamedata.exe src/build/mkgamedata.c src/kv.c || exit /b
  %HOSTCC% -municode -O2 %warnings% -D_CRT_SECURE_NO_WARNINGS -ladvapi32 ^
  -o .build/mkentprops.exe src/build/mkentprops.c src/kv.c || exit /b
 -.build\codegen.exe src/autojump.c src/con_.c src/demorec.c src/engineapi.c src/ent.c src/extmalloc.c src/fixes.c ^
 -src/fov.c src/gamedata.c src/gameinfo.c src/hook.c src/kv.c src/l4dwarp.c src/nosleep.c src/rinput.c src/sst.c src/x86.c || exit /b
 +.build\codegen.exe src/autojump.c src/con_.c src/demorec.c src/engineapi.c src/ent.c src/extmalloc.c src/fixes.c src/fov.c ^
 +src/gamedata.c src/gameinfo.c src/hook.c src/kv.c src/l4dwarp.c src/nosleep.c src/portalcolours.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
  .build\mkentprops.exe gamedata/entprops.kv || exit /b
  llvm-rc /FO .build\dll.res src\dll.rc || exit /b
 @@ -63,6 +63,7 @@ call :cc src/hook.c || exit /b  call :cc src/kv.c || exit /b
  call :cc src/l4dwarp.c || exit /b
  call :cc src/nosleep.c || exit /b
 +call :cc src/portalcolours.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/src/autojump.c b/src/autojump.c index 590b916..a8064da 100644 --- a/src/autojump.c +++ b/src/autojump.c @@ -62,7 +62,7 @@ static bool VCALLCONV hookcl(void *this) {  static bool unprot(void *gm) {  	void **vtable = *(void ***)gm;  	bool ret = os_mprot(vtable + vtidx_CheckJumpButton, sizeof(void *), -			PAGE_EXECUTE_READWRITE); +			PAGE_READWRITE);  	if (!ret) con_warn("autojump: couldn't make memory writable\n");  	return ret;  } diff --git a/src/demorec.c b/src/demorec.c index 448e92d..a7e0486 100644 --- a/src/demorec.c +++ b/src/demorec.c @@ -234,7 +234,7 @@ bool demorec_init(void) {  	void **vtable = *(void ***)demorecorder;  	// XXX: 16 is totally arbitrary here! figure out proper bounds later -	if (!os_mprot(vtable, 16 * sizeof(void *), PAGE_EXECUTE_READWRITE)) { +	if (!os_mprot(vtable, 16 * sizeof(void *), PAGE_READWRITE)) {  #ifdef _WIN32  		char err[128];  		OS_WINDOWS_ERROR(err); diff --git a/src/nosleep.c b/src/nosleep.c index 4ad02df..c1c5a9b 100644 --- a/src/nosleep.c +++ b/src/nosleep.c @@ -55,7 +55,7 @@ bool nosleep_init(void) {  	}  	vtable = *(void ***)insys;  	if (!os_mprot(vtable + vtidx_SleepUntilInput, sizeof(void *), -			PAGE_EXECUTE_READWRITE)) { +			PAGE_READWRITE)) {  		con_warn("nosleep: couldn't make memory writable\n");  		return false;  	} diff --git a/src/portalcolours.c b/src/portalcolours.c new file mode 100644 index 0000000..6030bb8 --- /dev/null +++ b/src/portalcolours.c @@ -0,0 +1,147 @@ +/* + * 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 <string.h> + +#include "con_.h" +#include "engineapi.h" +#include "extmalloc.h" +#include "gametype.h" +#include "hook.h" +#include "intdefs.h" +#include "mem.h" +#include "os.h" +#include "ppmagic.h" +#include "vcall.h" + +// It's like the thing Portal Tools does, but at runtime! + +DEF_CVAR(sst_portal_colour0, "Crosshair colour for gravity beam (hex)", +		"F2CAA7", CON_ARCHIVE | CON_HIDDEN) +DEF_CVAR(sst_portal_colour1, "Crosshair colour for left portal (hex)", +		"40A0FF", CON_ARCHIVE | CON_HIDDEN) +DEF_CVAR(sst_portal_colour2, "Crosshair colour for right portal (hex)", +		"FFA020", CON_ARCHIVE | CON_HIDDEN) +// XXX: bit weird that this is still con_colour. should we move it back out to +// engineapi as a general colour struct?? +static struct con_colour colours[3] = { +		{242, 202, 167, 255}, {64, 160, 255, 255}, {255, 160, 32, 255}}; + +static void hexparse(uchar out[static 4], const char *s) { +	const char *p = s; +	for (uchar *q = out; q - out < 3; ++q) { +		if (*p >= '0' && *p <= '9') { +			*q = *p++ - '0' << 4; +		} +		else if ((*p | 32) >= 'a' && (*p | 32) <= 'f') { +			*q = 10 + (*p++ | 32) - 'a' << 4; +		} +		else { +			// screw it, just fall back on white, I guess. +			// note: this also handles *p == '\0' so we don't overrun the string +			memset(out, 255, 4); // write 4 rather than 3, prolly faster? +			return; +		} +		// repetitive unrolled nonsense +		if (*p >= '0' && *p <= '9') { +			*q |= *p++ - '0'; +		} +		else if ((*p | 32) >= 'a' && (*p | 32) <= 'f') { +			*q |= 10 + (*p++ | 32) - 'a'; +		} +		else { +			memset(out, 255, 4); +			return; +		} +	} +	//out[3] = 255; // never changes! +} + +static void colourcb(struct con_var *v) { +	// this is stupid and ugly and has no friends, too bad! +	if (v == sst_portal_colour0) { +		hexparse(colours[0].bytes, con_getvarstr(v)); +	} +	else if (v == sst_portal_colour1) { +		hexparse(colours[1].bytes, con_getvarstr(v)); +	} +	else /* sst_portal_colour2 */ { +		hexparse(colours[2].bytes, con_getvarstr(v)); +	} +} + +// Original sig is the following but we wanna avoid calling convention weirdness +//typedef struct con_colour (*UTIL_Portal_Color_func)(int); +typedef void (*UTIL_Portal_Color_func)(struct con_colour *out, int portal); +static UTIL_Portal_Color_func orig_UTIL_Portal_Color; +static void hook_UTIL_Portal_Color(struct con_colour *out, int portal) { +	if (portal < 0 || portal > 2) *out = (struct con_colour){255, 255, 255, 255}; +	else *out = colours[portal]; +} + +// TODO(compat): would like to do the usual pointer-chasing business instead of +// using hardcoded offsets, but that's pretty hard here. Would probably have to +// do the entprops stuff for ClientClass, get at the portalgun factory, get a +// vtable, find ViewModelDrawn or something, chase through another 4 or 5 call +// offsets to find something that calls UTIL_Portal_Color... that or dig through +// vgui/hud entries, find the crosshair drawing... +// +// For now we do this! + +static bool find_UTIL_Portal_Color(void *base) { +	static const uchar x[] = HEXBYTES(8B, 44, 24, 08, 83, E8, 00, 74, 37, 83, +			E8, 01, B1, FF, 74, 1E, 83, E8, 01, 8B, 44, 24, 04, 88); +	// 5135 +	orig_UTIL_Portal_Color = (UTIL_Portal_Color_func)mem_offset(base, 0x1BF090); +	if (!memcmp((void *)orig_UTIL_Portal_Color, x, sizeof(x))) return true; +	// 3420 +	orig_UTIL_Portal_Color = (UTIL_Portal_Color_func)mem_offset(base, 0x1AA810); +	if (!memcmp((void *)orig_UTIL_Portal_Color, x, sizeof(x))) return true; +	return false; +} + +bool portalcolours_init(void *clientlib) { // ... should libs be globals? +	if (!GAMETYPE_MATCHES(Portal)) return false; +#ifdef _WIN32 +	if (!find_UTIL_Portal_Color(clientlib)) { +		con_warn("portalcolours: error: couldn't find UTIL_Portal_Color\n"); +		return false; +	} +	orig_UTIL_Portal_Color = (UTIL_Portal_Color_func)hook_inline( +			(void *)orig_UTIL_Portal_Color, (void *)&hook_UTIL_Portal_Color); +	if (!orig_UTIL_Portal_Color) { +		con_warn("portalcolours: error: couldn't hook UTIL_Portal_Color\n"); +		return false; +	} +	sst_portal_colour0->base.flags &= ~CON_HIDDEN; +	sst_portal_colour0->cb = &colourcb; +	sst_portal_colour1->base.flags &= ~CON_HIDDEN; +	sst_portal_colour1->cb = &colourcb; +	sst_portal_colour2->base.flags &= ~CON_HIDDEN; +	sst_portal_colour2->cb = &colourcb; +	return true; +#else +#warning TODO(linux): yet more stuff! +	return false; +#endif +} + +void portalcolours_end(void) { +	unhook_inline((void *)orig_UTIL_Portal_Color); +} + +// vi: sw=4 ts=4 noet tw=80 cc=80 diff --git a/src/portalcolours.h b/src/portalcolours.h new file mode 100644 index 0000000..2dd4bb5 --- /dev/null +++ b/src/portalcolours.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_PORTALCOLOURS_H +#define INC_PORTALCOLOURS_H + +#include <stdbool.h> + +bool portalcolours_init(void *clientlib); +void portalcolours_end(); + +#endif + +// vi: sw=4 ts=4 noet tw=80 cc=80 @@ -33,6 +33,7 @@  #include "hook.h"  #include "l4dwarp.h"  #include "nosleep.h" +#include "portalcolours.h"  #include "os.h"  #include "rinput.h"  #include "vcall.h" @@ -46,10 +47,8 @@  static int ifacever; -#ifdef __linux__  // we need to keep this reference to dlclose() it later - see below  static void *clientlib = 0; -#endif  #ifdef _WIN32  extern long __ImageBase; // this is actually the PE header struct but don't care @@ -189,7 +188,7 @@ static const void *const *const plugin_obj;  // but we want to actually release the plugin this decade so for now I'm just  // plonking some bools here and worrying about it later. :^)  static bool has_autojump = false, has_demorec = false, has_fov = false, -		has_nosleep = false; +		has_nosleep = false, has_portalcolours = false;  #ifdef _WIN32  static bool has_rinput = false;  #endif @@ -207,6 +206,7 @@ static void do_featureinit(void) {  	has_fov = fov_init(has_ent);  	if (has_ent) l4dwarp_init();  	has_nosleep = nosleep_init(); +	if (clientlib) has_portalcolours = portalcolours_init(clientlib);  #ifdef _WIN32  	has_rinput = rinput_init();  #endif @@ -286,7 +286,7 @@ static bool do_load(ifacefactory enginef, ifacefactory serverf) {  	*p   = (void *)&nop_p_v;		  // OnEdictFreed  #ifdef _WIN32 -	void *clientlib = GetModuleHandleW(gameinfo_clientlib); +	clientlib = GetModuleHandleW(gameinfo_clientlib);  #else  	// Apparently on Linux, the client library isn't actually loaded yet here,  	// so RTLD_NOLOAD won't actually find it. We have to just dlopen it @@ -385,6 +385,7 @@ static void do_unload(void) {  	if (has_demorec) demorec_end();  	if (has_fov) fov_end(); // dep on ent  	if (has_nosleep) nosleep_end(); +	if (has_portalcolours) portalcolours_end();  #ifdef _WIN32  	if (has_rinput) rinput_end();  #endif | 
