mirror of
https://github.com/yquake2/yquake2remaster.git
synced 2024-11-13 00:24:44 +00:00
Implement gamedata loading from binary path
even if $PWD is not the same path as the executable is in, the game will look for game data in directories next to the executable.
This commit is contained in:
parent
d2f7d27ad0
commit
544a464eea
4 changed files with 168 additions and 2 deletions
4
Makefile
4
Makefile
|
@ -574,6 +574,7 @@ GAME_OBJS_ = \
|
||||||
|
|
||||||
# Used by the client
|
# Used by the client
|
||||||
CLIENT_OBJS_ := \
|
CLIENT_OBJS_ := \
|
||||||
|
src/backends/generic/misc.o \
|
||||||
src/backends/generic/qal.o \
|
src/backends/generic/qal.o \
|
||||||
src/backends/generic/vid.o \
|
src/backends/generic/vid.o \
|
||||||
src/backends/generic/qgl.o \
|
src/backends/generic/qgl.o \
|
||||||
|
@ -698,7 +699,8 @@ SERVER_OBJS_ := \
|
||||||
src/server/sv_save.o \
|
src/server/sv_save.o \
|
||||||
src/server/sv_send.o \
|
src/server/sv_send.o \
|
||||||
src/server/sv_user.o \
|
src/server/sv_user.o \
|
||||||
src/server/sv_world.o
|
src/server/sv_world.o \
|
||||||
|
src/backends/generic/misc.o
|
||||||
|
|
||||||
ifeq ($(OSTYPE), Windows)
|
ifeq ($(OSTYPE), Windows)
|
||||||
SERVER_OBJS_ += \
|
SERVER_OBJS_ += \
|
||||||
|
|
141
src/backends/generic/misc.c
Normal file
141
src/backends/generic/misc.c
Normal file
|
@ -0,0 +1,141 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 1997-2001 Id Software, Inc.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or (at
|
||||||
|
* your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
*
|
||||||
|
* See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||||
|
* 02111-1307, USA.
|
||||||
|
*
|
||||||
|
* =======================================================================
|
||||||
|
*
|
||||||
|
* This file implements some generic funktions
|
||||||
|
*
|
||||||
|
* =======================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#if defined(__linux) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
|
||||||
|
#include <unistd.h> // readlink(), amongst others
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __FreeBSD__
|
||||||
|
#include <sys/sysctl.h> // for sysctl() to get path to executable
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <windows.h> // GetModuleFileNameA()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
#include <mach-o/dyld.h> // _NSGetExecutablePath
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef PATH_MAX
|
||||||
|
// this is mostly for windows. windows has a MAX_PATH = 260 #define, but allows
|
||||||
|
// longer paths anyway.. this might not be the maximum allowed length, but is
|
||||||
|
// hopefully good enough for realistic usecases
|
||||||
|
#define PATH_MAX 4096
|
||||||
|
#define _DG__DEFINED_PATH_MAX
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void SetExecutablePath(char* exePath)
|
||||||
|
{
|
||||||
|
// !!! this assumes that exePath can hold PATH_MAX chars !!!
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
|
||||||
|
DWORD len = GetModuleFileNameA(NULL, exePath, PATH_MAX);
|
||||||
|
if(len <= 0 || len == PATH_MAX)
|
||||||
|
{
|
||||||
|
// an error occured, clear exe path
|
||||||
|
exePath[0] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined(__linux) || defined(__NetBSD__) || defined(__OpenBSD__)
|
||||||
|
|
||||||
|
// all the platforms that have /proc/$pid/exe or similar that symlink the
|
||||||
|
// real executable - basiscally Linux and the BSDs except for FreeBSD which
|
||||||
|
// doesn't enable proc by default and has a sysctl() for this
|
||||||
|
char buf[PATH_MAX] = {0};
|
||||||
|
#ifdef __linux
|
||||||
|
snprintf(buf, sizeof(buf), "/proc/%d/exe", getpid());
|
||||||
|
#else // the BSDs
|
||||||
|
snprintf(buf, sizeof(buf), "/proc/%d/file", getpid());
|
||||||
|
#endif
|
||||||
|
// readlink() doesn't null-terminate!
|
||||||
|
int len = readlink(buf, exePath, PATH_MAX-1);
|
||||||
|
if (len <= 0)
|
||||||
|
{
|
||||||
|
// an error occured, clear exe path
|
||||||
|
exePath[0] = '\0';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
exePath[len] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined(__FreeBSD__)
|
||||||
|
|
||||||
|
// the sysctl should also work when /proc/ is not mounted (which seems to
|
||||||
|
// be common on FreeBSD), so use it..
|
||||||
|
int name[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1};
|
||||||
|
size_t len = PATH_MAX-1;
|
||||||
|
int ret = sysctl(name, sizeof(name)/sizeof(name[0]), exePath, &len, NULL, 0);
|
||||||
|
if(ret != 0)
|
||||||
|
{
|
||||||
|
// an error occured, clear exe path
|
||||||
|
exePath[0] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
|
||||||
|
uint32_t bufSize = PATH_MAX;
|
||||||
|
if(_NSGetExecutablePath(exePath, &bufSize) != 0)
|
||||||
|
{
|
||||||
|
// WTF, PATH_MAX is not enough to hold the path?
|
||||||
|
// an error occured, clear exe path
|
||||||
|
exePath[0] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: realpath() ?
|
||||||
|
// TODO: no idea what this is if the executable is in an app bundle
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#error "Unsupported Platform!" // feel free to add implementation for your platform and send me a patch
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *Sys_GetBinaryDir(void)
|
||||||
|
{
|
||||||
|
static char exeDir[PATH_MAX] = {0};
|
||||||
|
|
||||||
|
if(exeDir[0] != '\0') return exeDir;
|
||||||
|
|
||||||
|
SetExecutablePath(exeDir);
|
||||||
|
|
||||||
|
// cut off executable name
|
||||||
|
char* lastSlash = strrchr(exeDir, '/');
|
||||||
|
#ifdef _WIN32
|
||||||
|
char* lastBackSlash = strrchr(exeDir, '\\');
|
||||||
|
if(lastSlash == NULL || lastBackSlash > lastSlash) lastSlash = lastBackSlash;
|
||||||
|
#endif // _WIN32
|
||||||
|
|
||||||
|
if(lastSlash != NULL) lastSlash[1] = '\0'; // cut off after last (back)slash
|
||||||
|
|
||||||
|
return exeDir;
|
||||||
|
}
|
|
@ -1368,7 +1368,7 @@ FS_AddHomeAsGameDirectory(char *dir)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
len = snprintf(gdir, sizeof(gdir), "%s%s/", home, dir);
|
len = snprintf(gdir, sizeof(gdir), "%s%s/", home, dir);
|
||||||
FS_CreatePath(gdir);
|
FS_CreatePath(gdir);
|
||||||
|
|
||||||
if ((len > 0) && (len < sizeof(gdir)) && (gdir[len - 1] == '/'))
|
if ((len > 0) && (len < sizeof(gdir)) && (gdir[len - 1] == '/'))
|
||||||
|
@ -1400,6 +1400,26 @@ FS_AddSystemwideGameDirectory(char *dir)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void FS_AddBinaryDirAsGameDirectory(const char* dir)
|
||||||
|
{
|
||||||
|
char gdir[MAX_OSPATH];
|
||||||
|
const char *datadir = Sys_GetBinaryDir();
|
||||||
|
if(datadir[0] == '\0')
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int len = snprintf(gdir, sizeof(gdir), "%s%s/", datadir, dir);
|
||||||
|
|
||||||
|
printf("Using binary dir %s to fetch paks\n", gdir);
|
||||||
|
|
||||||
|
if ((len > 0) && (len < sizeof(gdir)) && (gdir[len - 1] == '/'))
|
||||||
|
{
|
||||||
|
gdir[len - 1] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
FS_AddGameDirectory(gdir);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Allows enumerating all of the directories in the search path.
|
* Allows enumerating all of the directories in the search path.
|
||||||
*/
|
*/
|
||||||
|
@ -1675,6 +1695,7 @@ FS_SetGamedir(char *dir)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
FS_AddGameDirectory(va("%s/%s", fs_basedir->string, dir));
|
FS_AddGameDirectory(va("%s/%s", fs_basedir->string, dir));
|
||||||
|
FS_AddBinaryDirAsGameDirectory(dir);
|
||||||
FS_AddHomeAsGameDirectory(dir);
|
FS_AddHomeAsGameDirectory(dir);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2086,6 +2107,7 @@ FS_InitFilesystem(void)
|
||||||
|
|
||||||
/* Add baseq2 to search path. */
|
/* Add baseq2 to search path. */
|
||||||
FS_AddGameDirectory(va("%s/" BASEDIRNAME, fs_basedir->string));
|
FS_AddGameDirectory(va("%s/" BASEDIRNAME, fs_basedir->string));
|
||||||
|
FS_AddBinaryDirAsGameDirectory(BASEDIRNAME);
|
||||||
FS_AddHomeAsGameDirectory(BASEDIRNAME);
|
FS_AddHomeAsGameDirectory(BASEDIRNAME);
|
||||||
|
|
||||||
/* Any set gamedirs will be freed up to here. */
|
/* Any set gamedirs will be freed up to here. */
|
||||||
|
|
|
@ -793,6 +793,7 @@ void Sys_SendKeyEvents(void);
|
||||||
void Sys_Error(char *error, ...);
|
void Sys_Error(char *error, ...);
|
||||||
void Sys_Quit(void);
|
void Sys_Quit(void);
|
||||||
char *Sys_GetHomeDir(void);
|
char *Sys_GetHomeDir(void);
|
||||||
|
const char *Sys_GetBinaryDir(void);
|
||||||
|
|
||||||
void Sys_FreeLibrary(void *handle);
|
void Sys_FreeLibrary(void *handle);
|
||||||
void *Sys_LoadLibrary(const char *path, const char *sym, void **handle);
|
void *Sys_LoadLibrary(const char *path, const char *sym, void **handle);
|
||||||
|
|
Loading…
Reference in a new issue