partial work on wad file access cleanup in preparation of making a wad

utility
This commit is contained in:
Bill Currie 2004-01-09 23:34:32 +00:00
parent 45f542d293
commit 03a24be4de
7 changed files with 406 additions and 66 deletions

View file

@ -8,4 +8,4 @@ include_HEADERS = bspfile.h cbuf.h cdaudio.h checksum.h clip_hull.h cmd.h \
pakfile.h pcx.h png.h plugin.h pr_comp.h pr_debug.h pr_obj.h progs.h \
qargs.h qdefs.h qendian.h qfplist.h qtypes.h quakefs.h quakeio.h render.h \
riff.h screen.h sizebuf.h skin.h sound.h spritegn.h sys.h teamplay.h \
tga.h uint32.h va.h ver_check.h vid.h view.h wad.h zone.h
tga.h uint32.h va.h ver_check.h vid.h view.h wad.h wadfile.h zone.h

View file

@ -30,7 +30,7 @@
#ifndef _WAD_H
#define _WAD_H
#include "QF/qtypes.h"
#include "QF/wadfile.h"
//===============
// TYPES
@ -49,39 +49,17 @@
#define TYP_SOUND 67
#define TYP_MIPTEX 68
typedef struct qpic_s
{
typedef struct qpic_s {
int width, height;
byte data[4]; // variably sized
} qpic_t;
typedef struct
{
char identification[4]; // should be WAD2 or 2DAW
int numlumps;
int infotableofs;
} wadinfo_t;
typedef struct
{
int filepos;
int disksize;
int size; // uncompressed
char type;
char compression;
char pad1, pad2;
char name[16]; // must be null terminated
} lumpinfo_t;
extern int wad_numlumps;
extern lumpinfo_t *wad_lumps;
extern byte *wad_base;
void W_LoadWadFile (const char *filename);
void W_CleanupName (const char *in, char *out);
lumpinfo_t *W_GetLumpinfo (const char *name);
void *W_GetLumpName (const char *name);
void *W_GetLumpNum (int num);
void SwapPic (qpic_t *pic);

78
include/QF/wadfile.h Normal file
View file

@ -0,0 +1,78 @@
/*
wadfile.h
(description)
Copyright (C) 1996-1997 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:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
$Id$
*/
// wadfile.h
#ifndef __QF_wadfile_h
#define __QF_wadfile_h
#include "QF/quakeio.h"
#include "QF/qtypes.h"
typedef struct wadinfo_s {
char id[4]; // should be WAD2 or 2DAW
int numlumps;
int infotableofs;
} wadinfo_t;
typedef struct lumpinfo_s {
int filepos;
int disksize;
int size; // uncompressed
byte type;
byte compression;
byte pad1, pad2;
char name[16]; // must be null terminated
} lumpinfo_t;
typedef struct wad_s {
char *filename;
QFile *handle;
int numlumps;
int lumps_size;
lumpinfo_t *lumps;
struct hashtab_s *lump_hash;
wadinfo_t header;
int modified;
int old_numlumps;
int pad;
} wad_t;
wad_t *wad_new (const char *name);
void wad_del (wad_t *wad);
void wad_rehash (wad_t *wad);
wad_t *wad_open (const char *name);
void wad_close (wad_t *wad);
wad_t *wad_create (const char *name);
int wad_add (wad_t *wad, const char *filename, const char *lumpname,
byte type);
int wad_extract (wad_t *wad, lumpinfo_t *pf);
lumpinfo_t *wad_find_lump (wad_t *wad, const char *filename);
#endif//__QF_wadfile_h

View file

@ -31,6 +31,6 @@ libQFutil_la_SOURCES= \
fendian.c getopt.c getopt1.c hash.c idparse.c info.c link.c llist.c \
mathlib.c mdfour.c msg.c pakfile.c plugin.c qargs.c qendian.c \
qfplist.c quakefs.c quakeio.c riff.c sizebuf.c string.c sys.c \
va.c ver_check.c wad.c zone.c $(fnmatch)
va.c ver_check.c wad.c wadfile.c zone.c $(fnmatch)
EXTRA_DIST= $(asm_src) $(fnmatch_src)

View file

@ -56,7 +56,7 @@ byte *wad_base;
comparing 4 chars at a time Space padding is so names can be printed
nicely in tables. Can safely be performed in place.
*/
void
static void
W_CleanupName (const char *in, char *out)
{
int i;
@ -90,10 +90,8 @@ W_LoadWadFile (const char *filename)
header = (wadinfo_t *) wad_base;
if (header->identification[0] != 'W'
|| header->identification[1] != 'A'
|| header->identification[2] != 'D'
|| header->identification[3] != '2')
if (header->id[0] != 'W' || header->id[1] != 'A' || header->id[2] != 'D'
|| header->id[3] != '2')
Sys_Error ("Wad file %s doesn't have WAD2 id", filename);
wad_numlumps = LittleLong (header->numlumps);
@ -109,7 +107,7 @@ W_LoadWadFile (const char *filename)
}
}
lumpinfo_t *
static lumpinfo_t *
W_GetLumpinfo (const char *name)
{
int i;
@ -137,23 +135,6 @@ W_GetLumpName (const char *name)
return (void *) (wad_base + lump->filepos);
}
void *
W_GetLumpNum (int num)
{
lumpinfo_t *lump;
if (num < 0 || num > wad_numlumps)
Sys_Error ("W_GetLumpNum: bad number: %i", num);
lump = wad_lumps + num;
return (void *) (wad_base + lump->filepos);
}
/*
automatic byte swapping
*/
void
SwapPic (qpic_t *pic)
{

318
libs/util/wadfile.c Normal file
View file

@ -0,0 +1,318 @@
/*
wadfile.c
wad file support
Copyright (C) 2003 #AUTHOR#
Author: #AUTHOR#
Date: #DATE#
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$";
#include <sys/stat.h>
#include <sys/types.h>
#include <limits.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <ctype.h>
#include "QF/hash.h"
#include "QF/qendian.h"
#include "QF/wad.h"
// case insensitive hash and compare
static unsigned long
wad_get_hash (void *l, void *unused)
{
char name[16];
int i;
for (i = 0; i < 16; i++)
name[i] = tolower (((lumpinfo_t *) l)->name[i]);
return Hash_String (name);
}
static int
wad_compare (void *la, void *lb, void *unused)
{
return strcasecmp (((lumpinfo_t *) la)->name,
((lumpinfo_t *) lb)->name) == 0;
}
wad_t *
wad_new (const char *name)
{
wad_t *wad = calloc (sizeof (*wad), 1);
if (!wad)
return 0;
wad->filename = strdup (name);
if (!wad->filename) {
free (wad);
return 0;
}
wad->lump_hash = Hash_NewTable (1021, 0, 0, 0);
if (!wad->lump_hash) {
free (wad->filename);
free (wad);
return 0;
}
Hash_SetHashCompare (wad->lump_hash, wad_get_hash, wad_compare);
return wad;
}
void
wad_del (wad_t *wad)
{
if (wad->lumps)
free (wad->lumps);
if (wad->handle)
Qclose (wad->handle);
if (wad->filename)
free (wad->filename);
if (wad->lump_hash)
free (wad->lump_hash);
free (wad);
}
void
wad_rehash (wad_t *wad)
{
int i;
for (i = 0; i < wad->numlumps; i++) {
Hash_Add (wad->lump_hash, &wad->lumps[i]);
}
}
wad_t *
wad_open (const char *name)
{
wad_t *wad = wad_new (name);
int i;
if (!wad)
return 0;
wad->handle = Qopen (name, "rb");
if (!wad->handle) {
goto error;
}
if (Qread (wad->handle, &wad->header, sizeof (wad->header))
!= sizeof (wad->header)) {
fprintf (stderr, "%s: not a wad file\n", name);
errno = 0;
goto error;
}
if (strncmp (wad->header.id, "PACK", 4)) {
fprintf (stderr, "%s: not a wad file\n", name);
errno = 0;
goto error;
}
wad->header.infotableofs = LittleLong (wad->header.infotableofs);
wad->header.numlumps = LittleLong (wad->header.numlumps);
wad->numlumps = wad->header.numlumps / sizeof (lumpinfo_t);
wad->old_numlumps = wad->lumps_size = wad->numlumps;
wad->lumps = malloc (wad->lumps_size * sizeof (lumpinfo_t));
if (!wad->lumps) {
//fprintf (stderr, "out of memory\n");
goto error;
}
Qseek (wad->handle, wad->header.infotableofs, SEEK_SET);
Qread (wad->handle, wad->lumps, wad->numlumps * sizeof (wad->lumps[0]));
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]);
}
return wad;
error:
wad_del (wad);
return 0;
}
wad_t *
wad_create (const char *name)
{
wad_t *wad = wad_new (name);
if (!wad)
return 0;
wad->handle = Qopen (name, "wb");
if (!wad->handle) {
wad_del (wad);
return 0;
}
strncpy (wad->header.id, "PACK", sizeof (wad->header.id));
Qwrite (wad->handle, &wad->header, sizeof (wad->header));
return wad;
}
void
wad_close (wad_t *wad)
{
int i;
if (wad->modified) {
if (wad->numlumps > wad->old_numlumps) {
Qseek (wad->handle, 0, SEEK_END);
wad->header.infotableofs = Qtell (wad->handle);
}
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);
}
Qseek (wad->handle, wad->header.infotableofs, SEEK_SET);
Qwrite (wad->handle, wad->lumps,
wad->numlumps * sizeof (wad->lumps[0]));
wad->header.numlumps = wad->numlumps * sizeof (wad->lumps[0]);
wad->header.infotableofs = LittleLong (wad->header.infotableofs);
wad->header.numlumps = LittleLong (wad->numlumps
* sizeof (wad->lumps[0]));
Qseek (wad->handle, 0, SEEK_SET);
Qwrite (wad->handle, &wad->header, sizeof (wad->header));
Qseek (wad->handle, 0, SEEK_END);
}
wad_del (wad);
}
int
wad_add (wad_t *wad, const char *filename, const char *lumpname, byte type)
{
lumpinfo_t *pf;
QFile *file;
char buffer[16384];
int bytes;
pf = Hash_Find (wad->lump_hash, lumpname);
if (pf)
return -1;
if (wad->numlumps == wad->lumps_size) {
lumpinfo_t *f;
wad->lumps_size += 64;
f = realloc (wad->lumps, wad->lumps_size * sizeof (lumpinfo_t));
if (!f)
return -1;
wad->lumps = f;
}
file = Qopen (filename, "rb");
if (!file)
return -1;
wad->modified = 1;
pf = &wad->lumps[wad->numlumps++];
strncpy (pf->name, lumpname, sizeof (pf->name));
pf->name[sizeof (pf->name) - 1] = 0;
Qseek (wad->handle, 0, SEEK_END);
pf->filepos = Qtell (wad->handle);
pf->size = 0;
while ((bytes = Qread (file, buffer, sizeof (buffer)))) {
Qwrite (wad->handle, buffer, bytes);
pf->size += bytes;
}
Qclose (file);
if (wad->pad && pf->size & 3) {
static char buf[4];
Qwrite (wad->handle, buf, 4 - (pf->size & 3));
}
Hash_Add (wad->lump_hash, pf);
return 0;
}
static int
make_parents (const char *_path)
{
char *path;
char *d, *p, t;
path = (char *) alloca (strlen (_path) + 1);
strcpy (path, _path);
for (p = path; *p && (d = strchr (p, '/')); p = d + 1) {
t = *d;
*d = 0;
#ifdef WIN32
if (mkdir (path) < 0)
#else
if (mkdir (path, 0777) < 0)
#endif
if (errno != EEXIST)
return -1;
*d = t;
}
return 0;
}
int
wad_extract (wad_t *wad, lumpinfo_t *pf)
{
const char *name = pf->name;
size_t count;
int len;
QFile *file;
char buffer[16384];
if (make_parents (name) == -1)
return -1;
if (!(file = Qopen (name, "wb")))
return -1;
Qseek (wad->handle, pf->filepos, SEEK_SET);
len = pf->size;
while (len) {
count = len;
if (count > sizeof (buffer))
count = sizeof (buffer);
count = Qread (wad->handle, buffer, count);
Qwrite (file, buffer, count);
len -= count;
}
Qclose (file);
return 0;
}
lumpinfo_t *
wad_find_lump (wad_t *wad, const char *filename)
{
return Hash_Find (wad->lump_hash, filename);
}

View file

@ -38,6 +38,7 @@ static __attribute__ ((unused)) const char rcsid[] =
#include "QF/qendian.h"
#include "QF/sys.h"
#include "QF/va.h"
#include "QF/wad.h"
#include "bsp5.h"
#include "options.h"
@ -276,22 +277,6 @@ BumpModel (int hullnum)
BSP_AddModel (bsp, &bm);
}
typedef struct {
char identification[4]; // should be WAD2
int numlumps;
int infotableofs;
} wadinfo_t;
typedef struct {
int filepos;
int disksize;
int size; // uncompressed
char type;
char compression;
char pad1, pad2;
char name[16]; // must be null terminated
} lumpinfo_t;
typedef struct wadlist_s {
struct wadlist_s *next;
const char *path;
@ -337,7 +322,7 @@ TEX_InitFromWad (char *path)
wl->path = strdup (path);
Qread (texfile, &wl->wadinfo, sizeof (wadinfo_t));
if (strncmp (wl->wadinfo.identification, "WAD2", 4))
if (strncmp (wl->wadinfo.id, "WAD2", 4))
Sys_Error ("TEX_InitFromWad: %s isn't a wadfile", path);
wl->wadinfo.numlumps = LittleLong (wl->wadinfo.numlumps);
wl->wadinfo.infotableofs = LittleLong (wl->wadinfo.infotableofs);