use getopt and add wad search paths

This commit is contained in:
Bill Currie 2002-09-20 21:48:34 +00:00
parent 8fba02bf2f
commit 4d9fb73b29
11 changed files with 365 additions and 157 deletions

View file

@ -1,3 +1,3 @@
AUTOMAKE_OPTIONS= foreign
EXTRA_DIST= bsp5.h map.h
EXTRA_DIST= bsp5.h map.h options.h

View file

@ -246,26 +246,12 @@ qboolean FillOutside (node_t *node);
//=============================================================================
extern qboolean drawflag;
extern qboolean nofill;
extern qboolean notjunc;
extern qboolean noclip;
extern qboolean verbose;
extern int subdivide_size;
extern int hullnum;
extern brushset_t *brushset;
void qprintf (char *fmt, ...); // only prints if verbose
extern int valid;
extern char portfilename[1024];
extern char bspfilename[1024];
extern char pointfilename[1024];
extern qboolean worldmodel;
// misc functions

View file

@ -0,0 +1,56 @@
/*
options.h
command line options handling
Copyright (C) 2002 Bill Currie
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:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
$Id$
*/
#ifndef __options_h
#define __options_h
#include "QF/qtypes.h"
typedef struct {
int verbosity; // 0=silent
qboolean drawflag;
qboolean notjunc;
qboolean nofill;
qboolean noclip;
qboolean onlyents;
qboolean usehulls;
int hullnum;
int subdivide_size;
char *mapfile;
char *bspfile;
char *portfile;
char *pointfile;
char *hullfile;
char *wadpath;
} options_t;
extern options_t options;
int DecodeArgs (int argc, char **argv);
void usage (int status);
extern const char *this_program;
#endif//__options_h

View file

@ -17,8 +17,8 @@ bin_PROGRAMS= $(qfbsp)
EXTRA_PROGRAMS= qfbsp
qfbsp_SOURCES= \
brush.c csg4.c map.c merge.c nodraw.c outside.c portals.c qfbsp.c \
region.c solidbsp.c surfaces.c tjunc.c writebsp.c
brush.c csg4.c map.c merge.c nodraw.c options.c outside.c portals.c \
qfbsp.c region.c solidbsp.c surfaces.c tjunc.c writebsp.c
qfbsp_LDFLAGS= $(PTHREAD_FLAGS)
qfbsp_LDADD= $(QFBSP_LIBS)

View file

