From 44b38c5cb73c4ae3fdd73a217aea736217756019 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Sat, 10 Jan 2004 08:05:25 +0000 Subject: [PATCH] add a wad tool along the lines of pak. can't yet be used for wad creation (that's a little more complicated), but it can be used for listing and extracting the contents of a wad file. watch out for *foo :) --- configure.ac | 23 ++--- libs/util/wadfile.c | 21 ++-- tools/Makefile.am | 2 +- tools/wad/.gitignore | 9 ++ tools/wad/Makefile.am | 26 +++++ tools/wad/wad.1 | 98 ++++++++++++++++++ tools/wad/wad.c | 235 ++++++++++++++++++++++++++++++++++++++++++ tools/wad/wad.h | 55 ++++++++++ 8 files changed, 449 insertions(+), 20 deletions(-) create mode 100644 tools/wad/.gitignore create mode 100644 tools/wad/Makefile.am create mode 100644 tools/wad/wad.1 create mode 100644 tools/wad/wad.c create mode 100644 tools/wad/wad.h diff --git a/configure.ac b/configure.ac index 18716827b..24bbd5514 100644 --- a/configure.ac +++ b/configure.ac @@ -1565,7 +1565,7 @@ QF_WITH_TARGETS( QF_WITH_TARGETS( tools, [ --with-tools= compile qf tools:], - [bsp2img,carne,pak,qfbsp,qfcc,qfdefs,qflight,qfmodelgen,qfprogs,qfvis,qwaq,wav],dummy + [bsp2img,carne,pak,qfbsp,qfcc,qfdefs,qflight,qfmodelgen,qfprogs,qfvis,qwaq,wad,wav],dummy ) unset CL_TARGETS @@ -1729,17 +1729,6 @@ if test "x$ENABLE_servers_qw" = xyes; then QF_NEED(qw, [common server]) fi -unset BSP2IMG_TARGETS -unset CARNE_TARGETS -unset PAK_TARGETS -unset QFCC_TARGETS -unset QFDEFS_TARGETS -unset QFLIGHT_TARGETS -unset QFMODELGEN_TARGETS -unset QFPROGS_TARGETS -unset QFVIS_TARGETS -unset QWAQ_TARGETS -unset WAV_TARGETS unset TOOLS_TARGETS if test "x$ENABLE_tools_bsp2img" = xyes; then TOOLS_TARGETS="$TOOLS_TARGETS bsp2img" @@ -1774,6 +1763,9 @@ fi if test "x$ENABLE_tools_qwaq" = xyes; then TOOLS_TARGETS="$TOOLS_TARGETS qwaq" fi +if test "x$ENABLE_tools_wad" = xyes; then + TOOLS_TARGETS="$TOOLS_TARGETS wad" +fi if test "x$ENABLE_tools_wav" = xyes; then TOOLS_TARGETS="$TOOLS_TARGETS wav" fi @@ -1789,6 +1781,7 @@ AM_CONDITIONAL(BUILD_QFMODELGEN, test "$ENABLE_tools_qfmodelgen" = "yes") AM_CONDITIONAL(BUILD_QFPROGS, test "$ENABLE_tools_qfprogs" = "yes") AM_CONDITIONAL(BUILD_QFVIS, test "$ENABLE_tools_qfvis" = "yes") AM_CONDITIONAL(BUILD_QWAQ, test "$ENABLE_tools_qwaq" = "yes" -a "$ENABLE_tools_qfcc" = "yes") +AM_CONDITIONAL(BUILD_WAD, test "$ENABLE_tools_wad" = "yes") AM_CONDITIONAL(BUILD_WAV, test "$ENABLE_tools_wav" = "yes") AM_CONDITIONAL(BUILD_RUAMOKO, test "$ENABLE_tools_qfcc" = "yes" -a "$ENABLE_tools_pak" = "yes") @@ -2050,6 +2043,11 @@ QF_DEPS(PAK, [$(top_builddir)/libs/util/libQFutil.la], [$(WIN32_LIBS)], ) +QF_DEPS(WAD, + [], + [$(top_builddir)/libs/util/libQFutil.la], + [$(WIN32_LIBS)], +) QF_DEPS(WAV, [], [$(top_builddir)/libs/util/libQFutil.la], @@ -2160,6 +2158,7 @@ AC_OUTPUT( tools/qfvis/source/Makefile tools/qwaq/Makefile tools/qwaq/progs.src + tools/wad/Makefile tools/wav/Makefile ruamoko/Makefile diff --git a/libs/util/wadfile.c b/libs/util/wadfile.c index 84eecae47..621a487ae 100644 --- a/libs/util/wadfile.c +++ b/libs/util/wadfile.c @@ -110,7 +110,7 @@ wad_rehash (wad_t *wad) int i; for (i = 0; i < wad->numlumps; i++) { - Hash_Add (wad->lump_hash, &wad->lumps[i]); + Hash_AddElement (wad->lump_hash, &wad->lumps[i]); } } @@ -132,7 +132,7 @@ wad_open (const char *name) errno = 0; goto error; } - if (strncmp (wad->header.id, "PACK", 4)) { + if (strncmp (wad->header.id, "WAD2", 4)) { fprintf (stderr, "%s: not a wad file\n", name); errno = 0; goto error; @@ -155,7 +155,7 @@ wad_open (const char *name) for (i = 0; i < wad->numlumps; i++) { wad->lumps[i].filepos = LittleLong (wad->lumps[i].filepos); wad->lumps[i].size = LittleLong (wad->lumps[i].size); - Hash_Add (wad->lump_hash, &wad->lumps[i]); + Hash_AddElement (wad->lump_hash, &wad->lumps[i]); } return wad; error: @@ -216,11 +216,15 @@ int wad_add (wad_t *wad, const char *filename, const char *lumpname, byte type) { lumpinfo_t *pf; + lumpinfo_t dummy; QFile *file; char buffer[16384]; int bytes; - pf = Hash_Find (wad->lump_hash, lumpname); + strncpy (dummy.name, lumpname, 16); + dummy.name[15] = 0; + + pf = Hash_FindElement (wad->lump_hash, &dummy); if (pf) return -1; if (wad->numlumps == wad->lumps_size) { @@ -257,7 +261,7 @@ wad_add (wad_t *wad, const char *filename, const char *lumpname, byte type) static char buf[4]; Qwrite (wad->handle, buf, 4 - (pf->size & 3)); } - Hash_Add (wad->lump_hash, pf); + Hash_AddElement (wad->lump_hash, pf); return 0; } @@ -312,7 +316,10 @@ wad_extract (wad_t *wad, lumpinfo_t *pf) } lumpinfo_t * -wad_find_lump (wad_t *wad, const char *filename) +wad_find_lump (wad_t *wad, const char *lumpname) { - return Hash_Find (wad->lump_hash, filename); + lumpinfo_t dummy; + strncpy (dummy.name, lumpname, 16); + dummy.name[15] = 0; + return Hash_FindElement (wad->lump_hash, &dummy); } diff --git a/tools/Makefile.am b/tools/Makefile.am index 51d5de831..42a8c5859 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -1,2 +1,2 @@ -SUBDIRS=bsp2img carne pak qfbsp qfcc qfdefs qflight qfmodelgen qfprogs qfvis qwaq wav +SUBDIRS=bsp2img carne pak qfbsp qfcc qfdefs qflight qfmodelgen qfprogs qfvis qwaq wad wav bin_SCRIPTS=zpak diff --git a/tools/wad/.gitignore b/tools/wad/.gitignore new file mode 100644 index 000000000..9f9126132 --- /dev/null +++ b/tools/wad/.gitignore @@ -0,0 +1,9 @@ +*.d +*.la +*.lo +.deps +.libs +.vimrc +Makefile +Makefile.in +wad diff --git a/tools/wad/Makefile.am b/tools/wad/Makefile.am new file mode 100644 index 000000000..3b4134b48 --- /dev/null +++ b/tools/wad/Makefile.am @@ -0,0 +1,26 @@ +AUTOMAKE_OPTIONS= foreign + +WAD_LIBS=@WAD_LIBS@ +WAD_DEPS=@WAD_DEPS@ +WAD_INCS=@WAD_INCS@ + +INCLUDES= -I$(top_srcdir)/include $(WAD_INCS) + +if BUILD_WAD +wad=wad +mans=wad.1 +else +wad= +mans= +endif + +bin_PROGRAMS= $(wad) +EXTRA_PROGRAMS= wad + +man_MANS= $(mans) + +wad_SOURCES= wad.c +wad_LDADD= $(WAD_LIBS) +wad_DEPENDENCIES= $(WAD_DEPS) + +EXTRA_DIST= wad.h wad.1 diff --git a/tools/wad/wad.1 b/tools/wad/wad.1 new file mode 100644 index 000000000..23f274343 --- /dev/null +++ b/tools/wad/wad.1 @@ -0,0 +1,98 @@ +.\" hey, Emacs: -*- nroff -*- +.\" wad 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; see the file COPYING. If not, write to: +.\" +.\" Free Software Foundation, Inc. +.\" 59 Temple Place, Suite 330 +.\" Boston, MA 02111-1307, USA +.\" +.\" Some roff macros, for reference: +.\" .nh disable hyphenation +.\" .hy enable hyphenation +.\" .ad l left justify +.\" .ad b justify to both left and right margins (default) +.\" .nf disable filling +.\" .fi enable filling +.\" .br insert line break +.\" .sp insert n+1 empty lines +.\" for manpage-specific macros, see man(7) +.\" +.TH WAD 1 "9 Jan, 2004" QuakeForge "QuakeForge User's Manual" +.\" Please update the above date whenever this man page is modified. +.SH NAME +wad \- The QuakeForge Packfile Tool +.SH SYNOPSIS +.B wad +<\fBcommand\fP> [\fBoptions\fP] \fIARCHIVE\fP \fIFILE\fP... +.SH DESCRIPTION +\fBwad\fP is a utility for managing pack (*.wad) archives. The format used is +compatible with Quake and Quake II. wad archives are a convenient way to store +groups of related files. Some engines allow wad archives to be compressed +internally. +.SH COMMANDS +\fBwad\fP accepts the following arguments as a command. Only one command may be +used at a time. +.TP +.B \-c, \-\-create +Create an archive. Overwrites any contents the archive may have had. +.TP +.B \-t, \-\-test +Test an archive for valid formatting. +.TP +.B \-x, \-\-extract +Extract an archive. Overwrites any files in the current directory with the same +names as those inside the archive. +.TP +.B \-h, \-\-help +Show summary of options. +.TP +.B \-V, \-\-version +Show the version of wad. +.SH OPTIONS +\fBwad\fP takes the following arguments as options. +.TP +.B \-f, \-\-file ARCHIVE +Use ARCHIVE as the archive filename, instead of the first non-option argument. +This option is provided for compatibility with older versions of \fBwad\fP. +.TP +.B \-p, \-\-pad +Can be useful when creating an archive. File space is padded to a 4\-byte +boundary, assisting in the speed of loading files from the archive. The file +data itself is not changed. +.TP +.B \-q, \-\-quiet +Inhibit some of wad's normal output. +.TP +.B \-v, \-\-verbose +Display more output than usual. +.SH "EXIT STATUS" +\fBwad\fP returns a zero exit status when it has completed a command +successfully (without error). Otherwise, it returns a non-zero exit status. +.SH BUGS +.PP +The program does not currently handle compression or decompression. This +is planned for a future version. +.PP +The program does not currently handle extraction of individual files inside an +archive. This is planned for a future version. +.PP +The program cannot modify an archive once it has been created. +.SH AUTHORS +Bill Currie (taniwha@quakeforge.net) wrote most of the program. +.PP +Jeff Teunissen (deek@quakeforge.net) wrote the command-line interface and the +documentation. +.SH "SEE ALSO" +.BR quakeforge (1), +.BR qfcc (1) diff --git a/tools/wad/wad.c b/tools/wad/wad.c new file mode 100644 index 000000000..27c4b0cc1 --- /dev/null +++ b/tools/wad/wad.c @@ -0,0 +1,235 @@ +/* + wad.c + + wadfile tool + + Copyright (C) 1996-1997 Id Software, Inc. + Copyright (C) 2002 Bill Currie + Copyright (C) 2002 Jeff Teunissen + + 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 +*/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +static __attribute__ ((unused)) const char rcsid[] = + "$Id$"; + +#ifdef HAVE_STRING_H +# include +#endif + +#ifdef HAVE_STRINGS_H +# include +#endif + +#include +#include +#include +#include + +#include +#include + +#include "wad.h" + +const char *this_program; +options_t options; + +static const struct option long_options[] = { + {"create", no_argument, 0, 'c'}, + {"test", no_argument, 0, 't'}, + {"extract", no_argument, 0, 'x'}, + {"help", no_argument, 0, 'h'}, + {"version", no_argument, 0, 'V'}, + {"pad", no_argument, 0, 'p'}, + {"quiet", no_argument, 0, 'q'}, + {"verbose", no_argument, 0, 'v'}, + {NULL, 0, NULL, 0}, +}; + +static void +usage (int status) +{ + printf ("%s - QuakeForge Packfile tool\n", this_program); + printf ("Usage: %s [options] ARCHIVE [FILE...]\n", + this_program); + + printf ("Commands:\n" + " -c, --create Create archive\n" + " -t, --test Test archive\n" + " -x, --extract Extract archive contents\n" + " -h, --help Display this help and exit\n" + " -V, --version Output version information and exit\n\n"); + + printf ("Options:\n" + " -f, --file ARCHIVE Use ARCHIVE for archive filename\n" + " -p, --pad Pad file space to a 32-bit boundary\n" + " -q, --quiet Inhibit usual output\n" + " -v, --verbose Display more output than usual\n"); + exit (status); +} + +static int +decode_args (int argc, char **argv) +{ + int c; + + options.mode = mo_none; + options.pad = false; + options.wadfile = NULL; + options.verbosity = 0; + + while ((c = getopt_long (argc, argv, "c" // create archive + "t" // test archive + "x" // extract archive contents + "h" // show help + "V" // show version + "f:" // filename + "p" // pad + "q" // quiet + "v" // verbose + , long_options, (int *) 0)) != EOF) { + switch (c) { + case 'h': // help + usage (0); + break; + case 'V': // version + printf ("wad version %s\n", VERSION); + exit (0); + break; + case 'c': // create + options.mode = mo_create; + break; + case 't': // test + options.mode = mo_test; + break; + case 'x': // extract + options.mode = mo_extract; + break; + case 'f': // set filename + options.wadfile = strdup (optarg); + break; + case 'q': // lower verbosity + options.verbosity--; + break; + case 'p': // pad + options.pad = true; + break; + case 'v': // increase verbosity + options.verbosity++; + break; + default: + usage (1); + } + } + + if ((!options.wadfile) && argv[optind] && *(argv[optind])) + options.wadfile = strdup (argv[optind++]); + + return optind; +} + +int +main (int argc, char **argv) +{ + wad_t *wad; + int i;//, j, rehash = 0; + lumpinfo_t *pf; + + this_program = argv[0]; + + decode_args (argc, argv); + + if (!options.wadfile) { + fprintf (stderr, "%s: no archive file specified.\n", + this_program); + usage (1); + } + + switch (options.mode) { + case mo_extract: + if (!(wad = wad_open (options.wadfile))) { + fprintf (stderr, "%s: error opening %s: %s\n", this_program, + options.wadfile, + strerror (errno)); + return 1; + } + for (i = 0; i < wad->numlumps; i++) { + pf = &wad->lumps[i]; + if (optind == argc) { + if (options.verbosity > 0) + printf ("%s\n", pf->name); + wad_extract (wad, pf); + } + } + if (optind < argc) { + while (optind < argc) { + pf = wad_find_lump (wad, argv[optind]); + if (!pf) { + fprintf (stderr, "could not find %s\n", argv[optind]); + continue; + } + if (options.verbosity > 0) + printf ("%s\n", pf->name); + wad_extract (wad, pf); + optind++; + } + } + wad_close (wad); + break; + case mo_test: + if (!(wad = wad_open (options.wadfile))) { + fprintf (stderr, "%s: error opening %s: %s\n", this_program, + options.wadfile, + strerror (errno)); + return 1; + } + for (i = 0; i < wad->numlumps; i++) { + if (options.verbosity >= 1) + printf ("%6d ", wad->lumps[i].size); + if (options.verbosity >= 0) + printf ("%s\n", wad->lumps[i].name); + } + wad_close (wad); + break; + case mo_create: +/* wad = wad_create (options.wadfile); + if (!wad) { + fprintf (stderr, "%s: error creating %s: %s\n", this_program, + options.wadfile, + strerror (errno)); + return 1; + } + wad->pad = options.pad; + while (optind < argc) { + if (options.verbosity > 0) + printf ("%s\n", argv[optind]); + wad_add (wad, argv[optind++]); + } + wad_close (wad);*/ + break; + default: + fprintf (stderr, "%s: No command given.\n", + this_program); + usage (1); + } + return 0; +} diff --git a/tools/wad/wad.h b/tools/wad/wad.h new file mode 100644 index 000000000..e3e856e75 --- /dev/null +++ b/tools/wad/wad.h @@ -0,0 +1,55 @@ +/* + wad.h + + wadfile tool (definitions) + + Copyright (C) 1996-1997 Id Software, Inc. + Copyright (C) 2002 Bill Currie + Copyright (C) 2002 Jeff Teunissen + + 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 __wad_h +#define __wad_h + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +typedef enum { + mo_none, + mo_test, + mo_create, + mo_extract, +} wadmode_t; + +typedef struct { + wadmode_t mode; // see above + int verbosity; // 0=silent + qboolean compress; // for the future + qboolean pad; // pad area of files to 4-byte boundary + char *wadfile; // wad file to read/write/test +} options_t; + +#endif // __wad_h