mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-01-17 22:50:51 +00:00
partial work on wad file access cleanup in preparation of making a wad
utility
This commit is contained in:
parent
45f542d293
commit
03a24be4de
7 changed files with 406 additions and 66 deletions
|
@ -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
|
||||
|
|
|
@ -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
78
include/QF/wadfile.h
Normal 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
|
|
@ -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)
|
||||
|
|
|
@ -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
318
libs/util/wadfile.c
Normal 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);
|
||||
}
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue