qbsp: fix relative paths for .wad files

Fixes #279
This commit is contained in:
Eric Wasylishen 2019-10-27 15:29:01 -06:00
parent 99cdf3e4dd
commit 79d3aa99de
6 changed files with 98 additions and 93 deletions

View File

@ -37,6 +37,8 @@
#include <stdint.h>
#include <string>
#define PATHSEPERATOR '/'
/* set these before calling CheckParm */
@ -763,15 +765,15 @@ DefaultPath(char *path, const char *basepath)
strcat(path, temp);
}
void
StripFilename(char *path)
std::string
StrippedFilename(const std::string& path)
{
int length;
length = strlen(path) - 1;
while (length > 0 && path[length] != PATHSEPERATOR)
length--;
path[length] = '\0';
const size_t lastSlash = path.rfind(PATHSEPERATOR);
if (lastSlash == std::string::npos) {
return std::string();
}
// excludes the trailing slash
return path.substr(0, lastSlash);
}
void

View File

@ -28,6 +28,7 @@
#include <time.h>
#include <stdarg.h>
#include <stdbool.h>
#include <string>
#include <common/log.hh>
#include <common/qvec.hh> // FIXME: For qmax/qmin
@ -95,7 +96,7 @@ void SaveFile(const char *filename, const void *buffer, int count);
void DefaultExtension(char *path, const char *extension);
void DefaultPath(char *path, const char *basepath);
void StripFilename(char *path);
std::string StrippedFilename(const std::string& path);
void StripExtension(char *path);
std::string StrippedExtension(const std::string& path);
int IsAbsolutePath(const char *path);

View File

@ -371,11 +371,13 @@ public:
float midsplitSurfFraction;
char szMapName[512];
char szBSPName[512];
struct
{
char *path;
struct wadpath {
std::string path;
bool external; //wads from this path are not to be embedded into the bsp, but will instead require the engine to load them from elsewhere. strongly recommended for eg halflife.wad
} wadPaths[16];
};
std::vector<wadpath> wadPathsVec;
vec_t on_epsilon;
bool fObjExport;
bool fOmitDetail;
@ -388,34 +390,47 @@ public:
bool fContentHack;
vec_t worldExtent;
~options_t() {
for (int i = 0; i < sizeof(wadPaths)/sizeof(wadPaths[0]); i++)
{
free(wadPaths[i].path);
wadPaths[i].path = nullptr;
}
}
options_t() {
memset(this, 0, sizeof(options_t));
// Initial values
this->dxLeakDist = 2;
this->dxSubdivide = 240;
this->fVerbose = true;
this->szMapName[0] = 0;
this->szBSPName[0] = 0;
/* Default to the original Quake BSP Version... */
this->BSPVersion = BSPVERSION;
this->fTranswater = true;
this->fixRotateObjTexture = true;
this->fOldaxis = true;
this->maxNodeSize = 1024;
this->midsplitSurfFraction = 0;
this->on_epsilon = 0.0001;
this->worldExtent = 65536;
}
options_t() :
fNofill(false),
fNoclip(false),
fNoskip(false),
fNodetail(false),
fOnlyents(false),
fConvertMapFormat(false),
convertMapFormat(conversion_t::quake),
fVerbose(true),
fAllverbose(false),
fSplitspecial(false),
fSplitturb(false),
fSplitsky(false),
fTranswater(true),
fTranssky(false),
fOldaxis(true),
fNoverbose(false),
fNopercent(false),
forceGoodTree(false),
fixRotateObjTexture(true),
fbspx_brushes(false),
fNoTextures(false),
hexen2(0),
BSPVersion(BSPVERSION), // Default to the original Quake BSP Version...
dxSubdivide(240),
dxLeakDist(2),
maxNodeSize(1024),
midsplitSurfFraction(0.0f),
szMapName{},
szBSPName{},
on_epsilon(0.0001),
fObjExport(false),
fOmitDetail(false),
fOmitDetailWall(false),
fOmitDetailIllusionary(false),
fOmitDetailFence(false),
fForcePRT1(false),
fTestExpand(false),
fLeakTest(false),
fContentHack(false),
worldExtent(65536.0f) {}
};
extern options_t options;

View File

@ -4,15 +4,6 @@
#include <common/cmdlib.hh>
TEST(common, StripFilename) {
char test[] = "/home/foo/bar.txt";
StripFilename(test);
ASSERT_EQ(std::string("/home/foo"), std::string(test));
}
TEST(common, StripFilenameFileOnly) {
char test[] = "bar.txt";
StripFilename(test);
ASSERT_EQ(std::string(""), std::string(test));
ASSERT_EQ("/home/foo", StrippedFilename("/home/foo/bar.txt"));
ASSERT_EQ("", StrippedFilename("bar.txt"));
}