@ -0,0 +1,188 @@
/*
options.c
command line options handling
Copyright (C) 2002 Bill Currie
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:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
*/
static const char rcsid[] =
"$Id$";
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#ifdef HAVE_STRING_H
# include <string.h>
#endif
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#include <stdlib.h>
#include <stdio.h>
#include <getopt.h>
#include "QF/quakefs.h"
#include "options.h"
const char *this_program;
static struct option const long_options[] = {
{"quiet", no_argument, 0, 'q'},
{"verbose", no_argument, 0, 'v'},
{"help", no_argument, 0, 'h'},
{"version", no_argument, 0, 'V'},
{"draw", no_argument, 0, 'd'},
{"notjunc", no_argument, 0, 't'},
{"nofill", no_argument, 0, 'f'},
{"noclip", no_argument, 0, 'c'},
{"onlyents", no_argument, 0, 'e'},
{"usehulls", no_argument, 0, 'u'},
{"hullnum", required_argument, 0, 'H'},
{"subdivide", required_argument, 0, 's'},
{"wadpath", required_argument, 0, 'w'},
{NULL, 0, NULL, 0}
};
static const char *short_options =
"q" // quiet
"v" // verbose
"h" // help
"V" // version
"d" // draw
"t" // notjunc
"f" // nofill
"c" // noclip
"e" // onlyents
"u" // usehulls
"H:" // hullnum
"s:" // subdivide
"w:" // wadpath
;
void
usage (int status)
{
printf ("%s - QuakeForge PVS/PHS generation tool\n", this_program);
printf ("Usage: %s [options]\n", this_program);
printf (
"Options:\n"
" -q, --quiet Inhibit usual output\n"
" -v, --verbose Display more output than usual\n"
" -h, --help Display this help and exit\n"
" -V, --version Output version information and exit\n"
" -d, --draw\n"
" -t, --notjunc\n"
" -c, --noclip\n"
" -e, --onlyents\n"
" -u, --usehulls Use the existing hull files\n"
" -H, --hullnum [num]\n"
" -s, --subdivide [size]\n"
" -w, --wadpath [path] semicolon sparated set of dirs to \n"
" search for texture wads\n");
exit (status);
}
int
DecodeArgs (int argc, char **argv)
{
int c;
memset (&options, 0, sizeof (options));
options.verbosity = 1;
options.subdivide_size = 240;
while ((c = getopt_long (argc, argv, short_options, long_options, 0))
!= EOF) {
switch (c) {
case 'q': // quiet
options.verbosity -= 1;
break;
case 'v': // verbose
options.verbosity += 1;
break;
case 'h': // help
usage (0);
break;
case 'V': // version
printf ("%s version %s\n", PACKAGE, VERSION);
exit (0);
break;
case 'd': // draw
options.drawflag = true;
break;
case 't': // notjunc
options.notjunc = true;
break;
case 'f': // nofill
options.nofill = true;
break;
case 'c': // noclip
options.noclip = true;
break;
case 'e': // onlyents
options.onlyents = true;
break;
case 'u': // usehulls
options.usehulls = true;
break;
case 'H': // hullnum
options.hullnum = atoi (optarg);
break;
case 's': // subdivide
options.subdivide_size = atoi (optarg);
break;
case 'w': // wadpath
options.wadpath = optarg;
break;
default:
usage (1);
}
}
if (argv[optind] && *(argv[optind])) {
options.mapfile = malloc (strlen(argv[optind]) + 5);
strcpy (options.mapfile, argv[optind++]);
} else {
usage (1);
}
if (argv[optind] && *(argv[optind])) {
options.bspfile = strdup (argv[optind++]);
} else {
options.bspfile = malloc (strlen (options.mapfile) + 5);
COM_StripExtension (options.mapfile, options.bspfile);
strcat (options.bspfile, ".bsp");
}
options.hullfile = malloc (strlen (options.bspfile) + 5);
options.portfile = malloc (strlen (options.bspfile) + 5);
options.pointfile = malloc (strlen (options.bspfile) + 5);
if (options.wadpath) {
char *t = malloc (strlen (options.wadpath) + 2);
strcpy (t, ";");
strcat (t, options.wadpath);
options.wadpath = t;
} else {
options.wadpath = "";
}
return optind;
}

View file

