Fixed the filesystem support for doom wads.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@2151 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
parent
45a50b2e8e
commit
f2a3436e6c
1 changed files with 191 additions and 221 deletions
|
@ -658,6 +658,192 @@ searchpathfuncs_t packfilefuncs = {
|
|||
FSPAK_OpenVFS
|
||||
};
|
||||
|
||||
|
||||
|
||||
#ifdef DOOMWADS
|
||||
void *FSPAK_LoadDoomWadFile (vfsfile_t *packhandle, char *desc)
|
||||
{
|
||||
dwadheader_t header;
|
||||
int i;
|
||||
packfile_t *newfiles;
|
||||
int numpackfiles;
|
||||
pack_t *pack;
|
||||
dwadfile_t info;
|
||||
|
||||
int section=0;
|
||||
char sectionname[MAX_QPATH];
|
||||
char filename[52];
|
||||
char neatwadname[52];
|
||||
|
||||
if (packhandle == NULL)
|
||||
return NULL;
|
||||
|
||||
VFS_READ(packhandle, &header, sizeof(header));
|
||||
if (header.id[1] != 'W' || header.id[2] != 'A' || header.id[3] != 'D')
|
||||
return NULL; //not a doom wad
|
||||
|
||||
//doom wads come in two sorts. iwads and pwads.
|
||||
//iwads are the master wads, pwads are meant to replace parts of the master wad.
|
||||
//this is awkward, of course.
|
||||
//we ignore the i/p bit for the most part, but with maps, pwads are given a prefixed name.
|
||||
if (header.id[0] == 'I')
|
||||
*neatwadname = '\0';
|
||||
else if (header.id[0] == 'P')
|
||||
{
|
||||
COM_FileBase(desc, neatwadname, sizeof(neatwadname)-1);
|
||||
strcat(neatwadname, "#");
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
|
||||
header.dirofs = LittleLong (header.dirofs);
|
||||
header.dirlen = LittleLong (header.dirlen);
|
||||
|
||||
numpackfiles = header.dirlen;
|
||||
newfiles = (packfile_t*)Z_Malloc (numpackfiles * sizeof(packfile_t));
|
||||
VFS_SEEK(packhandle, header.dirofs);
|
||||
|
||||
//doom wads are awkward.
|
||||
//they have no directory structure, except for start/end 'files'.
|
||||
//they follow along the lines of lumps after the parent name.
|
||||
//a map is the name of that map, and then a squence of the lumps that form that map (found by next-with-that-name).
|
||||
//this is a problem for a real virtual filesystem, so we add a hack to recognise special names and expand them specially.
|
||||
for (i=0 ; i<numpackfiles ; i++)
|
||||
{
|
||||
VFS_READ (packhandle, &info, sizeof(info));
|
||||
|
||||
strcpy (filename, info.name);
|
||||
filename[8] = '\0';
|
||||
Q_strlwr(filename);
|
||||
|
||||
newfiles[i].filepos = LittleLong(info.filepos);
|
||||
newfiles[i].filelen = LittleLong(info.filelen);
|
||||
|
||||
switch(section) //be prepared to remap filenames.
|
||||
{
|
||||
newsection:
|
||||
case 0:
|
||||
if (info.filelen == 0)
|
||||
{ //marker for something...
|
||||
|
||||
if (!strcmp(filename, "s_start"))
|
||||
{
|
||||
section = 2;
|
||||
sprintf (newfiles[i].name, "sprites/%s", filename); //the model loader has a hack to recognise .dsp
|
||||
break;
|
||||
}
|
||||
if (!strcmp(filename, "p_start"))
|
||||
{
|
||||
section = 3;
|
||||
sprintf (newfiles[i].name, "patches/%s", filename); //the map loader will find these.
|
||||
break;
|
||||
}
|
||||
if (!strcmp(filename, "f_start"))
|
||||
{
|
||||
section = 4;
|
||||
sprintf (newfiles[i].name, "flats/%s", filename); //the map loader will find these
|
||||
break;
|
||||
}
|
||||
if ((filename[0] == 'e' && filename[2] == 'm') || !strncmp(filename, "map", 3))
|
||||
{ //this is the start of a beutiful new map
|
||||
section = 1;
|
||||
strcpy(sectionname, filename);
|
||||
sprintf (newfiles[i].name, "maps/%s%s.bsp", neatwadname, filename); //generate fake bsps to allow the server to find them
|
||||
newfiles[i].filepos = 0;
|
||||
newfiles[i].filelen = 4;
|
||||
break;
|
||||
}
|
||||
if (!strncmp(filename, "gl_", 3) && ((filename[4] == 'e' && filename[5] == 'm') || !strncmp(filename+3, "map", 3)))
|
||||
{ //this is the start of a beutiful new map
|
||||
section = 5;
|
||||
strcpy(sectionname, filename+3);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
sprintf (newfiles[i].name, "wad/%s", filename); //but there are many files that we don't recognise/know about. archive them off to keep the vfs moderatly clean.
|
||||
break;
|
||||
case 1: //map section
|
||||
if (strcmp(filename, "things") &&
|
||||
strcmp(filename, "linedefs") &&
|
||||
strcmp(filename, "sidedefs") &&
|
||||
strcmp(filename, "vertexes") &&
|
||||
strcmp(filename, "segs") &&
|
||||
strcmp(filename, "ssectors") &&
|
||||
strcmp(filename, "nodes") &&
|
||||
strcmp(filename, "sectors") &&
|
||||
strcmp(filename, "reject") &&
|
||||
strcmp(filename, "blockmap"))
|
||||
{
|
||||
section = 0;
|
||||
goto newsection;
|
||||
}
|
||||
sprintf (newfiles[i].name, "maps/%s%s.%s", neatwadname, sectionname, filename);
|
||||
break;
|
||||
case 5: //glbsp output section
|
||||
if (strcmp(filename, "gl_vert") &&
|
||||
strcmp(filename, "gl_segs") &&
|
||||
strcmp(filename, "gl_ssect") &&
|
||||
strcmp(filename, "gl_pvs") &&
|
||||
strcmp(filename, "gl_nodes"))
|
||||
{
|
||||
section = 0;
|
||||
goto newsection;
|
||||
}
|
||||
sprintf (newfiles[i].name, "maps/%s%s.%s", neatwadname, sectionname, filename);
|
||||
break;
|
||||
case 2: //sprite section
|
||||
if (!strcmp(filename, "s_end"))
|
||||
{
|
||||
section = 0;
|
||||
goto newsection;
|
||||
}
|
||||
sprintf (newfiles[i].name, "sprites/%s", filename);
|
||||
break;
|
||||
case 3: //patches section
|
||||
if (!strcmp(filename, "p_end"))
|
||||
{
|
||||
section = 0;
|
||||
goto newsection;
|
||||
}
|
||||
sprintf (newfiles[i].name, "patches/%s", filename);
|
||||
break;
|
||||
case 4: //flats section
|
||||
if (!strcmp(filename, "f_end"))
|
||||
{
|
||||
section = 0;
|
||||
goto newsection;
|
||||
}
|
||||
sprintf (newfiles[i].name, "flats/%s", filename);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pack = (pack_t*)Z_Malloc (sizeof (pack_t));
|
||||
strcpy (pack->descname, desc);
|
||||
pack->handle = packhandle;
|
||||
pack->numfiles = numpackfiles;
|
||||
pack->files = newfiles;
|
||||
pack->filepos = 0;
|
||||
VFS_SEEK(packhandle, pack->filepos);
|
||||
|
||||
pack->references++;
|
||||
|
||||
Con_TPrintf (TL_ADDEDPACKFILE, desc, numpackfiles);
|
||||
return pack;
|
||||
}
|
||||
searchpathfuncs_t doomwadfilefuncs = {
|
||||
FSPAK_PrintPath,
|
||||
FSPAK_ClosePath,
|
||||
FSPAK_BuildHash,
|
||||
FSPAK_FLocate,
|
||||
FSOS_ReadFile,
|
||||
FSPAK_EnumerateFiles,
|
||||
FSPAK_LoadDoomWadFile,
|
||||
NULL,
|
||||
FSPAK_OpenVFS
|
||||
};
|
||||
#endif
|
||||
//======================================================================================================
|
||||
//ZIP files (*.zip *.pk3)
|
||||
|
||||
|
@ -1163,6 +1349,11 @@ searchpath_t *COM_AddPathHandle(char *probablepath, searchpathfuncs_t *funcs, vo
|
|||
//we could easily add zip, but it's friendlier not to
|
||||
#endif
|
||||
|
||||
#ifdef DOOMWADS
|
||||
if (loadstuff & 16)
|
||||
COM_AddDataFiles(probablepath, search, "wad", &doomwadfilefuncs); //q4
|
||||
#endif
|
||||
|
||||
return search;
|
||||
}
|
||||
|
||||
|
@ -2310,228 +2501,7 @@ qboolean COM_LoadMapPackFile (char *filename, int ofs)
|
|||
*/
|
||||
}
|
||||
|
||||
#ifdef DOOMWADS
|
||||
qboolean COM_LoadWadFile (char *wadname)
|
||||
{
|
||||
dwadheader_t header;
|
||||
int i;
|
||||
packfile_t *newfiles;
|
||||
int numpackfiles;
|
||||
pack_t *pack;
|
||||
FILE *packhandle;
|
||||
dwadfile_t info;
|
||||
int fstart;
|
||||
|
||||
int section=0;
|
||||
char sectionname[MAX_QPATH];
|
||||
char filename[52];
|
||||
char neatwadname[52];
|
||||
|
||||
searchpath_t *search;
|
||||
flocation_t loc;
|
||||
|
||||
FS_FLocateFile(wadname, FSLFRT_LENGTH, &loc);
|
||||
|
||||
if (!loc.search)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!*loc.rawname)
|
||||
{
|
||||
Con_Printf("File %s is compressed\n");
|
||||
return false;
|
||||
}
|
||||
packhandle = fopen(loc.rawname, "rb");
|
||||
if (!packhandle)
|
||||
{
|
||||
Con_Printf("Couldn't open file\n");
|
||||
return false;
|
||||
}
|
||||
fseek(packhandle, loc.offset, SEEK_SET);
|
||||
|
||||
fstart = loc.offset;
|
||||
fseek(packhandle, fstart, SEEK_SET);
|
||||
|
||||
fread (&header, 1, sizeof(header), packhandle);
|
||||
if (header.id[1] != 'W'
|
||||
|| header.id[2] != 'A' || header.id[3] != 'D')
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (header.id[0] == 'I')
|
||||
*neatwadname = '\0';
|
||||
else if (header.id[0] == 'P')
|
||||
{
|
||||
COM_StripExtension(wadname, neatwadname);
|
||||
strcat(neatwadname, ":");
|
||||
}
|
||||
else
|
||||
return false;
|
||||
header.dirofs = LittleLong (header.dirofs);
|
||||
header.dirlen = LittleLong (header.dirlen);
|
||||
|
||||
numpackfiles = header.dirlen;
|
||||
|
||||
newfiles = (packfile_t*)Z_Malloc (numpackfiles * sizeof(packfile_t));
|
||||
|
||||
fseek (packhandle, header.dirofs+fstart, SEEK_SET);
|
||||
|
||||
pack = (pack_t*)Z_Malloc (sizeof (pack_t));
|
||||
#ifdef HASH_FILESYSTEM
|
||||
Hash_InitTable(&pack->hash, numpackfiles+1, Z_Malloc(Hash_BytesForBuckets(numpackfiles+1)));
|
||||
#endif
|
||||
// parse the directory
|
||||
for (i=0 ; i<numpackfiles ; i++)
|
||||
{
|
||||
fread (&info, 1, sizeof(info), packhandle);
|
||||
|
||||
strcpy (filename, info.name);
|
||||
filename[8] = '\0';
|
||||
Q_strlwr(filename);
|
||||
|
||||
newfiles[i].filepos = LittleLong(info.filepos)+fstart;
|
||||
newfiles[i].filelen = LittleLong(info.filelen);
|
||||
|
||||
switch(section) //be prepared to remap filenames.
|
||||
{
|
||||
newsection:
|
||||
case 0:
|
||||
if (info.filelen == 0)
|
||||
{ //marker for something...
|
||||
|
||||
if (!strcmp(filename, "s_start"))
|
||||
{
|
||||
section = 2;
|
||||
sprintf (newfiles[i].name, "sprites/%s", filename);
|
||||
break;
|
||||
}
|
||||
if (!strcmp(filename, "p_start"))
|
||||
{
|
||||
section = 3;
|
||||
sprintf (newfiles[i].name, "patches/%s", filename);
|
||||
break;
|
||||
}
|
||||
if (!strcmp(filename, "f_start"))
|
||||
{
|
||||
section = 4;
|
||||
sprintf (newfiles[i].name, "flats/%s", filename);
|
||||
break;
|
||||
}
|
||||
if ((filename[0] == 'e' && filename[2] == 'm') || !strncmp(filename, "map", 3))
|
||||
{ //this is the start of a beutiful new map
|
||||
section = 1;
|
||||
strcpy(sectionname, filename);
|
||||
sprintf (newfiles[i].name, "maps/%s%s.bsp", neatwadname, filename);
|
||||
newfiles[i].filepos = fstart;
|
||||
newfiles[i].filelen = 4;
|
||||
break;
|
||||
}
|
||||
if (!strncmp(filename, "gl_", 3) && ((filename[4] == 'e' && filename[5] == 'm') || !strncmp(filename+3, "map", 3)))
|
||||
{ //this is the start of a beutiful new map
|
||||
section = 5;
|
||||
strcpy(sectionname, filename+3);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
sprintf (newfiles[i].name, "wad/%s", filename);
|
||||
break;
|
||||
case 1: //map section
|
||||
if (strcmp(filename, "things") &&
|
||||
strcmp(filename, "linedefs") &&
|
||||
strcmp(filename, "sidedefs") &&
|
||||
strcmp(filename, "vertexes") &&
|
||||
strcmp(filename, "segs") &&
|
||||
strcmp(filename, "ssectors") &&
|
||||
strcmp(filename, "nodes") &&
|
||||
strcmp(filename, "sectors") &&
|
||||
strcmp(filename, "reject") &&
|
||||
strcmp(filename, "blockmap"))
|
||||
{
|
||||
section = 0;
|
||||
goto newsection;
|
||||
}
|
||||
sprintf (newfiles[i].name, "maps/%s%s.%s", neatwadname, sectionname, filename);
|
||||
break;
|
||||
case 5: //glbsp output section
|
||||
if (strcmp(filename, "gl_vert") &&
|
||||
strcmp(filename, "gl_segs") &&
|
||||
strcmp(filename, "gl_ssect") &&
|
||||
strcmp(filename, "gl_pvs") &&
|
||||
strcmp(filename, "gl_nodes"))
|
||||
{
|
||||
section = 0;
|
||||
goto newsection;
|
||||
}
|
||||
sprintf (newfiles[i].name, "maps/%s%s.%s", neatwadname, sectionname, filename);
|
||||
break;
|
||||
case 2: //sprite section
|
||||
if (!strcmp(filename, "s_end"))
|
||||
{
|
||||
section = 0;
|
||||
goto newsection;
|
||||
}
|
||||
sprintf (newfiles[i].name, "sprites/%s", filename);
|
||||
break;
|
||||
case 3: //patches section
|
||||
if (!strcmp(filename, "p_end"))
|
||||
{
|
||||
section = 0;
|
||||
goto newsection;
|
||||
}
|
||||
sprintf (newfiles[i].name, "patches/%s", filename);
|
||||
break;
|
||||
case 4: //flats section
|
||||
if (!strcmp(filename, "f_end"))
|
||||
{
|
||||
section = 0;
|
||||
goto newsection;
|
||||
}
|
||||
sprintf (newfiles[i].name, "flats/%s", filename);
|
||||
break;
|
||||
}
|
||||
#ifdef HASH_FILESYSTEM
|
||||
Hash_AddInsensative(&pack->hash, newfiles[i].name, &newfiles[i], &newfiles[i].bucket);
|
||||
#endif
|
||||
}
|
||||
|
||||
strcpy (pack->filename, loc.rawname);
|
||||
pack->handle = packhandle;
|
||||
pack->numfiles = numpackfiles;
|
||||
pack->files = newfiles;
|
||||
|
||||
Con_Printf ("Added wad file %s\n", wadname, numpackfiles);
|
||||
|
||||
COM_AddPathHandle(&packfilefuncs, pack, true, false);
|
||||
|
||||
COM_StripExtension(wadname, sectionname);
|
||||
strcat(sectionname, ".gwa");
|
||||
if (strcmp(sectionname, wadname))
|
||||
COM_LoadWadFile(sectionname);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#ifdef DOOMWADS
|
||||
static int COM_AddWad (char *descriptor)
|
||||
{
|
||||
searchpath_t *search;
|
||||
char pakfile[MAX_OSPATH];
|
||||
|
||||
sprintf (pakfile, descriptor, com_gamedir);
|
||||
|
||||
for (search = com_searchpaths; search; search = search->next)
|
||||
{
|
||||
if (!stricmp(search->filename, pakfile))
|
||||
return true; //already loaded (base paths?)
|
||||
}
|
||||
|
||||
return COM_LoadWadFile (descriptor);
|
||||
}
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
searchpathfuncs_t *funcs;
|
||||
|
|
Loading…
Reference in a new issue