mirror of
https://github.com/yquake2/yquake2remaster.git
synced 2024-11-10 07:12:07 +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
|
||||
CLIENT_OBJS_ := \
|
||||
src/backends/generic/misc.o \
|
||||
src/backends/generic/qal.o \
|
||||
src/backends/generic/vid.o \
|
||||
src/backends/generic/qgl.o \
|
||||
|
@ -698,7 +699,8 @@ SERVER_OBJS_ := \
|
|||
src/server/sv_save.o \
|
||||
src/server/sv_send.o \
|
||||
src/server/sv_user.o \
|
||||
src/server/sv_world.o
|
||||
src/server/sv_world.o \
|
||||
src/backends/generic/misc.o
|
||||
|
||||
ifeq ($(OSTYPE), Windows)
|
||||
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;
|
||||
}
|
||||
|
||||
len = snprintf(gdir, sizeof(gdir), "%s%s/", home, dir);
|
||||
len = snprintf(gdir, sizeof(gdir), "%s%s/", home, dir);
|
||||
FS_CreatePath(gdir);
|
||||
|
||||
if ((len > 0) && (len < sizeof(gdir)) && (gdir[len - 1] == '/'))
|
||||
|
@ -1400,6 +1400,26 @@ FS_AddSystemwideGameDirectory(char *dir)
|
|||
}
|
||||
#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.
|
||||
*/
|
||||
|
@ -1675,6 +1695,7 @@ FS_SetGamedir(char *dir)
|
|||
#endif
|
||||
|
||||
FS_AddGameDirectory(va("%s/%s", fs_basedir->string, dir));
|
||||
FS_AddBinaryDirAsGameDirectory(dir);
|
||||
FS_AddHomeAsGameDirectory(dir);
|
||||
}
|
||||
}
|
||||
|
@ -2086,6 +2107,7 @@ FS_InitFilesystem(void)
|
|||
|
||||
/* Add baseq2 to search path. */
|
||||
FS_AddGameDirectory(va("%s/" BASEDIRNAME, fs_basedir->string));
|
||||
FS_AddBinaryDirAsGameDirectory(BASEDIRNAME);
|
||||
FS_AddHomeAsGameDirectory(BASEDIRNAME);
|
||||
|
||||
/* Any set gamedirs will be freed up to here. */
|
||||
|
|
|
@ -793,6 +793,7 @@ void Sys_SendKeyEvents(void);
|
|||
void Sys_Error(char *error, ...);
|
||||
void Sys_Quit(void);
|
||||
char *Sys_GetHomeDir(void);
|
||||
const char *Sys_GetBinaryDir(void);
|
||||
|
||||
void Sys_FreeLibrary(void *handle);
|
||||
void *Sys_LoadLibrary(const char *path, const char *sym, void **handle);
|
||||
|
|
Loading…
Reference in a new issue