View File

@ -863,20 +863,18 @@ ParseOptions(char *szOptions)
szTok2 = GetTok(szTok + strlen(szTok) + 1, szEnd);
if (!szTok2)
Error("Invalid argument to option %s", szTok);
int i;
for (i = 0; i < sizeof(options.wadPaths)/sizeof(options.wadPaths[0]); i++)
{
if (options.wadPaths[i].path)
continue;
options.wadPaths[i].external = !!Q_strcasecmp(szTok, "wadpath");
options.wadPaths[i].path = strdup(szTok2);
/* Remove trailing /, if any */
if (options.wadPaths[i].path[strlen(options.wadPaths[i].path) - 1] == '/')
options.wadPaths[i].path[strlen(options.wadPaths[i].path) - 1] = 0;
break;
std::string wadpath = szTok2;
/* Remove trailing /, if any */
if (wadpath.size() > 0 && wadpath[wadpath.size() - 1] == '/') {
wadpath.resize(wadpath.size() - 1);
}
if (i == sizeof(options.wadPaths)/sizeof(options.wadPaths[0]))
Error("too many -wadpath args");
options_t::wadpath wp;
wp.external = !!Q_strcasecmp(szTok, "wadpath");
wp.path = wadpath;
options.wadPathsVec.push_back(wp);
szTok = szTok2;
} else if (!Q_strcasecmp(szTok, "oldrottex")) {
options.fixRotateObjTexture = false;
@ -1016,10 +1014,16 @@ InitQBSP(int argc, const char **argv)
Message(msgFile, IntroString);
/* If no wadpath given, default to the map directory */
if (!options.wadPaths[0].path) {
options.wadPaths[0].external = false;
options.wadPaths[0].path = strdup(options.szMapName);
StripFilename(options.wadPaths[0].path);
if (options.wadPathsVec.empty()) {
options_t::wadpath wp;
wp.external = false;
wp.path = StrippedFilename(options.szMapName);
// If options.szMapName is a relative path, StrippedFilename will return the empty string.
// In that case, don't add it as a wad path.
if (!wp.path.empty()) {
options.wadPathsVec.push_back(wp);
}
}
// Remove already existing files

View File

@ -133,37 +133,29 @@ wad_t *WADList_AddWad(const char *fpath, bool external, wad_t *current_wadlist)
wad_t *
WADList_Init(const char *wadstring)
{
int len;
wad_t *wadlist;
const char *fname;
char *fpath;
const char *pos;
int pathlen;
if (!wadstring || !wadstring[0])
return NULL;
return nullptr;
wadlist = NULL;
len = strlen(wadstring);
pos = wadstring;
wad_t *wadlist = nullptr;
const int len = strlen(wadstring);
const char *pos = wadstring;
while (pos - wadstring < len) {
fname = pos;
// split string by ';' and copy the current component into fpath
const char *const fname = pos;
while (*pos && *pos != ';')
pos++;
if (!options.wadPaths[0].path || IsAbsolutePath(fname)) {
fpath = (char *)AllocMem(OTHER, (pos - fname) + 1, false);
q_snprintf(fpath, (pos - fname) + 1, "%s", fname);
wadlist = WADList_AddWad(fpath, false, wadlist);
FreeMem(fpath, OTHER, strlen(fpath) + 1);
const size_t fpathLen = pos - fname;
std::string fpath;
fpath.resize(fpathLen);
memcpy(&fpath[0], fname, fpathLen);
if (options.wadPathsVec.empty() || IsAbsolutePath(fpath.c_str())) {
wadlist = WADList_AddWad(fpath.c_str(), false, wadlist);
} else {
for (int i = 0; i < sizeof(options.wadPaths)/sizeof(options.wadPaths[0]) && options.wadPaths[i].path; i++)
{
pathlen = strlen(options.wadPaths[i].path) + 1 + (pos - fname);
fpath = (char *)AllocMem(OTHER, pathlen + 1, true);
q_snprintf(fpath, pathlen + 1, "%s/%s", options.wadPaths[i].path, fname);
wadlist = WADList_AddWad(fpath, options.wadPaths[i].external, wadlist);
FreeMem(fpath, OTHER, strlen(fpath) + 1);
for (const options_t::wadpath& wadpath : options.wadPathsVec) {
const std::string fullPath = wadpath.path + "/" + fpath;
wadlist = WADList_AddWad(fullPath.c_str(), wadpath.external, wadlist);
}
}