From 2c0d39acd0329d3e976bd83d85fcf67388465e67 Mon Sep 17 00:00:00 2001 From: Michael Smith Date: Thu, 24 Mar 2022 04:56:31 +0000 Subject: Add auto VDF installation Breaks the Linux build because I can't file paths brain I need sleeping --- src/os-unix.h | 2 ++ src/os-win32.h | 2 ++ src/sst.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 85 insertions(+) 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 #include +#ifdef _WIN32 +#include +#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__ -- cgit v1.2.3