qbsp: make wadlist a null-terminated linked list of wads

Signed-off-by: Kevin Shanahan <kmshanah@disenchant.net>
This commit is contained in:
Kevin Shanahan 2013-03-13 12:56:57 +10:30
parent 0348f64274
commit a9e05ffd07
3 changed files with 86 additions and 108 deletions

View File

@ -290,8 +290,7 @@ ProcessFile(void)
{ {
const char *wadstring; const char *wadstring;
char *defaultwad; char *defaultwad;
wad_t *wads; wad_t *wadlist;
int numwads = 0;
// load brushes and entities // load brushes and entities
LoadMapFile(); LoadMapFile();
@ -300,15 +299,16 @@ ProcessFile(void)
return; return;
} }
wadlist = NULL;
wadstring = ValueForKey(pWorldEnt, "_wad"); wadstring = ValueForKey(pWorldEnt, "_wad");
if (!wadstring[0]) if (!wadstring[0])
wadstring = ValueForKey(pWorldEnt, "wad"); wadstring = ValueForKey(pWorldEnt, "wad");
if (!wadstring[0]) if (!wadstring[0])
Message(msgWarning, warnNoWadKey); Message(msgWarning, warnNoWadKey);
else else
numwads = WADList_Init(&wads, wadstring); wadlist = WADList_Init(wadstring);
if (!numwads) { if (!wadlist) {
if (wadstring[0]) if (wadstring[0])
Message(msgWarning, warnNoValidWads); Message(msgWarning, warnNoValidWads);
/* Try the default wad name */ /* Try the default wad name */
@ -316,8 +316,8 @@ ProcessFile(void)
strcpy(defaultwad, options.szMapName); strcpy(defaultwad, options.szMapName);
StripExtension(defaultwad); StripExtension(defaultwad);
DefaultExtension(defaultwad, ".wad"); DefaultExtension(defaultwad, ".wad");
numwads = WADList_Init(&wads, defaultwad); wadlist = WADList_Init(defaultwad);
if (numwads) if (wadlist)
Message(msgLiteral, "Using default WAD: %s\n", defaultwad); Message(msgLiteral, "Using default WAD: %s\n", defaultwad);
FreeMem(defaultwad, OTHER, strlen(options.szMapName) + 5); FreeMem(defaultwad, OTHER, strlen(options.szMapName) + 5);
} }
@ -325,16 +325,15 @@ ProcessFile(void)
// init the tables to be shared by all models // init the tables to be shared by all models
BeginBSPFile(); BeginBSPFile();
// the clipping hulls will not be written out to text files by forked processes :)
if (!options.fAllverbose) if (!options.fAllverbose)
options.fVerbose = false; options.fVerbose = false;
CreateHulls(); CreateHulls();
WriteEntitiesToString(); WriteEntitiesToString();
WADList_Process(wads, numwads); WADList_Process(wadlist);
FinishBSPFile(); FinishBSPFile();
WADList_Free(wads, numwads); WADList_Free(wadlist);
} }

View File

