mirror of
https://git.do.srb2.org/KartKrew/Kart-Public.git
synced 2024-11-10 07:12:03 +00:00
Merge branch 'futurepk3' into 'next'
Backport SRB2 2.2's PK3 loader code fixes See merge request KartKrew/Kart-Public!289
This commit is contained in:
commit
d9f4bd6111
4 changed files with 504 additions and 133 deletions
|
@ -204,9 +204,9 @@ void LUA_LoadLump(UINT16 wad, UINT16 lump)
|
||||||
else // If it's not a .lua file, copy the lump name in too.
|
else // If it's not a .lua file, copy the lump name in too.
|
||||||
{
|
{
|
||||||
lumpinfo_t *lump_p = &wadfiles[wad]->lumpinfo[lump];
|
lumpinfo_t *lump_p = &wadfiles[wad]->lumpinfo[lump];
|
||||||
len += 1 + strlen(lump_p->name2); // length of file name, '|', and lump name
|
len += 1 + strlen(lump_p->fullname); // length of file name, '|', and lump name
|
||||||
name = malloc(len+1);
|
name = malloc(len+1);
|
||||||
sprintf(name, "%s|%s", wadfiles[wad]->filename, lump_p->name2);
|
sprintf(name, "%s|%s", wadfiles[wad]->filename, lump_p->fullname);
|
||||||
name[len] = '\0';
|
name[len] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
32
src/r_data.c
32
src/r_data.c
|
@ -429,16 +429,26 @@ void R_LoadTextures(void)
|
||||||
// Add all the textures between TX_START and TX_END
|
// Add all the textures between TX_START and TX_END
|
||||||
if (texstart != INT16_MAX && texend != INT16_MAX)
|
if (texstart != INT16_MAX && texend != INT16_MAX)
|
||||||
{
|
{
|
||||||
numtextures += (UINT32)(texend - texstart);
|
// PK3s have subfolders, so we can't just make a simple sum
|
||||||
}
|
if (W_FileHasFolders(wadfiles[w]))
|
||||||
|
{
|
||||||
// If no textures found by this point, bomb out
|
for (j = texstart; j < texend; j++)
|
||||||
if (!numtextures && w == (numwadfiles - 1))
|
{
|
||||||
{
|
if (!W_IsLumpFolder((UINT16)w, j)) // Check if lump is a folder; if not, then count it
|
||||||
I_Error("No textures detected in any WADs!\n");
|
numtextures++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
numtextures += (UINT32)(texend - texstart);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If no textures found by this point, bomb out
|
||||||
|
if (!numtextures)
|
||||||
|
I_Error("No textures detected in any WADs!\n");
|
||||||
|
|
||||||
// Allocate memory and initialize to 0 for all the textures we are initialising.
|
// Allocate memory and initialize to 0 for all the textures we are initialising.
|
||||||
// There are actually 5 buffers allocated in one for convenience.
|
// There are actually 5 buffers allocated in one for convenience.
|
||||||
textures = Z_Calloc((numtextures * sizeof(void *)) * 5, PU_STATIC, NULL);
|
textures = Z_Calloc((numtextures * sizeof(void *)) * 5, PU_STATIC, NULL);
|
||||||
|
@ -484,8 +494,13 @@ void R_LoadTextures(void)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Work through each lump between the markers in the WAD.
|
// Work through each lump between the markers in the WAD.
|
||||||
for (j = 0; j < (texend - texstart); i++, j++)
|
for (j = 0; j < (texend - texstart); j++)
|
||||||
{
|
{
|
||||||
|
if (W_FileHasFolders(wadfiles[w]))
|
||||||
|
{
|
||||||
|
if (W_IsLumpFolder(w, texstart + j)) // Check if lump is a folder
|
||||||
|
continue; // If it is then SKIP IT
|
||||||
|
}
|
||||||
patchlump = W_CacheLumpNumPwad((UINT16)w, texstart + j, PU_CACHE);
|
patchlump = W_CacheLumpNumPwad((UINT16)w, texstart + j, PU_CACHE);
|
||||||
|
|
||||||
// Then, check the lump directly to see if it's a texture SOC,
|
// Then, check the lump directly to see if it's a texture SOC,
|
||||||
|
@ -524,6 +539,7 @@ void R_LoadTextures(void)
|
||||||
texturewidthmask[i] = k - 1;
|
texturewidthmask[i] = k - 1;
|
||||||
textureheight[i] = texture->height << FRACBITS;
|
textureheight[i] = texture->height << FRACBITS;
|
||||||
}
|
}
|
||||||
|
i++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
587
src/w_wad.c
587
src/w_wad.c
|
@ -53,6 +53,7 @@
|
||||||
#include "fastcmp.h"
|
#include "fastcmp.h"
|
||||||
|
|
||||||
#include "g_game.h" // G_LoadGameData
|
#include "g_game.h" // G_LoadGameData
|
||||||
|
#include "d_main.h"
|
||||||
#include "filesrch.h"
|
#include "filesrch.h"
|
||||||
|
|
||||||
#include "i_time.h"
|
#include "i_time.h"
|
||||||
|
@ -97,7 +98,7 @@ typedef struct
|
||||||
|
|
||||||
typedef struct lumpnum_cache_s
|
typedef struct lumpnum_cache_s
|
||||||
{
|
{
|
||||||
char lumpname[8];
|
char lumpname[32];
|
||||||
lumpnum_t lumpnum;
|
lumpnum_t lumpnum;
|
||||||
} lumpnum_cache_t;
|
} lumpnum_cache_t;
|
||||||
|
|
||||||
|
@ -119,12 +120,17 @@ void W_Shutdown(void)
|
||||||
{
|
{
|
||||||
while (numwadfiles--)
|
while (numwadfiles--)
|
||||||
{
|
{
|
||||||
fclose(wadfiles[numwadfiles]->handle);
|
wadfile_t *wad = wadfiles[numwadfiles];
|
||||||
Z_Free(wadfiles[numwadfiles]->filename);
|
|
||||||
while (wadfiles[numwadfiles]->numlumps--)
|
if (wad->handle)
|
||||||
Z_Free(wadfiles[numwadfiles]->lumpinfo[wadfiles[numwadfiles]->numlumps].name2);
|
fclose(wad->handle);
|
||||||
Z_Free(wadfiles[numwadfiles]->lumpinfo);
|
Z_Free(wad->filename);
|
||||||
Z_Free(wadfiles[numwadfiles]);
|
while (wad->numlumps--) {
|
||||||
|
Z_Free(wad->lumpinfo[wad->numlumps].longname);
|
||||||
|
Z_Free(wad->lumpinfo[wad->numlumps].fullname);
|
||||||
|
}
|
||||||
|
Z_Free(wad->lumpinfo);
|
||||||
|
Z_Free(wad);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -195,7 +201,6 @@ static inline void W_LoadDehackedLumpsPK3(UINT16 wadnum)
|
||||||
if (posStart != INT16_MAX)
|
if (posStart != INT16_MAX)
|
||||||
{
|
{
|
||||||
posEnd = W_CheckNumForFolderEndPK3("Lua/", wadnum, posStart);
|
posEnd = W_CheckNumForFolderEndPK3("Lua/", wadnum, posStart);
|
||||||
posStart++;
|
|
||||||
for (; posStart < posEnd; posStart++)
|
for (; posStart < posEnd; posStart++)
|
||||||
LUA_LoadLump(wadnum, posStart);
|
LUA_LoadLump(wadnum, posStart);
|
||||||
}
|
}
|
||||||
|
@ -205,13 +210,12 @@ static inline void W_LoadDehackedLumpsPK3(UINT16 wadnum)
|
||||||
if (posStart != INT16_MAX)
|
if (posStart != INT16_MAX)
|
||||||
{
|
{
|
||||||
posEnd = W_CheckNumForFolderEndPK3("SOC/", wadnum, posStart);
|
posEnd = W_CheckNumForFolderEndPK3("SOC/", wadnum, posStart);
|
||||||
posStart++;
|
|
||||||
for(; posStart < posEnd; posStart++)
|
for(; posStart < posEnd; posStart++)
|
||||||
{
|
{
|
||||||
lumpinfo_t *lump_p = &wadfiles[wadnum]->lumpinfo[posStart];
|
lumpinfo_t *lump_p = &wadfiles[wadnum]->lumpinfo[posStart];
|
||||||
size_t length = strlen(wadfiles[wadnum]->filename) + 1 + strlen(lump_p->name2); // length of file name, '|', and lump name
|
size_t length = strlen(wadfiles[wadnum]->filename) + 1 + strlen(lump_p->fullname); // length of file name, '|', and lump name
|
||||||
char *name = malloc(length + 1);
|
char *name = malloc(length + 1);
|
||||||
sprintf(name, "%s|%s", wadfiles[wadnum]->filename, lump_p->name2);
|
sprintf(name, "%s|%s", wadfiles[wadnum]->filename, lump_p->fullname);
|
||||||
name[length] = '\0';
|
name[length] = '\0';
|
||||||
CONS_Printf(M_GetText("Loading SOC from %s\n"), name);
|
CONS_Printf(M_GetText("Loading SOC from %s\n"), name);
|
||||||
DEH_LoadDehackedLumpPwad(wadnum, posStart);
|
DEH_LoadDehackedLumpPwad(wadnum, posStart);
|
||||||
|
@ -240,9 +244,9 @@ static inline void W_LoadDehackedLumps(UINT16 wadnum)
|
||||||
for (lump = 0; lump < wadfiles[wadnum]->numlumps; lump++, lump_p++)
|
for (lump = 0; lump < wadfiles[wadnum]->numlumps; lump++, lump_p++)
|
||||||
if (memcmp(lump_p->name,"SOC_",4)==0) // Check for generic SOC lump
|
if (memcmp(lump_p->name,"SOC_",4)==0) // Check for generic SOC lump
|
||||||
{ // shameless copy+paste of code from LUA_LoadLump
|
{ // shameless copy+paste of code from LUA_LoadLump
|
||||||
size_t length = strlen(wadfiles[wadnum]->filename) + 1 + strlen(lump_p->name2); // length of file name, '|', and lump name
|
size_t length = strlen(wadfiles[wadnum]->filename) + 1 + strlen(lump_p->fullname); // length of file name, '|', and lump name
|
||||||
char *name = malloc(length + 1);
|
char *name = malloc(length + 1);
|
||||||
sprintf(name, "%s|%s", wadfiles[wadnum]->filename, lump_p->name2);
|
sprintf(name, "%s|%s", wadfiles[wadnum]->filename, lump_p->fullname);
|
||||||
name[length] = '\0';
|
name[length] = '\0';
|
||||||
|
|
||||||
CONS_Printf(M_GetText("Loading SOC from %s\n"), name);
|
CONS_Printf(M_GetText("Loading SOC from %s\n"), name);
|
||||||
|
@ -339,16 +343,16 @@ static restype_t ResourceFileDetect (const char* filename)
|
||||||
static lumpinfo_t* ResGetLumpsStandalone (FILE* handle, UINT16* numlumps, const char* lumpname)
|
static lumpinfo_t* ResGetLumpsStandalone (FILE* handle, UINT16* numlumps, const char* lumpname)
|
||||||
{
|
{
|
||||||
lumpinfo_t* lumpinfo = Z_Calloc(sizeof (*lumpinfo), PU_STATIC, NULL);
|
lumpinfo_t* lumpinfo = Z_Calloc(sizeof (*lumpinfo), PU_STATIC, NULL);
|
||||||
lumpinfo = Z_Calloc(sizeof (*lumpinfo), PU_STATIC, NULL);
|
|
||||||
lumpinfo->position = 0;
|
lumpinfo->position = 0;
|
||||||
fseek(handle, 0, SEEK_END);
|
fseek(handle, 0, SEEK_END);
|
||||||
lumpinfo->size = ftell(handle);
|
lumpinfo->size = ftell(handle);
|
||||||
fseek(handle, 0, SEEK_SET);
|
fseek(handle, 0, SEEK_SET);
|
||||||
strcpy(lumpinfo->name, lumpname);
|
strlcpy(lumpinfo->name, lumpname, 9);
|
||||||
// Allocate the lump's full name.
|
|
||||||
lumpinfo->name2 = Z_Malloc(9 * sizeof(char), PU_STATIC, NULL);
|
// Allocate the lump's full and long name.
|
||||||
strcpy(lumpinfo->name2, lumpname);
|
lumpinfo->fullname = Z_StrDup(lumpname);
|
||||||
lumpinfo->name2[8] = '\0';
|
lumpinfo->longname = Z_StrDup(lumpname);
|
||||||
|
|
||||||
*numlumps = 1;
|
*numlumps = 1;
|
||||||
return lumpinfo;
|
return lumpinfo;
|
||||||
}
|
}
|
||||||
|
@ -435,10 +439,16 @@ static lumpinfo_t* ResGetLumpsWad (FILE* handle, UINT16* nlmp, const char* filen
|
||||||
lump_p->compression = CM_NOCOMPRESSION;
|
lump_p->compression = CM_NOCOMPRESSION;
|
||||||
memset(lump_p->name, 0x00, 9);
|
memset(lump_p->name, 0x00, 9);
|
||||||
strncpy(lump_p->name, fileinfo->name, 8);
|
strncpy(lump_p->name, fileinfo->name, 8);
|
||||||
|
|
||||||
|
// Allocate the lump's long name.
|
||||||
|
lump_p->longname = Z_Malloc(9 * sizeof(char), PU_STATIC, NULL);
|
||||||
|
strncpy(lump_p->longname, fileinfo->name, 8);
|
||||||
|
lump_p->longname[8] = '\0';
|
||||||
|
|
||||||
// Allocate the lump's full name.
|
// Allocate the lump's full name.
|
||||||
lump_p->name2 = Z_Malloc(9 * sizeof(char), PU_STATIC, NULL);
|
lump_p->fullname = Z_Malloc(9 * sizeof(char), PU_STATIC, NULL);
|
||||||
strncpy(lump_p->name2, fileinfo->name, 8);
|
strncpy(lump_p->fullname, fileinfo->name, 8);
|
||||||
lump_p->name2[8] = '\0';
|
lump_p->fullname[8] = '\0';
|
||||||
}
|
}
|
||||||
free(fileinfov);
|
free(fileinfov);
|
||||||
*nlmp = numlumps;
|
*nlmp = numlumps;
|
||||||
|
@ -529,8 +539,8 @@ typedef struct zlentry_s
|
||||||
static lumpinfo_t* ResGetLumpsZip (FILE* handle, UINT16* nlmp)
|
static lumpinfo_t* ResGetLumpsZip (FILE* handle, UINT16* nlmp)
|
||||||
{
|
{
|
||||||
zend_t zend;
|
zend_t zend;
|
||||||
zentry_t* zentries;
|
zentry_t zentry;
|
||||||
zentry_t* zentry;
|
zlentry_t zlentry;
|
||||||
|
|
||||||
UINT16 numlumps = *nlmp;
|
UINT16 numlumps = *nlmp;
|
||||||
lumpinfo_t* lumpinfo;
|
lumpinfo_t* lumpinfo;
|
||||||
|
@ -558,40 +568,36 @@ static lumpinfo_t* ResGetLumpsZip (FILE* handle, UINT16* nlmp)
|
||||||
numlumps = zend.entries;
|
numlumps = zend.entries;
|
||||||
|
|
||||||
lump_p = lumpinfo = Z_Malloc(numlumps * sizeof (*lumpinfo), PU_STATIC, NULL);
|
lump_p = lumpinfo = Z_Malloc(numlumps * sizeof (*lumpinfo), PU_STATIC, NULL);
|
||||||
zentry = zentries = malloc(numlumps * sizeof (*zentries));
|
|
||||||
|
|
||||||
fseek(handle, zend.cdiroffset, SEEK_SET);
|
fseek(handle, zend.cdiroffset, SEEK_SET);
|
||||||
for (i = 0; i < numlumps; i++, zentry++, lump_p++)
|
for (i = 0; i < numlumps; i++, lump_p++)
|
||||||
{
|
{
|
||||||
char* fullname;
|
char* fullname;
|
||||||
char* trimname;
|
char* trimname;
|
||||||
char* dotpos;
|
char* dotpos;
|
||||||
|
|
||||||
if (fread(zentry, 1, sizeof(zentry_t), handle) < sizeof(zentry_t))
|
if (fread(&zentry, 1, sizeof(zentry_t), handle) < sizeof(zentry_t))
|
||||||
{
|
{
|
||||||
CONS_Alert(CONS_ERROR, "Failed to read central directory (%s)\n", M_FileError(handle));
|
CONS_Alert(CONS_ERROR, "Failed to read central directory (%s)\n", M_FileError(handle));
|
||||||
Z_Free(lumpinfo);
|
Z_Free(lumpinfo);
|
||||||
free(zentry);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (memcmp(zentry->signature, pat_central, 4))
|
if (memcmp(zentry.signature, pat_central, 4))
|
||||||
{
|
{
|
||||||
CONS_Alert(CONS_ERROR, "Central directory is corrupt\n");
|
CONS_Alert(CONS_ERROR, "Central directory is corrupt\n");
|
||||||
Z_Free(lumpinfo);
|
Z_Free(lumpinfo);
|
||||||
free(zentry);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
lump_p->position = zentry->offset + zentry->namelen + zentry->xtralen + sizeof(zlentry_t);
|
lump_p->position = zentry.offset; // NOT ACCURATE YET: we still need to read the local entry to find our true position
|
||||||
lump_p->disksize = zentry->compsize;
|
lump_p->disksize = zentry.compsize;
|
||||||
lump_p->size = zentry->size;
|
lump_p->size = zentry.size;
|
||||||
|
|
||||||
fullname = malloc(zentry->namelen + 1);
|
fullname = malloc(zentry.namelen + 1);
|
||||||
if (fgets(fullname, zentry->namelen + 1, handle) != fullname)
|
if (fgets(fullname, zentry.namelen + 1, handle) != fullname)
|
||||||
{
|
{
|
||||||
CONS_Alert(CONS_ERROR, "Unable to read lumpname (%s)\n", M_FileError(handle));
|
CONS_Alert(CONS_ERROR, "Unable to read lumpname (%s)\n", M_FileError(handle));
|
||||||
Z_Free(lumpinfo);
|
Z_Free(lumpinfo);
|
||||||
free(zentry);
|
|
||||||
free(fullname);
|
free(fullname);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -608,10 +614,13 @@ static lumpinfo_t* ResGetLumpsZip (FILE* handle, UINT16* nlmp)
|
||||||
memset(lump_p->name, '\0', 9); // Making sure they're initialized to 0. Is it necessary?
|
memset(lump_p->name, '\0', 9); // Making sure they're initialized to 0. Is it necessary?
|
||||||
strncpy(lump_p->name, trimname, min(8, dotpos - trimname));
|
strncpy(lump_p->name, trimname, min(8, dotpos - trimname));
|
||||||
|
|
||||||
lump_p->name2 = Z_Calloc(zentry->namelen + 1, PU_STATIC, NULL);
|
lump_p->longname = Z_Calloc(dotpos - trimname + 1, PU_STATIC, NULL);
|
||||||
strncpy(lump_p->name2, fullname, zentry->namelen);
|
strlcpy(lump_p->longname, trimname, dotpos - trimname + 1);
|
||||||
|
|
||||||
switch(zentry->compression)
|
lump_p->fullname = Z_Calloc(zentry.namelen + 1, PU_STATIC, NULL);
|
||||||
|
strncpy(lump_p->fullname, fullname, zentry.namelen);
|
||||||
|
|
||||||
|
switch(zentry.compression)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
lump_p->compression = CM_NOCOMPRESSION;
|
lump_p->compression = CM_NOCOMPRESSION;
|
||||||
|
@ -629,14 +638,47 @@ static lumpinfo_t* ResGetLumpsZip (FILE* handle, UINT16* nlmp)
|
||||||
lump_p->compression = CM_UNSUPPORTED;
|
lump_p->compression = CM_UNSUPPORTED;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
free(fullname);
|
free(fullname);
|
||||||
|
|
||||||
|
// skip and ignore comments/extra fields
|
||||||
|
if (fseek(handle, zentry.xtralen + zentry.commlen, SEEK_CUR) != 0)
|
||||||
|
{
|
||||||
|
CONS_Alert(CONS_ERROR, "Central directory is corrupt\n");
|
||||||
|
Z_Free(lumpinfo);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adjust lump position values properly
|
||||||
|
for (i = 0, lump_p = lumpinfo; i < numlumps; i++, lump_p++)
|
||||||
|
{
|
||||||
|
// skip and ignore comments/extra fields
|
||||||
|
if ((fseek(handle, lump_p->position, SEEK_SET) != 0) || (fread(&zlentry, 1, sizeof(zlentry_t), handle) < sizeof(zlentry_t)))
|
||||||
|
{
|
||||||
|
CONS_Alert(CONS_ERROR, "Local headers for lump %s are corrupt\n", lump_p->fullname);
|
||||||
|
Z_Free(lumpinfo);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
lump_p->position += sizeof(zlentry_t) + zlentry.namelen + zlentry.xtralen;
|
||||||
}
|
}
|
||||||
|
|
||||||
*nlmp = numlumps;
|
*nlmp = numlumps;
|
||||||
return lumpinfo;
|
return lumpinfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void W_ReadFileShaders(wadfile_t *wadfile)
|
||||||
|
{
|
||||||
|
#ifdef HWRENDER
|
||||||
|
if (rendermode == render_opengl)
|
||||||
|
{
|
||||||
|
HWR_LoadShaders(numwadfiles - 1, W_FileHasFolders(wadfile));
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
(void)wadfile;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
// Allocate a wadfile, setup the lumpinfo (directory) and
|
// Allocate a wadfile, setup the lumpinfo (directory) and
|
||||||
// lumpcache, add the wadfile to the current active wadfiles
|
// lumpcache, add the wadfile to the current active wadfiles
|
||||||
//
|
//
|
||||||
|
@ -768,10 +810,8 @@ UINT16 W_InitFile(const char *filename)
|
||||||
wadfiles[numwadfiles] = wadfile;
|
wadfiles[numwadfiles] = wadfile;
|
||||||
numwadfiles++; // must come BEFORE W_LoadDehackedLumps, so any addfile called by COM_BufInsertText called by Lua doesn't overwrite what we just loaded
|
numwadfiles++; // must come BEFORE W_LoadDehackedLumps, so any addfile called by COM_BufInsertText called by Lua doesn't overwrite what we just loaded
|
||||||
|
|
||||||
#ifdef HWRENDER
|
// Read shaders from file
|
||||||
if (rendermode == render_opengl)
|
W_ReadFileShaders(wadfile);
|
||||||
HWR_LoadShaders(numwadfiles - 1, (wadfile->type == RET_PK3));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// TODO: HACK ALERT - Load Lua & SOC stuff right here. I feel like this should be out of this place, but... Let's stick with this for now.
|
// TODO: HACK ALERT - Load Lua & SOC stuff right here. I feel like this should be out of this place, but... Let's stick with this for now.
|
||||||
switch (wadfile->type)
|
switch (wadfile->type)
|
||||||
|
@ -912,14 +952,13 @@ UINT16 W_CheckNumForNamePwad(const char *name, UINT16 wad, UINT16 startlump)
|
||||||
UINT16 i;
|
UINT16 i;
|
||||||
static char uname[9];
|
static char uname[9];
|
||||||
|
|
||||||
memset(uname, 0x00, sizeof uname);
|
|
||||||
strncpy(uname, name, 8);
|
|
||||||
uname[8] = 0;
|
|
||||||
strupr(uname);
|
|
||||||
|
|
||||||
if (!TestValidLump(wad,0))
|
if (!TestValidLump(wad,0))
|
||||||
return INT16_MAX;
|
return INT16_MAX;
|
||||||
|
|
||||||
|
memset(uname, 0, sizeof uname);
|
||||||
|
strncpy(uname, name, sizeof(uname)-1);
|
||||||
|
strupr(uname);
|
||||||
|
|
||||||
//
|
//
|
||||||
// scan forward
|
// scan forward
|
||||||
// start at 'startlump', useful parameter when there are multiple
|
// start at 'startlump', useful parameter when there are multiple
|
||||||
|
@ -929,25 +968,74 @@ UINT16 W_CheckNumForNamePwad(const char *name, UINT16 wad, UINT16 startlump)
|
||||||
{
|
{
|
||||||
lumpinfo_t *lump_p = wadfiles[wad]->lumpinfo + startlump;
|
lumpinfo_t *lump_p = wadfiles[wad]->lumpinfo + startlump;
|
||||||
for (i = startlump; i < wadfiles[wad]->numlumps; i++, lump_p++)
|
for (i = startlump; i < wadfiles[wad]->numlumps; i++, lump_p++)
|
||||||
{
|
if (memcmp(lump_p->name, uname, sizeof(uname) - 1) == 0)
|
||||||
if (memcmp(lump_p->name,uname,8) == 0)
|
|
||||||
return i;
|
return i;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// not found.
|
// not found.
|
||||||
return INT16_MAX;
|
return INT16_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Like W_CheckNumForNamePwad, but can find entries with long names
|
||||||
|
//
|
||||||
|
// Should be the only version, but that's not possible until we fix
|
||||||
|
// all the instances of non null-terminated strings in the codebase...
|
||||||
|
//
|
||||||
|
UINT16 W_CheckNumForLongNamePwad(const char *name, UINT16 wad, UINT16 startlump)
|
||||||
|
{
|
||||||
|
UINT16 i;
|
||||||
|
static char uname[256 + 1];
|
||||||
|
|
||||||
|
if (!TestValidLump(wad,0))
|
||||||
|
return INT16_MAX;
|
||||||
|
|
||||||
|
strlcpy(uname, name, sizeof uname);
|
||||||
|
strupr(uname);
|
||||||
|
|
||||||
|
//
|
||||||
|
// scan forward
|
||||||
|
// start at 'startlump', useful parameter when there are multiple
|
||||||
|
// resources with the same name
|
||||||
|
//
|
||||||
|
if (startlump < wadfiles[wad]->numlumps)
|
||||||
|
{
|
||||||
|
lumpinfo_t *lump_p = wadfiles[wad]->lumpinfo + startlump;
|
||||||
|
for (i = startlump; i < wadfiles[wad]->numlumps; i++, lump_p++)
|
||||||
|
if (!strcmp(lump_p->longname, uname))
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
// not found.
|
||||||
|
return INT16_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT16
|
||||||
|
W_CheckNumForMarkerStartPwad (const char *name, UINT16 wad, UINT16 startlump)
|
||||||
|
{
|
||||||
|
UINT16 marker;
|
||||||
|
marker = W_CheckNumForNamePwad(name, wad, startlump);
|
||||||
|
if (marker != INT16_MAX)
|
||||||
|
marker++; // Do not count the first marker
|
||||||
|
return marker;
|
||||||
|
}
|
||||||
|
|
||||||
// Look for the first lump from a folder.
|
// Look for the first lump from a folder.
|
||||||
UINT16 W_CheckNumForFolderStartPK3(const char *name, UINT16 wad, UINT16 startlump)
|
UINT16 W_CheckNumForFolderStartPK3(const char *name, UINT16 wad, UINT16 startlump)
|
||||||
{
|
{
|
||||||
|
size_t name_length;
|
||||||
INT32 i;
|
INT32 i;
|
||||||
lumpinfo_t *lump_p = wadfiles[wad]->lumpinfo + startlump;
|
lumpinfo_t *lump_p = wadfiles[wad]->lumpinfo + startlump;
|
||||||
|
name_length = strlen(name);
|
||||||
for (i = startlump; i < wadfiles[wad]->numlumps; i++, lump_p++)
|
for (i = startlump; i < wadfiles[wad]->numlumps; i++, lump_p++)
|
||||||
{
|
{
|
||||||
if (strnicmp(name, lump_p->name2, strlen(name)) == 0)
|
if (strnicmp(name, lump_p->fullname, name_length) == 0)
|
||||||
|
{
|
||||||
|
/* SLADE is special and puts a single directory entry. Skip that. */
|
||||||
|
if (strlen(lump_p->fullname) == name_length)
|
||||||
|
i++;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
@ -959,9 +1047,10 @@ UINT16 W_CheckNumForFolderEndPK3(const char *name, UINT16 wad, UINT16 startlump)
|
||||||
{
|
{
|
||||||
INT32 i;
|
INT32 i;
|
||||||
lumpinfo_t *lump_p = wadfiles[wad]->lumpinfo + startlump;
|
lumpinfo_t *lump_p = wadfiles[wad]->lumpinfo + startlump;
|
||||||
|
size_t name_length = strlen(name);
|
||||||
for (i = startlump; i < wadfiles[wad]->numlumps; i++, lump_p++)
|
for (i = startlump; i < wadfiles[wad]->numlumps; i++, lump_p++)
|
||||||
{
|
{
|
||||||
if (strnicmp(name, lump_p->name2, strlen(name)))
|
if (strnicmp(name, lump_p->fullname, name_length))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return i;
|
return i;
|
||||||
|
@ -973,9 +1062,10 @@ UINT16 W_CheckNumForFullNamePK3(const char *name, UINT16 wad, UINT16 startlump)
|
||||||
{
|
{
|
||||||
INT32 i;
|
INT32 i;
|
||||||
lumpinfo_t *lump_p = wadfiles[wad]->lumpinfo + startlump;
|
lumpinfo_t *lump_p = wadfiles[wad]->lumpinfo + startlump;
|
||||||
|
size_t name_length = strlen(name);
|
||||||
for (i = startlump; i < wadfiles[wad]->numlumps; i++, lump_p++)
|
for (i = startlump; i < wadfiles[wad]->numlumps; i++, lump_p++)
|
||||||
{
|
{
|
||||||
if (!strnicmp(name, lump_p->name2, strlen(name)))
|
if (!strnicmp(name, lump_p->fullname, name_length))
|
||||||
{
|
{
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
@ -993,11 +1083,15 @@ lumpnum_t W_CheckNumForName(const char *name)
|
||||||
INT32 i;
|
INT32 i;
|
||||||
lumpnum_t check = INT16_MAX;
|
lumpnum_t check = INT16_MAX;
|
||||||
|
|
||||||
|
if (!*name) // some doofus gave us an empty string?
|
||||||
|
return LUMPERROR;
|
||||||
|
|
||||||
// Check the lumpnumcache first. Loop backwards so that we check
|
// Check the lumpnumcache first. Loop backwards so that we check
|
||||||
// most recent entries first
|
// most recent entries first
|
||||||
for (i = lumpnumcacheindex + LUMPNUMCACHESIZE; i > lumpnumcacheindex; i--)
|
for (i = lumpnumcacheindex + LUMPNUMCACHESIZE; i > lumpnumcacheindex; i--)
|
||||||
{
|
{
|
||||||
if (strncmp(lumpnumcache[i & (LUMPNUMCACHESIZE - 1)].lumpname, name, 8) == 0)
|
if (!lumpnumcache[i & (LUMPNUMCACHESIZE - 1)].lumpname[8]
|
||||||
|
&& strncmp(lumpnumcache[i & (LUMPNUMCACHESIZE - 1)].lumpname, name, 8) == 0)
|
||||||
{
|
{
|
||||||
lumpnumcacheindex = i & (LUMPNUMCACHESIZE - 1);
|
lumpnumcacheindex = i & (LUMPNUMCACHESIZE - 1);
|
||||||
return lumpnumcache[lumpnumcacheindex].lumpnum;
|
return lumpnumcache[lumpnumcacheindex].lumpnum;
|
||||||
|
@ -1017,6 +1111,7 @@ lumpnum_t W_CheckNumForName(const char *name)
|
||||||
{
|
{
|
||||||
// Update the cache.
|
// Update the cache.
|
||||||
lumpnumcacheindex = (lumpnumcacheindex + 1) & (LUMPNUMCACHESIZE - 1);
|
lumpnumcacheindex = (lumpnumcacheindex + 1) & (LUMPNUMCACHESIZE - 1);
|
||||||
|
memset(lumpnumcache[lumpnumcacheindex].lumpname, '\0', 32);
|
||||||
strncpy(lumpnumcache[lumpnumcacheindex].lumpname, name, 8);
|
strncpy(lumpnumcache[lumpnumcacheindex].lumpname, name, 8);
|
||||||
lumpnumcache[lumpnumcacheindex].lumpnum = (i<<16)+check;
|
lumpnumcache[lumpnumcacheindex].lumpnum = (i<<16)+check;
|
||||||
|
|
||||||
|
@ -1024,6 +1119,58 @@ lumpnum_t W_CheckNumForName(const char *name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Like W_CheckNumForName, but can find entries with long names
|
||||||
|
//
|
||||||
|
// Should be the only version, but that's not possible until we fix
|
||||||
|
// all the instances of non null-terminated strings in the codebase...
|
||||||
|
//
|
||||||
|
lumpnum_t W_CheckNumForLongName(const char *name)
|
||||||
|
{
|
||||||
|
INT32 i;
|
||||||
|
lumpnum_t check = INT16_MAX;
|
||||||
|
|
||||||
|
if (!*name) // some doofus gave us an empty string?
|
||||||
|
return LUMPERROR;
|
||||||
|
|
||||||
|
// Check the lumpnumcache first. Loop backwards so that we check
|
||||||
|
// most recent entries first
|
||||||
|
for (i = lumpnumcacheindex + LUMPNUMCACHESIZE; i > lumpnumcacheindex; i--)
|
||||||
|
{
|
||||||
|
if (strcmp(lumpnumcache[i & (LUMPNUMCACHESIZE - 1)].lumpname, name) == 0)
|
||||||
|
{
|
||||||
|
lumpnumcacheindex = i & (LUMPNUMCACHESIZE - 1);
|
||||||
|
return lumpnumcache[lumpnumcacheindex].lumpnum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (check == INT16_MAX)
|
||||||
|
{
|
||||||
|
// scan wad files backwards so patch lump files take precedence
|
||||||
|
for (i = numwadfiles - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
check = W_CheckNumForLongNamePwad(name,(UINT16)i,0);
|
||||||
|
if (check != INT16_MAX)
|
||||||
|
break; //found it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (check == INT16_MAX) return LUMPERROR;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (strlen(name) < 32)
|
||||||
|
{
|
||||||
|
// Update the cache.
|
||||||
|
lumpnumcacheindex = (lumpnumcacheindex + 1) & (LUMPNUMCACHESIZE - 1);
|
||||||
|
memset(lumpnumcache[lumpnumcacheindex].lumpname, '\0', 32);
|
||||||
|
strlcpy(lumpnumcache[lumpnumcacheindex].lumpname, name, 32);
|
||||||
|
lumpnumcache[lumpnumcacheindex].lumpnum = (i << 16) + check;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (i << 16) + check;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Look for valid map data through all added files in descendant order.
|
// Look for valid map data through all added files in descendant order.
|
||||||
// Get a map marker for WADs, and a standalone WAD file lump inside PK3s.
|
// Get a map marker for WADs, and a standalone WAD file lump inside PK3s.
|
||||||
// TODO: Make it search through cache first, maybe...?
|
// TODO: Make it search through cache first, maybe...?
|
||||||
|
@ -1047,9 +1194,13 @@ lumpnum_t W_CheckNumForMap(const char *name)
|
||||||
else
|
else
|
||||||
continue;
|
continue;
|
||||||
// Now look for the specified map.
|
// Now look for the specified map.
|
||||||
for (++lumpNum; lumpNum < end; lumpNum++)
|
for (; lumpNum < end; lumpNum++)
|
||||||
if (!strnicmp(name, (wadfiles[i]->lumpinfo + lumpNum)->name, 8))
|
if (!strnicmp(name, (wadfiles[i]->lumpinfo + lumpNum)->name, 8))
|
||||||
return (i<<16) + lumpNum;
|
{
|
||||||
|
const char *extension = strrchr(wadfiles[i]->lumpinfo[lumpNum].fullname, '.');
|
||||||
|
if (!(extension && stricmp(extension, ".wad")))
|
||||||
|
return (i<<16) + lumpNum;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return LUMPERROR;
|
return LUMPERROR;
|
||||||
|
@ -1072,6 +1223,24 @@ lumpnum_t W_GetNumForName(const char *name)
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Like W_GetNumForName, but can find entries with long names
|
||||||
|
//
|
||||||
|
// Should be the only version, but that's not possible until we fix
|
||||||
|
// all the instances of non null-terminated strings in the codebase...
|
||||||
|
//
|
||||||
|
lumpnum_t W_GetNumForLongName(const char *name)
|
||||||
|
{
|
||||||
|
lumpnum_t i;
|
||||||
|
|
||||||
|
i = W_CheckNumForLongName(name);
|
||||||
|
|
||||||
|
if (i == LUMPERROR)
|
||||||
|
I_Error("W_GetNumForLongName: %s not found!\n", name);
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// W_CheckNumForNameInBlock
|
// W_CheckNumForNameInBlock
|
||||||
// Checks only in blocks from blockstart lump to blockend lump
|
// Checks only in blocks from blockstart lump to blockend lump
|
||||||
|
@ -1142,7 +1311,7 @@ boolean W_IsLumpWad(lumpnum_t lumpnum)
|
||||||
{
|
{
|
||||||
if (wadfiles[WADFILENUM(lumpnum)]->type == RET_PK3)
|
if (wadfiles[WADFILENUM(lumpnum)]->type == RET_PK3)
|
||||||
{
|
{
|
||||||
const char *lumpfullName = (wadfiles[WADFILENUM(lumpnum)]->lumpinfo + LUMPNUM(lumpnum))->name2;
|
const char *lumpfullName = (wadfiles[WADFILENUM(lumpnum)]->lumpinfo + LUMPNUM(lumpnum))->fullname;
|
||||||
|
|
||||||
if (strlen(lumpfullName) < 4)
|
if (strlen(lumpfullName) < 4)
|
||||||
return false; // can't possibly be a WAD can it?
|
return false; // can't possibly be a WAD can it?
|
||||||
|
@ -1152,6 +1321,22 @@ boolean W_IsLumpWad(lumpnum_t lumpnum)
|
||||||
return false; // WADs should never be inside non-PK3s as far as SRB2 is concerned
|
return false; // WADs should never be inside non-PK3s as far as SRB2 is concerned
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// W_IsLumpFolder
|
||||||
|
// Is the lump a folder? (not in a WAD obviously)
|
||||||
|
//
|
||||||
|
boolean W_IsLumpFolder(UINT16 wad, UINT16 lump)
|
||||||
|
{
|
||||||
|
if (W_FileHasFolders(wadfiles[wad]))
|
||||||
|
{
|
||||||
|
const char *name = wadfiles[wad]->lumpinfo[lump].fullname;
|
||||||
|
|
||||||
|
return (name[strlen(name)-1] == '/'); // folders end in '/'
|
||||||
|
}
|
||||||
|
|
||||||
|
return false; // WADs don't have folders
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef HAVE_ZLIB
|
#ifdef HAVE_ZLIB
|
||||||
/* report a zlib or i/o error */
|
/* report a zlib or i/o error */
|
||||||
void zerr(int ret)
|
void zerr(int ret)
|
||||||
|
@ -1238,7 +1423,7 @@ size_t W_ReadLumpHeaderPwad(UINT16 wad, UINT16 lump, void *dest, size_t size, si
|
||||||
#ifdef NO_PNG_LUMPS
|
#ifdef NO_PNG_LUMPS
|
||||||
{
|
{
|
||||||
size_t bytesread = fread(dest, 1, size, handle);
|
size_t bytesread = fread(dest, 1, size, handle);
|
||||||
ErrorIfPNG(dest, bytesread, wadfiles[wad]->filename, l->name2);
|
ErrorIfPNG(dest, bytesread, wadfiles[wad]->filename, l->fullname);
|
||||||
return bytesread;
|
return bytesread;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
@ -1279,7 +1464,7 @@ size_t W_ReadLumpHeaderPwad(UINT16 wad, UINT16 lump, void *dest, size_t size, si
|
||||||
Z_Free(rawData);
|
Z_Free(rawData);
|
||||||
Z_Free(decData);
|
Z_Free(decData);
|
||||||
#ifdef NO_PNG_LUMPS
|
#ifdef NO_PNG_LUMPS
|
||||||
ErrorIfPNG(dest, size, wadfiles[wad]->filename, l->name2);
|
ErrorIfPNG(dest, size, wadfiles[wad]->filename, l->fullname);
|
||||||
#endif
|
#endif
|
||||||
return size;
|
return size;
|
||||||
#else
|
#else
|
||||||
|
@ -1341,7 +1526,7 @@ size_t W_ReadLumpHeaderPwad(UINT16 wad, UINT16 lump, void *dest, size_t size, si
|
||||||
Z_Free(decData);
|
Z_Free(decData);
|
||||||
|
|
||||||
#ifdef NO_PNG_LUMPS
|
#ifdef NO_PNG_LUMPS
|
||||||
ErrorIfPNG(dest, size, wadfiles[wad]->filename, l->name2);
|
ErrorIfPNG(dest, size, wadfiles[wad]->filename, l->fullname);
|
||||||
#endif
|
#endif
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
@ -1525,6 +1710,9 @@ void *W_CachePatchNum(lumpnum_t lumpnum, INT32 tag)
|
||||||
|
|
||||||
void W_UnlockCachedPatch(void *patch)
|
void W_UnlockCachedPatch(void *patch)
|
||||||
{
|
{
|
||||||
|
if (!patch)
|
||||||
|
return;
|
||||||
|
|
||||||
// The hardware code does its own memory management, as its patches
|
// The hardware code does its own memory management, as its patches
|
||||||
// have different lifetimes from software's.
|
// have different lifetimes from software's.
|
||||||
#ifdef HWRENDER
|
#ifdef HWRENDER
|
||||||
|
@ -1618,13 +1806,221 @@ void W_VerifyFileMD5(UINT16 wadfilenum, const char *matchmd5)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Verify versions for different archive
|
||||||
|
// formats. checklist assumed to be valid.
|
||||||
|
|
||||||
|
static int
|
||||||
|
W_VerifyName (const char *name, lumpchecklist_t *checklist, boolean status)
|
||||||
|
{
|
||||||
|
size_t j;
|
||||||
|
for (j = 0; checklist[j].len && checklist[j].name; ++j)
|
||||||
|
{
|
||||||
|
if (( strncasecmp(name, checklist[j].name,
|
||||||
|
checklist[j].len) != false ) == status)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int W_VerifyWAD(FILE *fp, lumpchecklist_t *checklist, boolean status)
|
||||||
|
{
|
||||||
|
size_t i, j;
|
||||||
|
// if we're here it's a WAD file
|
||||||
|
wadinfo_t header;
|
||||||
|
filelump_t lumpinfo;
|
||||||
|
|
||||||
|
// read the header
|
||||||
|
if (fread(&header, 1, sizeof header, fp) == sizeof header
|
||||||
|
&& header.numlumps < INT16_MAX
|
||||||
|
&& strncmp(header.identification, "ZWAD", 4)
|
||||||
|
&& strncmp(header.identification, "IWAD", 4)
|
||||||
|
&& strncmp(header.identification, "PWAD", 4)
|
||||||
|
&& strncmp(header.identification, "SDLL", 4))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
header.numlumps = LONG(header.numlumps);
|
||||||
|
header.infotableofs = LONG(header.infotableofs);
|
||||||
|
|
||||||
|
// let seek to the lumpinfo list
|
||||||
|
if (fseek(fp, header.infotableofs, SEEK_SET) == -1)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
for (i = 0; i < header.numlumps; i++)
|
||||||
|
{
|
||||||
|
// fill in lumpinfo for this wad file directory
|
||||||
|
if (fread(&lumpinfo, sizeof (lumpinfo), 1 , fp) != 1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
lumpinfo.filepos = LONG(lumpinfo.filepos);
|
||||||
|
lumpinfo.size = LONG(lumpinfo.size);
|
||||||
|
|
||||||
|
if (lumpinfo.size == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (j = 0; j < NUMSPRITES; j++)
|
||||||
|
if (sprnames[j] && !strncmp(lumpinfo.name, sprnames[j], 4)) // Sprites
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (! W_VerifyName(lumpinfo.name, checklist, status))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// List of blacklisted folders to use when checking the PK3
|
||||||
|
static lumpchecklist_t folderblacklist[] =
|
||||||
|
{
|
||||||
|
{"Lua/", 4},
|
||||||
|
{"SOC/", 4},
|
||||||
|
{"Sprites/", 8},
|
||||||
|
{"Textures/", 9},
|
||||||
|
{"Patches/", 8},
|
||||||
|
{"Flats/", 6},
|
||||||
|
{"Fades/", 6},
|
||||||
|
{NULL, 0},
|
||||||
|
};
|
||||||
|
|
||||||
|
static int
|
||||||
|
W_VerifyPK3 (FILE *fp, lumpchecklist_t *checklist, boolean status)
|
||||||
|
{
|
||||||
|
int verified = true;
|
||||||
|
|
||||||
|
zend_t zend;
|
||||||
|
zentry_t zentry;
|
||||||
|
zlentry_t zlentry;
|
||||||
|
|
||||||
|
long file_size;/* size of zip file */
|
||||||
|
long data_size;/* size of data inside zip file */
|
||||||
|
|
||||||
|
long old_position;
|
||||||
|
|
||||||
|
UINT16 numlumps;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
char pat_central[] = {0x50, 0x4b, 0x01, 0x02, 0x00};
|
||||||
|
char pat_end[] = {0x50, 0x4b, 0x05, 0x06, 0x00};
|
||||||
|
|
||||||
|
char lumpname[9];
|
||||||
|
|
||||||
|
// Haha the ResGetLumpsZip function doesn't
|
||||||
|
// check for file errors, so neither will I.
|
||||||
|
|
||||||
|
// Central directory bullshit
|
||||||
|
|
||||||
|
fseek(fp, 0, SEEK_END);
|
||||||
|
file_size = ftell(fp);
|
||||||
|
|
||||||
|
if (!ResFindSignature(fp, pat_end, max(0, ftell(fp) - (22 + 65536))))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
fseek(fp, -4, SEEK_CUR);
|
||||||
|
if (fread(&zend, 1, sizeof zend, fp) < sizeof zend)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
data_size = sizeof zend;
|
||||||
|
|
||||||
|
numlumps = zend.entries;
|
||||||
|
|
||||||
|
fseek(fp, zend.cdiroffset, SEEK_SET);
|
||||||
|
for (i = 0; i < numlumps; i++)
|
||||||
|
{
|
||||||
|
char* fullname;
|
||||||
|
char* trimname;
|
||||||
|
char* dotpos;
|
||||||
|
|
||||||
|
if (fread(&zentry, 1, sizeof(zentry_t), fp) < sizeof(zentry_t))
|
||||||
|
return true;
|
||||||
|
if (memcmp(zentry.signature, pat_central, 4))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (verified == true)
|
||||||
|
{
|
||||||
|
fullname = malloc(zentry.namelen + 1);
|
||||||
|
if (fgets(fullname, zentry.namelen + 1, fp) != fullname)
|
||||||
|
{
|
||||||
|
free(fullname);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Strip away file address and extension for the 8char name.
|
||||||
|
if ((trimname = strrchr(fullname, '/')) != 0)
|
||||||
|
trimname++;
|
||||||
|
else
|
||||||
|
trimname = fullname; // Care taken for root files.
|
||||||
|
|
||||||
|
if (*trimname) // Ignore directories, well kinda
|
||||||
|
{
|
||||||
|
if ((dotpos = strrchr(trimname, '.')) == 0)
|
||||||
|
dotpos = fullname + strlen(fullname); // Watch for files without extension.
|
||||||
|
|
||||||
|
memset(lumpname, '\0', 9); // Making sure they're initialized to 0. Is it necessary?
|
||||||
|
strncpy(lumpname, trimname, min(8, dotpos - trimname));
|
||||||
|
|
||||||
|
if (! W_VerifyName(lumpname, checklist, status))
|
||||||
|
verified = false;
|
||||||
|
|
||||||
|
// Check for directories next, if it's blacklisted it will return false
|
||||||
|
else if (W_VerifyName(fullname, folderblacklist, status))
|
||||||
|
verified = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(fullname);
|
||||||
|
|
||||||
|
// skip and ignore comments/extra fields
|
||||||
|
if (fseek(fp, zentry.xtralen + zentry.commlen, SEEK_CUR) != 0)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (fseek(fp, zentry.namelen + zentry.xtralen + zentry.commlen, SEEK_CUR) != 0)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
data_size +=
|
||||||
|
sizeof zentry + zentry.namelen + zentry.xtralen + zentry.commlen;
|
||||||
|
|
||||||
|
old_position = ftell(fp);
|
||||||
|
|
||||||
|
if (fseek(fp, zentry.offset, SEEK_SET) != 0)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (fread(&zlentry, 1, sizeof(zlentry_t), fp) < sizeof (zlentry_t))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
data_size +=
|
||||||
|
sizeof zlentry + zlentry.namelen + zlentry.xtralen + zlentry.compsize;
|
||||||
|
|
||||||
|
fseek(fp, old_position, SEEK_SET);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data_size < file_size)
|
||||||
|
{
|
||||||
|
const char * error = "ZIP file has holes (%ld extra bytes)\n";
|
||||||
|
CONS_Alert(CONS_ERROR, error, (file_size - data_size));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else if (data_size > file_size)
|
||||||
|
{
|
||||||
|
const char * error = "Reported size of ZIP file contents exceeds file size (%ld extra bytes)\n";
|
||||||
|
CONS_Alert(CONS_ERROR, error, (data_size - file_size));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return verified;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Note: This never opens lumps themselves and therefore doesn't have to
|
// Note: This never opens lumps themselves and therefore doesn't have to
|
||||||
// deal with compressed lumps.
|
// deal with compressed lumps.
|
||||||
static int W_VerifyFile(const char *filename, lumpchecklist_t *checklist,
|
static int W_VerifyFile(const char *filename, lumpchecklist_t *checklist,
|
||||||
boolean status)
|
boolean status)
|
||||||
{
|
{
|
||||||
FILE *handle;
|
FILE *handle;
|
||||||
size_t i, j;
|
|
||||||
int goodfile = false;
|
int goodfile = false;
|
||||||
|
|
||||||
if (!checklist)
|
if (!checklist)
|
||||||
|
@ -1633,66 +2029,15 @@ static int W_VerifyFile(const char *filename, lumpchecklist_t *checklist,
|
||||||
if ((handle = W_OpenWadFile(&filename, false)) == NULL)
|
if ((handle = W_OpenWadFile(&filename, false)) == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
// detect wad file by the absence of the other supported extensions
|
if (stricmp(&filename[strlen(filename) - 4], ".pk3") == 0)
|
||||||
if (stricmp(&filename[strlen(filename) - 4], ".soc")
|
goodfile = W_VerifyPK3(handle, checklist, status);
|
||||||
#ifdef HAVE_BLUA
|
else
|
||||||
&& stricmp(&filename[strlen(filename) - 4], ".lua")
|
|
||||||
#endif
|
|
||||||
&& stricmp(&filename[strlen(filename) - 4], ".pk3"))
|
|
||||||
{
|
{
|
||||||
// assume wad file
|
// detect wad file by the absence of the other supported extensions
|
||||||
wadinfo_t header;
|
if (stricmp(&filename[strlen(filename) - 4], ".soc")
|
||||||
filelump_t lumpinfo;
|
&& stricmp(&filename[strlen(filename) - 4], ".lua"))
|
||||||
|
|
||||||
// read the header
|
|
||||||
if (fread(&header, 1, sizeof header, handle) == sizeof header
|
|
||||||
&& header.numlumps < INT16_MAX
|
|
||||||
&& strncmp(header.identification, "ZWAD", 4)
|
|
||||||
&& strncmp(header.identification, "IWAD", 4)
|
|
||||||
&& strncmp(header.identification, "PWAD", 4)
|
|
||||||
&& strncmp(header.identification, "SDLL", 4))
|
|
||||||
{
|
{
|
||||||
fclose(handle);
|
goodfile = W_VerifyWAD(handle, checklist, status);
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
header.numlumps = LONG(header.numlumps);
|
|
||||||
header.infotableofs = LONG(header.infotableofs);
|
|
||||||
|
|
||||||
// let seek to the lumpinfo list
|
|
||||||
if (fseek(handle, header.infotableofs, SEEK_SET) == -1)
|
|
||||||
{
|
|
||||||
fclose(handle);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
goodfile = true;
|
|
||||||
for (i = 0; i < header.numlumps; i++)
|
|
||||||
{
|
|
||||||
// fill in lumpinfo for this wad file directory
|
|
||||||
if (fread(&lumpinfo, sizeof (lumpinfo), 1 , handle) != 1)
|
|
||||||
{
|
|
||||||
fclose(handle);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
lumpinfo.filepos = LONG(lumpinfo.filepos);
|
|
||||||
lumpinfo.size = LONG(lumpinfo.size);
|
|
||||||
|
|
||||||
if (lumpinfo.size == 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
for (j = 0; j < NUMSPRITES; j++)
|
|
||||||
if (sprnames[j][0] && !strncmp(lumpinfo.name, sprnames[j], 4)) // Sprites
|
|
||||||
continue;
|
|
||||||
|
|
||||||
goodfile = false;
|
|
||||||
for (j = 0; checklist[j].len && checklist[j].name && !goodfile; j++)
|
|
||||||
if ((strncmp(lumpinfo.name, checklist[j].name, checklist[j].len) != false) == status)
|
|
||||||
goodfile = true;
|
|
||||||
|
|
||||||
if (!goodfile)
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fclose(handle);
|
fclose(handle);
|
||||||
|
|
14
src/w_wad.h
14
src/w_wad.h
|
@ -66,8 +66,9 @@ typedef struct
|
||||||
{
|
{
|
||||||
unsigned long position; // filelump_t filepos
|
unsigned long position; // filelump_t filepos
|
||||||
unsigned long disksize; // filelump_t size
|
unsigned long disksize; // filelump_t size
|
||||||
char name[9]; // filelump_t name[]
|
char name[9]; // filelump_t name[] e.g. "LongEntr"
|
||||||
char *name2; // Used by PK3s. Dynamically allocated name.
|
char *longname; // e.g. "LongEntryName"
|
||||||
|
char *fullname; // e.g. "Folder/Subfolder/LongEntryName.extension"
|
||||||
size_t size; // real (uncompressed) size
|
size_t size; // real (uncompressed) size
|
||||||
compmethod compression; // lump compression method
|
compmethod compression; // lump compression method
|
||||||
} lumpinfo_t;
|
} lumpinfo_t;
|
||||||
|
@ -137,10 +138,16 @@ void W_UnloadWadFile(UINT16 num);
|
||||||
// so that it stops with a message if a file was not found, but not if all is okay.
|
// so that it stops with a message if a file was not found, but not if all is okay.
|
||||||
INT32 W_InitMultipleFiles(char **filenames, boolean addons);
|
INT32 W_InitMultipleFiles(char **filenames, boolean addons);
|
||||||
|
|
||||||
|
#define W_FileHasFolders(wadfile) ((wadfile)->type == RET_PK3)
|
||||||
|
|
||||||
const char *W_CheckNameForNumPwad(UINT16 wad, UINT16 lump);
|
const char *W_CheckNameForNumPwad(UINT16 wad, UINT16 lump);
|
||||||
const char *W_CheckNameForNum(lumpnum_t lumpnum);
|
const char *W_CheckNameForNum(lumpnum_t lumpnum);
|
||||||
|
|
||||||
UINT16 W_CheckNumForNamePwad(const char *name, UINT16 wad, UINT16 startlump); // checks only in one pwad
|
UINT16 W_CheckNumForNamePwad(const char *name, UINT16 wad, UINT16 startlump); // checks only in one pwad
|
||||||
|
UINT16 W_CheckNumForLongNamePwad(const char *name, UINT16 wad, UINT16 startlump);
|
||||||
|
|
||||||
|
/* Find the first lump after F_START for instance. */
|
||||||
|
UINT16 W_CheckNumForMarkerStartPwad(const char *name, UINT16 wad, UINT16 startlump);
|
||||||
|
|
||||||
UINT16 W_CheckNumForFullNamePK3(const char *name, UINT16 wad, UINT16 startlump);
|
UINT16 W_CheckNumForFullNamePK3(const char *name, UINT16 wad, UINT16 startlump);
|
||||||
UINT16 W_CheckNumForFolderStartPK3(const char *name, UINT16 wad, UINT16 startlump);
|
UINT16 W_CheckNumForFolderStartPK3(const char *name, UINT16 wad, UINT16 startlump);
|
||||||
|
@ -148,7 +155,9 @@ UINT16 W_CheckNumForFolderEndPK3(const char *name, UINT16 wad, UINT16 startlump)
|
||||||
|
|
||||||
lumpnum_t W_CheckNumForMap(const char *name);
|
lumpnum_t W_CheckNumForMap(const char *name);
|
||||||
lumpnum_t W_CheckNumForName(const char *name);
|
lumpnum_t W_CheckNumForName(const char *name);
|
||||||
|
lumpnum_t W_CheckNumForLongName(const char *name);
|
||||||
lumpnum_t W_GetNumForName(const char *name); // like W_CheckNumForName but I_Error on LUMPERROR
|
lumpnum_t W_GetNumForName(const char *name); // like W_CheckNumForName but I_Error on LUMPERROR
|
||||||
|
lumpnum_t W_GetNumForLongName(const char *name);
|
||||||
lumpnum_t W_CheckNumForNameInBlock(const char *name, const char *blockstart, const char *blockend);
|
lumpnum_t W_CheckNumForNameInBlock(const char *name, const char *blockstart, const char *blockend);
|
||||||
UINT8 W_LumpExists(const char *name); // Lua uses this.
|
UINT8 W_LumpExists(const char *name); // Lua uses this.
|
||||||
|
|
||||||
|
@ -156,6 +165,7 @@ size_t W_LumpLengthPwad(UINT16 wad, UINT16 lump);
|
||||||
size_t W_LumpLength(lumpnum_t lumpnum);
|
size_t W_LumpLength(lumpnum_t lumpnum);
|
||||||
|
|
||||||
boolean W_IsLumpWad(lumpnum_t lumpnum); // for loading maps from WADs in PK3s
|
boolean W_IsLumpWad(lumpnum_t lumpnum); // for loading maps from WADs in PK3s
|
||||||
|
boolean W_IsLumpFolder(UINT16 wad, UINT16 lump); // for detecting folder "lumps"
|
||||||
|
|
||||||
#ifdef HAVE_ZLIB
|
#ifdef HAVE_ZLIB
|
||||||
void zerr(int ret); // zlib error checking
|
void zerr(int ret); // zlib error checking
|
||||||
|
|
Loading…
Reference in a new issue