summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorMichael Smith <mikesmiffy128@gmail.com>2022-03-24 04:56:31 +0000
committerMichael Smith <mikesmiffy128@gmail.com>2022-03-24 04:56:31 +0000
commit2c0d39acd0329d3e976bd83d85fcf67388465e67 (patch)
tree25a472250a6de536da048bdef9a63884cd8cf8d1
parent00ad7cdd3d05d09a43bda972c823fdc440feabb9 (diff)
Add auto VDF installation
Breaks the Linux build because I can't file paths brain I need sleeping
-rw-r--r--src/os-unix.h2
-rw-r--r--src/os-win32.h2
-rw-r--r--src/sst.c81
3 files changed, 85 insertions, 0 deletions
diff --git a/src/os-unix.h b/src/os-unix.h
index 6522029..8b7bf27 100644
--- a/src/os-unix.h
+++ b/src/os-unix.h
@@ -34,6 +34,8 @@ typedef char os_char;
#define os_open open
#define os_access access
#define os_stat stat
+#define os_mkdir(f) mkdir(f, 0755) // use real mkdir(2) if the mode matters
+#define os_unlink unlink
#define os_getenv getenv
#define os_getcwd getcwd
diff --git a/src/os-win32.h b/src/os-win32.h
index c7c0bae..08399dd 100644
--- a/src/os-win32.h
+++ b/src/os-win32.h
@@ -40,6 +40,8 @@ typedef unsigned short os_char;
// ucrt defines __stat64 to _stat64. we want _wstat64 to be the actual function
#define _stat64(path, buf) _wstat64(path, buf)
#define os_stat _stat64
+#define os_mkdir _wmkdir
+#define os_unlink _wunlink
#define os_getenv _wgetenv
#define os_getcwd _wgetcwd
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__