@ -24,9 +24,9 @@
#include "qbsp.h" #include "qbsp.h"
#include "wad.h" #include "wad.h"
static void WADList_LoadTextures(wad_t *wads, int numwads, dmiptexlump_t *l); static void WADList_LoadTextures(const wad_t *wadlist, dmiptexlump_t *lump);
static void WADList_AddAnimatingTextures(wad_t *wads, int numwads); static void WADList_AddAnimatingTextures(const wad_t *wadlist);
static int WAD_LoadLump(wad_t *w, char *name, byte *dest); static int WAD_LoadLump(const wad_t *wad, const char *name, byte *dest);
static bool static bool
@ -76,34 +76,21 @@ WAD_LoadInfo(wad_t *wad)
} }
int wad_t *
WADList_Init(wad_t **wads, const char *wadstring) WADList_Init(const char *wadstring)
{ {
int len, numwads; int len;
wad_t *wadlist, *wad; wad_t wad, *wadlist, *newwad;
const char *fname; const char *fname;
char *fpath; char *fpath;
const char *pos; const char *pos;
int pathlen; int pathlen;
*wads = NULL; if (!wadstring || !wadstring[0])
return NULL;
if (!wadstring)
return 0;
wadlist = NULL;
len = strlen(wadstring); len = strlen(wadstring);
if (len == 0)
return 0;
// Count # of wads
numwads = 1;
for (pos = wadstring; *pos ; pos++)
if (pos[0] == ';' && pos[1] != ';')
numwads++;
wadlist = AllocMem(OTHER, numwads * sizeof(wad_t), true);
wad = wadlist;
pos = wadstring; pos = wadstring;
while (pos - wadstring < len) { while (pos - wadstring < len) {
fname = pos; fname = pos;
@ -118,76 +105,68 @@ WADList_Init(wad_t **wads, const char *wadstring)
fpath = AllocMem(OTHER, pathlen + 1, true); fpath = AllocMem(OTHER, pathlen + 1, true);
snprintf(fpath, pathlen + 1, "%s/%s", options.wadPath, fname); snprintf(fpath, pathlen + 1, "%s/%s", options.wadPath, fname);
} }
wad->file = fopen(fpath, "rb"); wad.file = fopen(fpath, "rb");
if (wad->file) { if (wad.file) {
if (options.fVerbose) if (options.fVerbose)
Message(msgLiteral, "Opened WAD: %s\n", fpath); Message(msgLiteral, "Opened WAD: %s\n", fpath);
if (WAD_LoadInfo(wad)) { if (WAD_LoadInfo(&wad)) {
wad++; newwad = AllocMem(OTHER, sizeof(wad), true);
memcpy(newwad, &wad, sizeof(wad));
newwad->next = wadlist;
wadlist = newwad;
} else { } else {
Message(msgWarning, warnNotWad, fpath); Message(msgWarning, warnNotWad, fpath);
fclose(wad->file); fclose(wad.file);
} }
} }
FreeMem(fpath, OTHER, strlen(fpath) + 1); FreeMem(fpath, OTHER, strlen(fpath) + 1);
pos++; pos++;
} }
/* Re-allocate just the required amount */ return wadlist;
*wads = AllocMem(OTHER, (wad - wadlist) * sizeof(wad_t), false);
memcpy(*wads, wadlist, (wad - wadlist) * sizeof(wad_t));
FreeMem(wadlist, OTHER, numwads * sizeof(wad_t));
numwads = wad - wadlist;
return numwads;
} }
void void
WADList_Free(wad_t *wads, int numwads) WADList_Free(wad_t *wadlist)
{ {
int i; wad_t *wad, *next;
if (wads) { for (wad = wadlist; wad; wad = next) {
for (i = 0; i < numwads; i++) { next = wad->next;
fclose(wads[i].file); fclose(wad->file);
FreeMem(wads[i].lumps, OTHER, FreeMem(wad->lumps, OTHER, sizeof(lumpinfo_t) * wad->header.numlumps);
sizeof(lumpinfo_t) * wads[i].header.numlumps); FreeMem(wad, OTHER, sizeof(*wad));
}
FreeMem(wads, OTHER, numwads * sizeof(wad_t));
} }
} }
static lumpinfo_t * static lumpinfo_t *
WADList_FindTexture(const wad_t *wads, int numwads, const char *name) WADList_FindTexture(const wad_t *wadlist, const char *name)
{ {
int i, j; int i;
const wad_t *wad; const wad_t *wad;
for (i = 0, wad = wads; i < numwads; i++, wad++) for (wad = wadlist; wad; wad = wad->next)
for (j = 0; j < wad->header.numlumps; j++) for (i = 0; i < wad->header.numlumps; i++)
if (!strcasecmp(name, wad->lumps[j].name)) if (!strcasecmp(name, wad->lumps[i].name))
return &wad->lumps[j]; return &wad->lumps[i];
return NULL; return NULL;
} }
void void
WADList_Process(wad_t *wads, int numwads) WADList_Process(const wad_t *wadlist)
{ {
int i; int i;
lumpinfo_t *texture; lumpinfo_t *texture;
dmiptexlump_t *miptexlump; dmiptexlump_t *miptexlump;
struct lumpdata *texdata = &pWorldEnt->lumps[BSPTEX]; struct lumpdata *texdata = &pWorldEnt->lumps[BSPTEX];
if (numwads < 1) WADList_AddAnimatingTextures(wadlist);
return;
WADList_AddAnimatingTextures(wads, numwads);
// Count texture size. Slow but saves memory. // Count texture size. Slow but saves memory.
for (i = 0; i < map.nummiptex; i++) { for (i = 0; i < map.nummiptex; i++) {
texture = WADList_FindTexture(wads, numwads, map.miptex[i]); texture = WADList_FindTexture(wadlist, map.miptex[i]);
if (texture) if (texture)
texdata->count += texture->disksize; texdata->count += texture->disksize;
} }
@ -198,58 +177,57 @@ WADList_Process(wad_t *wads, int numwads)
miptexlump = (dmiptexlump_t *)texdata->data; miptexlump = (dmiptexlump_t *)texdata->data;
miptexlump->nummiptex = map.nummiptex; miptexlump->nummiptex = map.nummiptex;
WADList_LoadTextures(wads, numwads, miptexlump); WADList_LoadTextures(wadlist, miptexlump);
// Last pass, mark unfound textures as such // Last pass, mark unfound textures as such
for (i = 0; i < map.nummiptex; i++) for (i = 0; i < map.nummiptex; i++) {
if (miptexlump->dataofs[i] == 0) { if (miptexlump->dataofs[i] == 0) {
miptexlump->dataofs[i] = -1; miptexlump->dataofs[i] = -1;
Message(msgWarning, warnTextureNotFound, map.miptex[i]); Message(msgWarning, warnTextureNotFound, map.miptex[i]);
} }
} }
}
static void
WADList_LoadTextures(wad_t *wads, int numwads, dmiptexlump_t *l) static void
{ WADList_LoadTextures(const wad_t *wadlist, dmiptexlump_t *lump)
int i, j, len; {
byte *data; int i, size;
struct lumpdata *texdata = &pWorldEnt->lumps[BSPTEX]; byte *data;
const wad_t *wad;
data = (byte *)&l->dataofs[map.nummiptex]; struct lumpdata *texdata = &pWorldEnt->lumps[BSPTEX];
for (i = 0; i < numwads; i++) {
for (j = 0; j < map.nummiptex; j++) { data = (byte *)&lump->dataofs[map.nummiptex];
// Texture already found in a previous WAD
if (l->dataofs[j] != 0) for (i = 0; i < map.nummiptex; i++) {
continue; if (lump->dataofs[i])
continue;
l->dataofs[j] = data - (byte *)l; for (wad = wadlist; wad; wad = wad->next) {
len = WAD_LoadLump(wads + i, map.miptex[j], data); size = WAD_LoadLump(wad, map.miptex[i], data);
if (data + len - (byte *)texdata->data > texdata->count) if (size)
Error(errLowTextureCount); break;
}
// didn't find the texture if (data + size - (byte *)texdata->data > texdata->count)
if (!len) Error(errLowTextureCount);
l->dataofs[j] = 0; lump->dataofs[i] = data - (byte *)lump;
data += len; data += size;
}
} }
} }
static int static int
WAD_LoadLump(wad_t *w, char *name, byte *dest) WAD_LoadLump(const wad_t *wad, const char *name, byte *dest)
{ {
int i; int i;
int len; int size;
for (i = 0; i < w->header.numlumps; i++) { for (i = 0; i < wad->header.numlumps; i++) {
if (!strcasecmp(name, w->lumps[i].name)) { if (!strcasecmp(name, wad->lumps[i].name)) {
fseek(w->file, w->lumps[i].filepos, SEEK_SET); fseek(wad->file, wad->lumps[i].filepos, SEEK_SET);
len = fread(dest, 1, w->lumps[i].disksize, w->file); size = fread(dest, 1, wad->lumps[i].disksize, wad->file);
if (len != w->lumps[i].disksize) if (size != wad->lumps[i].disksize)
Error(errReadFailure); Error(errReadFailure);
return w->lumps[i].disksize; return wad->lumps[i].disksize;
} }
} }
@ -258,7 +236,7 @@ WAD_LoadLump(wad_t *w, char *name, byte *dest)
static void static void
WADList_AddAnimatingTextures(wad_t *wads, int numwads) WADList_AddAnimatingTextures(const wad_t *wadlist)
{ {
int base; int base;
int i, j; int i, j;
@ -274,7 +252,7 @@ WADList_AddAnimatingTextures(wad_t *wads, int numwads)
/* Search for all animations (0-9) and alt-animations (A-J) */ /* Search for all animations (0-9) and alt-animations (A-J) */
for (j = 0; j < 20; j++) { for (j = 0; j < 20; j++) {
name[1] = (j < 10) ? '0' + j : 'A' + j - 10; name[1] = (j < 10) ? '0' + j : 'A' + j - 10;
if (WADList_FindTexture(wads, numwads, name)) if (WADList_FindTexture(wadlist, name))
FindMiptex(name); FindMiptex(name);
} }
} }

View File

@ -47,15 +47,16 @@ typedef struct {
uint32_t offsets[MIPLEVELS]; uint32_t offsets[MIPLEVELS];
} dmiptex_t; } dmiptex_t;
typedef struct { typedef struct wad_s {
wadinfo_t header; wadinfo_t header;
int version; int version;
lumpinfo_t *lumps; lumpinfo_t *lumps;
FILE *file; FILE *file;
struct wad_s *next;
} wad_t; } wad_t;
int WADList_Init(wad_t **wads, const char *wadstring); wad_t *WADList_Init(const char *wadstring);
void WADList_Process(wad_t *wads, int numwads); void WADList_Process(const wad_t *wadlist);
void WADList_Free(wad_t *wads, int numwads); void WADList_Free(wad_t *wadlist);
#endif /* WAD_H */ #endif /* WAD_H */