summaryrefslogtreecommitdiffhomepage
path: root/src/sst.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/sst.c')
-rw-r--r--src/sst.c81
1 files changed, 81 insertions, 0 deletions
diff --git a/src/sst.c b/src/sst.c
index 1d0d18a..e9aa972 100644
--- a/src/sst.c
+++ b/src/sst.c
@@ -17,6 +17,10 @@
#include <stdbool.h>
#include <string.h>
+#ifdef _WIN32
+#include <shlwapi.h>
+#endif
+
#include "autojump.h"
#include "con_.h"
#include "demorec.h"
@@ -31,6 +35,12 @@
#include "vcall.h"
#include "version.h"
+#ifdef _WIN32
+#define fS "S"
+#else
+#define fS "s"
+#endif
+
#define RGBA(r, g, b, a) (&(struct con_colour){(r), (g), (b), (a)})
u32 _gametype_tag = 0; // spaghetti: no point making a .c file for 1 variable
@@ -147,6 +157,77 @@ static inline void *ownhandle(void) {
}
#endif
+#define VDFBASENAME "SourceSpeedrunTools"
+
+DEF_CCMD_HERE(sst_autoload_enable, "Register SST to load on game startup", 0) {
+ // note: gamedir doesn't account for if the dll is in a base mod's
+ // directory, although it will yield a valid/working relative path anyway.
+ const os_char *searchdir = ifacever == 3 ?
+ gameinfo_gamedir : gameinfo_bindir;
+ os_char path[PATH_MAX];
+ if (!os_dlfile(ownhandle(), path, sizeof(path) / sizeof(*path))) {
+ // hopefully by this point this won't happen, but, like, never know
+ con_warn("error: failed to get path to plugin\n");
+ return;
+ }
+ os_char relpath[PATH_MAX];
+#ifdef _WIN32
+ if (!PathRelativePathToW(relpath, searchdir, FILE_ATTRIBUTE_DIRECTORY,
+ path, 0)) {
+ con_warn("error: couldn't compute a relative path for some reason\n");
+ return;
+ }
+ // arbitrary aesthetic judgement
+ for (os_char *p = relpath; *p; ++p) if (*p == L'\\') *p = L'/';
+#else
+#error TODO(linux): implement this, it's late right now and I can't be bothered
+#endif
+ int len = os_strlen(gameinfo_gamedir);
+ if (len + sizeof("/addons/" VDFBASENAME ".vdf") >
+ sizeof(path) / sizeof(*path)) {
+ con_warn("error: path to VDF is too long\n");
+ return;
+ }
+ memcpy(path, gameinfo_gamedir, len * sizeof(*gameinfo_gamedir));
+ memcpy(path + len, OS_LIT("/addons"), 8 * sizeof(os_char));
+ if (os_mkdir(path) == -1 && errno != EEXIST) {
+ con_warn("error: couldn't create %" fS ": %s\n", path, strerror(errno));
+ return;
+ }
+ memcpy(path + len + sizeof("/addons") - 1,
+ OS_LIT("/") OS_LIT(VDFBASENAME) OS_LIT(".vdf"),
+ sizeof("/" VDFBASENAME ".vdf") * sizeof(os_char));
+ FILE *f = os_fopen(path, OS_LIT("wb"));
+ if (!f) {
+ con_warn("error: couldn't open %" fS ": %s", path, strerror(errno));
+ return;
+ }
+ // 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) {
+ con_warn("error: couldn't write to %" fS ": %s", path, strerror(errno));
+ // XXX: ?????? now what
+ }
+ fclose(f);
+}
+
+DEF_CCMD_HERE(sst_autoload_disable, "Stop loading SST on game startup", 0) {
+ os_char path[PATH_MAX];
+ int len = os_strlen(gameinfo_gamedir);
+ if (len + sizeof("/addons/" VDFBASENAME ".vdf") >
+ sizeof(path) / sizeof(*path)) {
+ con_warn("error: path to VDF is too long\n");
+ return;
+ }
+ memcpy(path, gameinfo_gamedir, len * sizeof(*gameinfo_gamedir));
+ memcpy(path + len, OS_LIT("/addons/") OS_LIT(VDFBASENAME) OS_LIT(".vdf"),
+ sizeof("/addons/" VDFBASENAME ".vdf") * sizeof(os_char));
+ if (os_unlink(path) == -1 && errno != ENOENT) {
+ con_warn("warning: couldn't delete %" fS ":%s\n", path, strerror(errno));
+ }
+}
+
static bool do_load(ifacefactory enginef, ifacefactory serverf) {
factory_engine = enginef; factory_server = serverf;
#ifndef __linux__