@ -24,6 +24,7 @@
#include "QF/sys.h"
#include "bsp5.h"
#include "options.h"
int outleafs;
@ -67,7 +68,7 @@ MarkLeakTrail (portal_t *n2)
portal_t *n1;
vec3_t p1, p2, dir;
if (hullnum)
if (options.hullnum)
return;
n1 = prevleaknode;
@ -188,7 +189,7 @@ FillOutside (node_t *node)
qprintf ("----- FillOutside ----\n");
if (nofill) {
if (options.nofill) {
printf ("skipped\n");
return false;
}
@ -203,7 +204,7 @@ FillOutside (node_t *node)
if (!inside) {
printf ("Hullnum %i: No entities in empty space -- no filling "
"performed\n", hullnum);
"performed\n", options.hullnum);
return false;
}
@ -215,10 +216,10 @@ FillOutside (node_t *node)
prevleaknode = NULL;
if (!hullnum) {
leakfile = fopen (pointfilename, "w");
if (!options.hullnum) {
leakfile = fopen (options.pointfile, "w");
if (!leakfile)
Sys_Error ("Couldn't open %s\n", pointfilename);
Sys_Error ("Couldn't open %s\n", options.pointfile);
}
if (RecursiveFillOutside (outside_node.portals->nodes[s], false)) {
@ -227,13 +228,13 @@ FillOutside (node_t *node)
qprintf ("reached occupant at: (%4.0f,%4.0f,%4.0f)\n", v[0], v[1],
v[2]);
qprintf ("no filling performed\n");
if (!hullnum)
if (!options.hullnum)
fclose (leakfile);
qprintf ("leak file written to %s\n", pointfilename);
qprintf ("leak file written to %s\n", options.pointfile);
qprintf ("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
return false;
}
if (!hullnum)
if (!options.hullnum)
fclose (leakfile);
// now go back and fill things in

View file

@ -28,6 +28,7 @@
#include "QF/sys.h"
#include "bsp5.h"
#include "options.h"
node_t outside_node; // portals outside the world face this
@ -504,10 +505,10 @@ WritePortalfile (node_t *headnode)
NumberLeafs_r (headnode);
// write the file
printf ("writing %s\n", portfilename);
pf = fopen (portfilename, "w");
printf ("writing %s\n", options.portfile);
pf = fopen (options.portfile, "w");
if (!pf)
Sys_Error ("Error opening %s", portfilename);
Sys_Error ("Error opening %s", options.portfile);
fprintf (pf, "%s\n", PORTALFILE);
fprintf (pf, "%i\n", num_visleafs);

View file

@ -35,30 +35,16 @@
#include "QF/sys.h"
#include "bsp5.h"
#include "options.h"
options_t options;
bsp_t *bsp;
// command line flags
qboolean drawflag;
qboolean nofill;
qboolean notjunc;
qboolean noclip;
qboolean onlyents;
qboolean verbose = true;
qboolean allverbose;
qboolean usehulls;
int subdivide_size = 240;
brushset_t *brushset;
int valid;
char bspfilename[1024];
char pointfilename[1024];
char portfilename[1024];
char hullfilename[1024];
char *argv0; // changed after fork();
qboolean worldmodel;
@ -71,7 +57,7 @@ qprintf (char *fmt, ...)
{
va_list argptr;
if (!verbose)
if (!options.verbosity)
return;
va_start (argptr, fmt);
@ -525,7 +511,7 @@ ProcessEntity (int entnum)
if (entnum == 1)
qprintf ("--- Internal Entities ---\n");
sprintf (mod, "*%i", bsp->nummodels);
if (verbose)
if (options.verbosity)
PrintEntity (ent);
if (hullnum == 0)
@ -548,7 +534,8 @@ ProcessEntity (int entnum)
if (hullnum != 0) {
nodes = SolidBSP (surfs, true);
if (entnum == 0 && !nofill) { // assume non-world bmodels are simple
if (entnum == 0 && !options.nofill) {
// assume non-world bmodels are simple
PortalizeWorld (nodes);
if (FillOutside (nodes)) {
surfs = GatherNodeFaces (nodes);
@ -569,7 +556,8 @@ ProcessEntity (int entnum)
// build all the portals in the bsp tree
// some portals are solid polygons, and some are paths to other leafs
if (entnum == 0 && !nofill) { // assume non-world bmodels are simple
if (entnum == 0 && !options.nofill) {
// assume non-world bmodels are simple
PortalizeWorld (nodes);
if (FillOutside (nodes)) {
@ -619,11 +607,11 @@ UpdateEntLump (void)
}
printf ("Updating entities lump...\n");
f = Qopen (bspfilename, "rb");
f = Qopen (options.bspfile, "rb");
bsp = LoadBSPFile (f, Qfilesize (f));
Qclose (f);
WriteEntitiesToString ();
f = Qopen (bspfilename, "wb");
f = Qopen (options.bspfile, "wb");
WriteBSPFile (bsp, f);
Qclose (f);
}
@ -643,14 +631,14 @@ WriteClipHull (void)
dplane_t *p;
int i;
hullfilename[strlen (hullfilename) - 1] = '0' + hullnum;
options.hullfile[strlen (options.hullfile) - 1] = '0' + hullnum;
qprintf ("---- WriteClipHull ----\n");
qprintf ("Writing %s\n", hullfilename);
qprintf ("Writing %s\n", options.hullfile);
f = fopen (hullfilename, "w");
f = fopen (options.hullfile, "w");
if (!f)
Sys_Error ("Couldn't open %s", hullfilename);
Sys_Error ("Couldn't open %s", options.hullfile);
fprintf (f, "%i\n", bsp->nummodels);
@ -688,14 +676,14 @@ ReadClipHull (int hullnum)
int firstclipnode, junk, c1, c2, i, j, n;
vec3_t norm;
hullfilename[strlen (hullfilename) - 1] = '0' + hullnum;
options.hullfile[strlen (options.hullfile) - 1] = '0' + hullnum;
f = fopen (hullfilename, "r");
f = fopen (options.hullfile, "r");
if (!f)
Sys_Error ("Couldn't open %s", hullfilename);
Sys_Error ("Couldn't open %s", options.hullfile);
if (fscanf (f, "%i\n", &n) != 1)
Sys_Error ("Error parsing %s", hullfilename);
Sys_Error ("Error parsing %s", options.hullfile);
if (n != bsp->nummodels)
Sys_Error ("ReadClipHull: hull had %i models, base had %i", n,
@ -715,7 +703,7 @@ ReadClipHull (int hullnum)
Sys_Error ("ReadClipHull: MAX_MAP_CLIPNODES");
if (fscanf (f, "%i : %f %f %f %f : %i %i\n", &junk, &f1, &f2, &f3, &f4,
&c1, &c2) != 7)
Sys_Error ("Error parsing %s", hullfilename);
Sys_Error ("Error parsing %s", options.hullfile);
p.normal[0] = f1;
p.normal[1] = f2;
@ -743,8 +731,8 @@ CreateSingleHull (void)
// for each entity in the map file that has geometry
for (entnum = 0; entnum < num_entities; entnum++) {
ProcessEntity (entnum);
if (!allverbose)
verbose = false; // don't print rest of entities
if (options.verbosity < 2)
options.verbosity = 0; // don't print rest of entities
}
if (hullnum)
@ -760,12 +748,12 @@ CreateHulls (void)
exit (0);
}
// commanded to use the allready existing hulls 1 and 2
if (usehulls) {
if (options.usehulls) {
CreateSingleHull ();
return;
}
// commanded to ignore the hulls altogether
if (noclip) {
if (options.noclip) {
CreateSingleHull ();
return;
}
@ -778,12 +766,12 @@ CreateHulls (void)
fflush (stdout);
if (!fork ()) {
hullnum = 1;
verbose = false;
options.verbosity = 0;
drawflag = false;
sprintf (argv0, "HUL%i", hullnum);
} else if (!fork ()) {
hullnum = 2;
verbose = false;
options.verbosity = 0;
drawflag = false;
sprintf (argv0, "HUL%i", hullnum);
}
@ -818,40 +806,34 @@ CreateHulls (void)
}
void
ProcessFile (char *sourcebase, char *bspfilename1)
ProcessFile ()
{
// create filenames
strcpy (bspfilename, bspfilename1);
COM_StripExtension (bspfilename, bspfilename);
strcat (bspfilename, ".bsp");
strcpy (hullfilename, bspfilename1);
COM_StripExtension (hullfilename, hullfilename);
strcat (hullfilename, ".h0");
COM_StripExtension (options.bspfile, options.hullfile);
strcat (options.hullfile, ".h0");
strcpy (portfilename, bspfilename1);
COM_StripExtension (portfilename, portfilename);
strcat (portfilename, ".prt");
COM_StripExtension (options.bspfile, options.portfile);
strcat (options.portfile, ".prt");
strcpy (pointfilename, bspfilename1);
COM_StripExtension (pointfilename, pointfilename);
strcat (pointfilename, ".pts");
COM_StripExtension (options.bspfile, options.pointfile);
strcat (options.pointfile, ".pts");
if (!onlyents) {
remove (bspfilename);
if (!usehulls) {
hullfilename[strlen (hullfilename) - 1] = '1';
remove (hullfilename);
hullfilename[strlen (hullfilename) - 1] = '2';
remove (hullfilename);
if (!options.onlyents) {
remove (options.bspfile);
if (!options.usehulls) {
options.hullfile[strlen (options.hullfile) - 1] = '1';
remove (options.hullfile);
options.hullfile[strlen (options.hullfile) - 1] = '2';
remove (options.hullfile);
}
remove (portfilename);
remove (pointfilename);
remove (options.portfile);
remove (options.pointfile);
}
bsp = BSP_New ();
// load brushes and entities
LoadMapFile (sourcebase);
if (onlyents) {
LoadMapFile (options.mapfile);
if (options.onlyents) {
UpdateEntLump ();
return;
}
@ -874,59 +856,17 @@ main (int argc, char **argv)
char sourcename[1024];
char destname[1024];
double start, end;
int i;
// malloc_debug (15);
// check command line flags
for (i = 1; i < argc; i++) {
if (argv[i][0] != '-')
break;
else if (!strcmp (argv[i], "-draw"))
drawflag = true;
else if (!strcmp (argv[i], "-notjunc"))
notjunc = true;
else if (!strcmp (argv[i], "-nofill"))
nofill = true;
else if (!strcmp (argv[i], "-noclip"))
noclip = true;
else if (!strcmp (argv[i], "-onlyents"))
onlyents = true;
else if (!strcmp (argv[i], "-verbose"))
allverbose = true;
else if (!strcmp (argv[i], "-usehulls"))
usehulls = true; // don't fork -- use the existing files
else if (!strcmp (argv[i], "-hullnum")) {
hullnum = atoi (argv[i + 1]);
i++;
} else if (!strcmp (argv[i], "-subdivide")) {
subdivide_size = atoi (argv[i + 1]);
i++;
} else
Sys_Error ("qbsp: Unknown option '%s'", argv[i]);
}
if (i != argc - 2 && i != argc - 1)
Sys_Error
("usage: qbsp [options] sourcefile [destfile]\noptions: -nojunc -nofill -threads[124] -draw -onlyents -verbose -proj <projectpath>");
DecodeArgs (argc, argv);
// XXX SetQdirFromPath (argv[i]);
// let forked processes change name for ps status
argv0 = argv[0];
// create destination name if not specified
strcpy (sourcename, argv[i]);
COM_DefaultExtension (sourcename, ".map");
if (i != argc - 2) {
strcpy (destname, argv[i]);
COM_StripExtension (destname, destname);
strcat (destname, ".bsp");
printf ("outputfile: %s\n", destname);
} else
strcpy (destname, argv[i + 1]);
// do it!
start = Sys_DoubleTime ();
ProcessFile (sourcename, destname);

View file

@ -31,6 +31,7 @@
#include "QF/sys.h"
#include "bsp5.h"
#include "options.h"
/*
a surface has all of the faces that could be drawn on a given plane
@ -80,7 +81,7 @@ SubdivideFace (face_t *f, face_t **prevptr)
maxs = v;
}
if (maxs - mins <= subdivide_size)
if (maxs - mins <= options.subdivide_size)
break;
// split it
@ -89,7 +90,7 @@ SubdivideFace (face_t *f, face_t **prevptr)
VectorCopy (tex->vecs[axis], plane.normal);
v = VectorLength (plane.normal);
VectorNormalize (plane.normal);
plane.dist = (mins + subdivide_size - 16) / v;
plane.dist = (mins + options.subdivide_size - 16) / v;
next = f->next;
SplitFace (f, &plane, &front, &back);
if (!front || !back)

View file

@ -30,6 +30,7 @@
#include "QF/sys.h"
#include "bsp5.h"
#include "options.h"
typedef struct wvert_s {
vec_t t;
@ -437,7 +438,7 @@ tjunc (node_t *headnode)
qprintf ("---- tjunc ----\n");
if (notjunc)
if (options.notjunc)
return;
// identify all points on common edges

View file

@ -33,8 +33,10 @@
#include "QF/dstring.h"
#include "QF/qendian.h"
#include "QF/sys.h"
#include "QF/va.h"
#include "bsp5.h"
#include "options.h"
int headclipnode;
int firstface;
@ -320,15 +322,20 @@ CleanupName (char *in, char *out)
out[i] = 0;
}
void
int
TEX_InitFromWad (char *path)
{
int i;
wadlist_t *wl;
texfile = Qopen (path, "rb");
texfile = Qopen (path, "rbz");
#ifdef HAVE_ZLIB
if (!texfile)
Sys_Error ("couldn't open %s", path);
texfile = Qopen (va ("%s.gz", path), "rbz");
#endif
if (!texfile)
return -1;
printf ("wadfile: %s\n", path);
wl = calloc (1, sizeof (wadlist_t));
@ -348,6 +355,7 @@ TEX_InitFromWad (char *path)
}
wl->next = wadlist;
wadlist = wl;
return 0;
}
int
@ -415,32 +423,58 @@ void
WriteMiptex (void)
{
dstring_t *data;
char *path, *p;
char fullpath[1024];
char *wad_list, *wad, *w;
char *path_list, *path, *p;
dstring_t *fullpath;
dmiptexlump_t *l;
int i, len;
int i, len, res = -1;
path = ValueForKey (&entities[0], "_wad");
if (!path || !path[0]) {
path = ValueForKey (&entities[0], "wad");
if (!path || !path[0]) {
wad_list = ValueForKey (&entities[0], "_wad");
if (!wad_list || !wad_list[0]) {
wad_list = ValueForKey (&entities[0], "wad");
if (!wad_list || !wad_list[0]) {
printf ("WARNING: no wadfile specified\n");
bsp->texdatasize = 0;
return;
}
}
path = strdup (path);
p = strtok (path, ";"); // yeah yeah. but it works :)
while (p) {
sprintf (fullpath, "%s/%s", /* FIXME gamedir */ ".", p);
TEX_InitFromWad (fullpath);
fullpath = dstring_new ();
wad = wad_list = strdup (wad_list);
w = strchr (wad, ';');
if (w)
*w++ = 0;
while (1) {
path = path_list = strdup (options.wadpath);
p = strchr (path, ';');
if (p)
*p++ = 0;
while (1) {
dsprintf (fullpath, "%s%s%s", path, path[0] ? "/" : "", wad);
res = TEX_InitFromWad (fullpath->str);
if (!res)
break;
path = p;
if (!path || !*path)
break;
p = strchr (path, ';');
if (p)
*p++ = 0;
}
free (path_list);
if (res == -1)
Sys_Error ("couldn't open %s[.gz]", wad);
AddAnimatingTextures ();
p = strtok (0, ";");
wad = w;
if (!wad || !*wad)
break;
w = strchr (wad, ';');
if (w)
*w++ = 0;
}
free (path);
free (wad_list);
dstring_delete (fullpath);
data = dstring_new ();
data->size = sizeof (dmiptexlump_t);
@ -485,12 +519,12 @@ FinishBSPFile (void)
QFile *f;
printf ("--- FinishBSPFile ---\n");
printf ("WriteBSPFile: %s\n", bspfilename);
printf ("WriteBSPFile: %s\n", options.bspfile);
WriteMiptex ();
// XXX PrintBSPFileSizes ();
f = Qopen (bspfilename, "wb");
f = Qopen (options.bspfile, "wb");
WriteBSPFile (bsp, f);
Qclose (f);
}