mirror of
https://git.do.srb2.org/STJr/SRB2.git
synced 2024-11-16 17:51:31 +00:00
Merge remote-tracking branch 'Nevur/PK3-BackportNext' into PK3-BackportNext
This commit is contained in:
commit
4ac481bcc6
2 changed files with 316 additions and 316 deletions
627
src/w_wad.c
627
src/w_wad.c
|
@ -313,6 +313,299 @@ static void W_InvalidateLumpnumCache(void)
|
||||||
memset(lumpnumcache, 0, sizeof (lumpnumcache));
|
memset(lumpnumcache, 0, sizeof (lumpnumcache));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Detect a file type.
|
||||||
|
* \todo Actually detect the wad/pkzip headers and whatnot, instead of just checking the extensions.
|
||||||
|
*/
|
||||||
|
static restype_t ResourceFileDetect (const char* filename)
|
||||||
|
{
|
||||||
|
if (!stricmp(&filename[strlen(filename) - 4], ".pk3"))
|
||||||
|
return RET_PK3;
|
||||||
|
if (!stricmp(&filename[strlen(filename) - 4], ".soc"))
|
||||||
|
return RET_SOC;
|
||||||
|
if (!stricmp(&filename[strlen(filename) - 4], ".lua"))
|
||||||
|
return RET_LUA;
|
||||||
|
|
||||||
|
return RET_WAD;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Create a 1-lump lumpinfo_t for standalone files.
|
||||||
|
*/
|
||||||
|
static lumpinfo_t* ResGetLumpsStandalone (FILE* handle, UINT16* numlumps, const char* lumpname)
|
||||||
|
{
|
||||||
|
lumpinfo_t* lumpinfo = Z_Calloc(sizeof (*lumpinfo), PU_STATIC, NULL);
|
||||||
|
lumpinfo = Z_Calloc(sizeof (*lumpinfo), PU_STATIC, NULL);
|
||||||
|
lumpinfo->position = 0;
|
||||||
|
fseek(handle, 0, SEEK_END);
|
||||||
|
lumpinfo->size = ftell(handle);
|
||||||
|
fseek(handle, 0, SEEK_SET);
|
||||||
|
strcpy(lumpinfo->name, lumpname);
|
||||||
|
// Allocate the lump's full name.
|
||||||
|
lumpinfo->name2 = Z_Malloc(9 * sizeof(char), PU_STATIC, NULL);
|
||||||
|
strcpy(lumpinfo->name2, lumpname);
|
||||||
|
lumpinfo->name2[8] = '\0';
|
||||||
|
*numlumps = 1;
|
||||||
|
return lumpinfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Create a lumpinfo_t array for a WAD file.
|
||||||
|
*/
|
||||||
|
static lumpinfo_t* ResGetLumpsWad (FILE* handle, UINT16* nlmp, const char* filename)
|
||||||
|
{
|
||||||
|
UINT16 numlumps = *nlmp;
|
||||||
|
lumpinfo_t* lumpinfo;
|
||||||
|
size_t i;
|
||||||
|
INT32 compressed = 0;
|
||||||
|
|
||||||
|
wadinfo_t header;
|
||||||
|
lumpinfo_t *lump_p;
|
||||||
|
filelump_t *fileinfo;
|
||||||
|
void *fileinfov;
|
||||||
|
|
||||||
|
// read the header
|
||||||
|
if (fread(&header, 1, sizeof header, handle) < sizeof header)
|
||||||
|
{
|
||||||
|
CONS_Alert(CONS_ERROR, M_GetText("Can't read wad header because %s\n"), strerror(ferror(handle)));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (memcmp(header.identification, "ZWAD", 4) == 0)
|
||||||
|
compressed = 1;
|
||||||
|
else if (memcmp(header.identification, "IWAD", 4) != 0
|
||||||
|
&& memcmp(header.identification, "PWAD", 4) != 0
|
||||||
|
&& memcmp(header.identification, "SDLL", 4) != 0)
|
||||||
|
{
|
||||||
|
CONS_Alert(CONS_ERROR, M_GetText("Invalid WAD header\n"));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
header.numlumps = LONG(header.numlumps);
|
||||||
|
header.infotableofs = LONG(header.infotableofs);
|
||||||
|
|
||||||
|
// read wad file directory
|
||||||
|
i = header.numlumps * sizeof (*fileinfo);
|
||||||
|
fileinfov = fileinfo = malloc(i);
|
||||||
|
if (fseek(handle, header.infotableofs, SEEK_SET) == -1
|
||||||
|
|| fread(fileinfo, 1, i, handle) < i)
|
||||||
|
{
|
||||||
|
CONS_Alert(CONS_ERROR, M_GetText("Corrupt wadfile directory (%s)\n"), strerror(ferror(handle)));
|
||||||
|
free(fileinfov);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
numlumps = header.numlumps;
|
||||||
|
|
||||||
|
// fill in lumpinfo for this wad
|
||||||
|
lump_p = lumpinfo = Z_Malloc(numlumps * sizeof (*lumpinfo), PU_STATIC, NULL);
|
||||||
|
for (i = 0; i < numlumps; i++, lump_p++, fileinfo++)
|
||||||
|
{
|
||||||
|
lump_p->position = LONG(fileinfo->filepos);
|
||||||
|
lump_p->size = lump_p->disksize = LONG(fileinfo->size);
|
||||||
|
if (compressed) // wad is compressed, lump might be
|
||||||
|
{
|
||||||
|
UINT32 realsize = 0;
|
||||||
|
if (fseek(handle, lump_p->position, SEEK_SET)
|
||||||
|
== -1 || fread(&realsize, 1, sizeof realsize,
|
||||||
|
handle) < sizeof realsize)
|
||||||
|
{
|
||||||
|
I_Error("corrupt compressed file: %s; maybe %s", /// \todo Avoid the bailout?
|
||||||
|
filename, strerror(ferror(handle)));
|
||||||
|
}
|
||||||
|
realsize = LONG(realsize);
|
||||||
|
if (realsize != 0)
|
||||||
|
{
|
||||||
|
lump_p->size = realsize;
|
||||||
|
lump_p->compression = CM_LZF;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lump_p->size -= 4;
|
||||||
|
lump_p->compression = CM_NOCOMPRESSION;
|
||||||
|
}
|
||||||
|
|
||||||
|
lump_p->position += 4;
|
||||||
|
lump_p->disksize -= 4;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
lump_p->compression = CM_NOCOMPRESSION;
|
||||||
|
memset(lump_p->name, 0x00, 9);
|
||||||
|
strncpy(lump_p->name, fileinfo->name, 8);
|
||||||
|
// Allocate the lump's full name.
|
||||||
|
lump_p->name2 = Z_Malloc(9 * sizeof(char), PU_STATIC, NULL);
|
||||||
|
strncpy(lump_p->name2, fileinfo->name, 8);
|
||||||
|
lump_p->name2[8] = '\0';
|
||||||
|
}
|
||||||
|
free(fileinfov);
|
||||||
|
*nlmp = numlumps;
|
||||||
|
return lumpinfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Optimized pattern search in a file.
|
||||||
|
*/
|
||||||
|
static boolean ResFindSignature (FILE* handle, char endPat[], UINT32 startpos)
|
||||||
|
{
|
||||||
|
char *s;
|
||||||
|
int c;
|
||||||
|
|
||||||
|
fseek(handle, startpos, SEEK_SET);
|
||||||
|
s = endPat;
|
||||||
|
while((c = fgetc(handle)) != EOF)
|
||||||
|
{
|
||||||
|
if (*s != c && s > endPat) // No match?
|
||||||
|
s = endPat; // We "reset" the counter by sending the s pointer back to the start of the array.
|
||||||
|
if (*s == c)
|
||||||
|
{
|
||||||
|
s++;
|
||||||
|
if (*s == 0x00) // The array pointer has reached the key char which marks the end. It means we have matched the signature.
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct zend_s
|
||||||
|
{
|
||||||
|
char signature[4];
|
||||||
|
UINT16 diskpos;
|
||||||
|
UINT16 cdirdisk;
|
||||||
|
UINT16 diskentries;
|
||||||
|
UINT16 entries;
|
||||||
|
UINT32 cdirsize;
|
||||||
|
UINT32 cdiroffset;
|
||||||
|
UINT16 commentlen;
|
||||||
|
} ATTRPACK zend_t;
|
||||||
|
|
||||||
|
typedef struct zentry_s
|
||||||
|
{
|
||||||
|
char signature[4];
|
||||||
|
UINT16 version;
|
||||||
|
UINT16 versionneeded;
|
||||||
|
UINT16 flags;
|
||||||
|
UINT16 compression;
|
||||||
|
UINT16 modtime;
|
||||||
|
UINT16 moddate;
|
||||||
|
UINT32 CRC32;
|
||||||
|
UINT32 compsize;
|
||||||
|
UINT32 size;
|
||||||
|
UINT16 namelen;
|
||||||
|
UINT16 xtralen;
|
||||||
|
UINT16 commlen;
|
||||||
|
UINT16 diskstart;
|
||||||
|
UINT16 attrint;
|
||||||
|
UINT32 attrext;
|
||||||
|
UINT32 offset;
|
||||||
|
} ATTRPACK zentry_t;
|
||||||
|
|
||||||
|
typedef struct zlentry_s
|
||||||
|
{
|
||||||
|
char signature[4];
|
||||||
|
UINT16 versionneeded;
|
||||||
|
UINT16 flags;
|
||||||
|
UINT16 compression;
|
||||||
|
UINT16 modtime;
|
||||||
|
UINT16 moddate;
|
||||||
|
UINT32 CRC32;
|
||||||
|
UINT32 compsize;
|
||||||
|
UINT32 size;
|
||||||
|
UINT16 namelen;
|
||||||
|
UINT16 xtralen;
|
||||||
|
} ATTRPACK zlentry_t;
|
||||||
|
|
||||||
|
/** Create a lumpinfo_t array for a PKZip file.
|
||||||
|
*/
|
||||||
|
static lumpinfo_t* ResGetLumpsZip (FILE* handle, UINT16* nlmp)
|
||||||
|
{
|
||||||
|
zend_t zend;
|
||||||
|
zentry_t* zentries;
|
||||||
|
zentry_t* zentry;
|
||||||
|
|
||||||
|
UINT16 numlumps = *nlmp;
|
||||||
|
lumpinfo_t* lumpinfo;
|
||||||
|
lumpinfo_t *lump_p;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
char pat_central[] = {0x50, 0x4b, 0x01, 0x02, 0x00};
|
||||||
|
char pat_end[] = {0x50, 0x4b, 0x05, 0x06, 0x00};
|
||||||
|
|
||||||
|
// Look for central directory end signature near end of file.
|
||||||
|
// Contains entry number (number of lumps), and central directory start offset.
|
||||||
|
fseek(handle, 0, SEEK_END);
|
||||||
|
if (!ResFindSignature(handle, pat_end, max(0, ftell(handle) - (22 + 65536))))
|
||||||
|
{
|
||||||
|
CONS_Alert(CONS_ERROR, "Missing central directory\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
fseek(handle, -4, SEEK_CUR);
|
||||||
|
fread(&zend, 1, sizeof zend, handle);
|
||||||
|
numlumps = zend.entries;
|
||||||
|
|
||||||
|
lump_p = lumpinfo = Z_Malloc(numlumps * sizeof (*lumpinfo), PU_STATIC, NULL);
|
||||||
|
zentry = zentries = malloc(numlumps * sizeof (*zentries));
|
||||||
|
|
||||||
|
fseek(handle, zend.cdiroffset, SEEK_SET);
|
||||||
|
for (i = 0; i < numlumps; i++, zentry++, lump_p++)
|
||||||
|
{
|
||||||
|
char* fullname;
|
||||||
|
char* trimname;
|
||||||
|
char* dotpos;
|
||||||
|
|
||||||
|
fread(zentry, 1, sizeof(zentry_t), handle);
|
||||||
|
if (memcmp(zentry->signature, pat_central, 4))
|
||||||
|
{
|
||||||
|
CONS_Alert(CONS_ERROR, "Central directory is corrupt\n");
|
||||||
|
Z_Free(lumpinfo);
|
||||||
|
free(zentry);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
lump_p->position = zentry->offset + zentry->namelen + zentry->xtralen + sizeof(zlentry_t);
|
||||||
|
lump_p->disksize = zentry->compsize;
|
||||||
|
lump_p->size = zentry->size;
|
||||||
|
|
||||||
|
fullname = malloc(zentry->namelen + 1);
|
||||||
|
fgets(fullname, zentry->namelen + 1, handle);
|
||||||
|
|
||||||
|
// 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 ((dotpos = strrchr(trimname, '.')) == 0)
|
||||||
|
dotpos = fullname + strlen(fullname); // Watch for files without extension.
|
||||||
|
|
||||||
|
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));
|
||||||
|
|
||||||
|
lump_p->name2 = Z_Calloc(zentry->namelen + 1, PU_STATIC, NULL);
|
||||||
|
strncpy(lump_p->name2, fullname, zentry->namelen);
|
||||||
|
|
||||||
|
free(fullname);
|
||||||
|
|
||||||
|
switch(zentry->compression)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
lump_p->compression = CM_NOCOMPRESSION;
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
lump_p->compression = CM_DEFLATE;
|
||||||
|
break;
|
||||||
|
case 14:
|
||||||
|
lump_p->compression = CM_LZF;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
CONS_Alert(CONS_WARNING, "%s: Unsupported compression method\n", fullname);
|
||||||
|
lump_p->compression = CM_UNSUPPORTED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*nlmp = numlumps;
|
||||||
|
return lumpinfo;
|
||||||
|
}
|
||||||
|
|
||||||
// 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
|
||||||
//
|
//
|
||||||
|
@ -330,9 +623,8 @@ UINT16 W_InitFile(const char *filename)
|
||||||
lumpinfo_t *lumpinfo;
|
lumpinfo_t *lumpinfo;
|
||||||
wadfile_t *wadfile;
|
wadfile_t *wadfile;
|
||||||
restype_t type;
|
restype_t type;
|
||||||
UINT16 numlumps;
|
UINT16 numlumps = 0;
|
||||||
size_t i;
|
size_t i;
|
||||||
INT32 compressed = 0;
|
|
||||||
size_t packetsize = 0;
|
size_t packetsize = 0;
|
||||||
serverinfo_pak *dummycheck = NULL;
|
serverinfo_pak *dummycheck = NULL;
|
||||||
UINT8 md5sum[16];
|
UINT8 md5sum[16];
|
||||||
|
@ -393,323 +685,30 @@ UINT16 W_InitFile(const char *filename)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// detect dehacked file with the "soc" extension
|
switch(type = ResourceFileDetect(filename))
|
||||||
if (!stricmp(&filename[strlen(filename) - 4], ".soc"))
|
|
||||||
{
|
{
|
||||||
// This code emulates a wadfile with one lump name "OBJCTCFG"
|
case RET_SOC:
|
||||||
// at position 0 and size of the whole file.
|
lumpinfo = ResGetLumpsStandalone(handle, &numlumps, "OBJCTCFG");
|
||||||
// This allows soc files to be like all wads, copied by network and loaded at the console.
|
break;
|
||||||
type = RET_SOC;
|
|
||||||
|
|
||||||
numlumps = 1;
|
|
||||||
lumpinfo = Z_Calloc(sizeof (*lumpinfo), PU_STATIC, NULL);
|
|
||||||
lumpinfo->position = 0;
|
|
||||||
fseek(handle, 0, SEEK_END);
|
|
||||||
lumpinfo->size = ftell(handle);
|
|
||||||
fseek(handle, 0, SEEK_SET);
|
|
||||||
strcpy(lumpinfo->name, "OBJCTCFG");
|
|
||||||
// Allocate the lump's full name.
|
|
||||||
lumpinfo->name2 = Z_Malloc(9 * sizeof(char), PU_STATIC, NULL);
|
|
||||||
strcpy(lumpinfo->name2, "OBJCTCFG");
|
|
||||||
lumpinfo->name2[8] = '\0';
|
|
||||||
}
|
|
||||||
#ifdef HAVE_BLUA
|
#ifdef HAVE_BLUA
|
||||||
// detect lua script with the "lua" extension
|
case RET_LUA:
|
||||||
else if (!stricmp(&filename[strlen(filename) - 4], ".lua"))
|
lumpinfo = ResGetLumpsStandalone(handle, &numlumps, "LUA_INIT");
|
||||||
{
|
break;
|
||||||
// This code emulates a wadfile with one lump name "LUA_INIT"
|
|
||||||
// at position 0 and size of the whole file.
|
|
||||||
// This allows soc files to be like all wads, copied by network and loaded at the console.
|
|
||||||
type = RET_LUA;
|
|
||||||
|
|
||||||
numlumps = 1;
|
|
||||||
lumpinfo = Z_Calloc(sizeof (*lumpinfo), PU_STATIC, NULL);
|
|
||||||
lumpinfo->position = 0;
|
|
||||||
fseek(handle, 0, SEEK_END);
|
|
||||||
lumpinfo->size = ftell(handle);
|
|
||||||
fseek(handle, 0, SEEK_SET);
|
|
||||||
strcpy(lumpinfo->name, "LUA_INIT");
|
|
||||||
// Allocate the lump's full name.
|
|
||||||
lumpinfo->name2 = Z_Malloc(9 * sizeof(char), PU_STATIC, NULL);
|
|
||||||
strcpy(lumpinfo->name2, "OBJCTCFG");
|
|
||||||
lumpinfo->name2[8] = '\0';
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
else if (!stricmp(&filename[strlen(filename) - 4], ".pk3"))
|
case RET_PK3:
|
||||||
{
|
lumpinfo = ResGetLumpsZip(handle, &numlumps);
|
||||||
char curHeader[4];
|
break;
|
||||||
unsigned long size;
|
case RET_WAD:
|
||||||
char seekPat[] = {0x50, 0x4b, 0x01, 0x02, 0x00};
|
lumpinfo = ResGetLumpsWad(handle, &numlumps, filename);
|
||||||
char endPat[] = {0x50, 0x4b, 0x05, 0x06, 0x00};
|
break;
|
||||||
char *s;
|
default:
|
||||||
int c;
|
CONS_Alert(CONS_ERROR, "Unsupported file format\n");
|
||||||
UINT32 position;
|
|
||||||
boolean matched = false;
|
|
||||||
lumpinfo_t *lump_p;
|
|
||||||
|
|
||||||
type = RET_PK3;
|
|
||||||
|
|
||||||
// Obtain the file's size.
|
|
||||||
fseek(handle, 0, SEEK_END);
|
|
||||||
size = ftell(handle);
|
|
||||||
CONS_Debug(DBG_SETUP, "PK3 size is: %ld\n", size);
|
|
||||||
|
|
||||||
// We must look for the central directory through the file. (Thanks to JTE for this algorithm.)
|
|
||||||
// All of the central directory entry headers have a signature of 0x50 0x4b 0x01 0x02.
|
|
||||||
// The first entry found means the beginning of the central directory.
|
|
||||||
fseek(handle, -min(size, (22 + 65536)), SEEK_CUR);
|
|
||||||
s = endPat;
|
|
||||||
while((c = fgetc(handle)) != EOF)
|
|
||||||
{
|
|
||||||
if (*s != c && s > endPat) // No match?
|
|
||||||
s = endPat; // We "reset" the counter by sending the s pointer back to the start of the array.
|
|
||||||
if (*s == c)
|
|
||||||
{
|
|
||||||
s++;
|
|
||||||
if (*s == 0x00) // The array pointer has reached the key char which marks the end. It means we have matched the signature.
|
|
||||||
{
|
|
||||||
matched = true;
|
|
||||||
CONS_Debug(DBG_SETUP, "Found PK3 central directory at position %ld.\n", ftell(handle));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Error if we couldn't find the central directory at all. It likely means this is not a ZIP/PK3 file.
|
|
||||||
if (matched == false)
|
|
||||||
{
|
|
||||||
CONS_Alert(CONS_ERROR, "No central directory inside PK3! File may be corrupted or incomplete.\n");
|
|
||||||
return INT16_MAX;
|
|
||||||
}
|
|
||||||
|
|
||||||
fseek(handle, 4, SEEK_CUR);
|
|
||||||
fread(&numlumps, 1, 2, handle);
|
|
||||||
fseek(handle, 6, SEEK_CUR);
|
|
||||||
fread(&position, 1, 4, handle);
|
|
||||||
lump_p = lumpinfo = Z_Malloc(numlumps * sizeof (*lumpinfo), PU_STATIC, NULL);
|
|
||||||
fseek(handle, position, SEEK_SET);
|
|
||||||
|
|
||||||
// Since we found the central directory, now we can map our lumpinfo table.
|
|
||||||
// We will look for file headers inside it, until we reach the central directory end signature.
|
|
||||||
// We exactly know what data to expect this time, so now we don't need to do a byte-by-byte search.
|
|
||||||
CONS_Debug(DBG_SETUP, "Now finding central directory file headers...\n");
|
|
||||||
for (i = 0; i < numlumps; i++, lump_p++)
|
|
||||||
{
|
|
||||||
fread(curHeader, 1, 4, handle);
|
|
||||||
|
|
||||||
// We found a central directory entry signature?
|
|
||||||
if (!strncmp(curHeader, seekPat, 3))
|
|
||||||
{
|
|
||||||
// Let's fill in the fields that we actually need.
|
|
||||||
// (Declaring all those vars might not be the optimal way to do this, sorry.)
|
|
||||||
char *eName;
|
|
||||||
int namePos;
|
|
||||||
int nameEnd;
|
|
||||||
unsigned short int eNameLen = 8;
|
|
||||||
unsigned short int eXFieldLen = 0;
|
|
||||||
unsigned short int lNameLen = 0;
|
|
||||||
unsigned short int lXFieldLen = 0;
|
|
||||||
unsigned short int eCommentLen = 0;
|
|
||||||
unsigned short int eCompression = 0;
|
|
||||||
unsigned int eSize = 0;
|
|
||||||
unsigned int eCompSize = 0;
|
|
||||||
unsigned int eLocalHeaderOffset = 0;
|
|
||||||
unsigned long int rememberPos = 0;
|
|
||||||
|
|
||||||
// We get the compression type indicator value.
|
|
||||||
fseek(handle, 6, SEEK_CUR);
|
|
||||||
fread(&eCompression, 1, 2, handle);
|
|
||||||
// Get the size
|
|
||||||
fseek(handle, 8, SEEK_CUR);
|
|
||||||
fread(&eCompSize, 1, 4, handle);
|
|
||||||
fread(&eSize, 1, 4, handle);
|
|
||||||
// We get the variable length fields.
|
|
||||||
fread(&eNameLen, 1, 2, handle);
|
|
||||||
fread(&eXFieldLen, 1, 2, handle);
|
|
||||||
fread(&eCommentLen, 1, 2, handle);
|
|
||||||
fseek(handle, 8, SEEK_CUR);
|
|
||||||
fread(&eLocalHeaderOffset, 1, 4, handle); // Get the offset.
|
|
||||||
|
|
||||||
eName = malloc(sizeof(char)*(eNameLen + 1));
|
|
||||||
fgets(eName, eNameLen + 1, handle);
|
|
||||||
|
|
||||||
// Don't load lump if folder.
|
|
||||||
// if (*(eName + eNameLen - 1) == '/')
|
|
||||||
// continue;
|
|
||||||
|
|
||||||
// We must calculate the position for the actual data.
|
|
||||||
// Why not eLocalHeaderOffset + 30 + eNameLen + eXFieldLen? That's because the extra field and name lengths MAY be different in the local headers.
|
|
||||||
rememberPos = ftell(handle);
|
|
||||||
fseek(handle, eLocalHeaderOffset + 26, SEEK_SET);
|
|
||||||
fread(&lNameLen, 1, 2, handle);
|
|
||||||
fread(&lXFieldLen, 1, 2, handle);
|
|
||||||
lump_p->position = ftell(handle) + lNameLen + lXFieldLen;
|
|
||||||
|
|
||||||
fseek(handle, rememberPos, SEEK_SET); // Let's go back to the central dir.
|
|
||||||
lump_p->disksize = eCompSize;
|
|
||||||
lump_p->size = eSize;
|
|
||||||
|
|
||||||
// We will trim the file's full name so that only the filename is left.
|
|
||||||
namePos = eNameLen - 1;
|
|
||||||
while(namePos--)
|
|
||||||
if(eName[namePos] == '/')
|
|
||||||
break;
|
|
||||||
namePos++;
|
|
||||||
// We will remove the file extension too.
|
|
||||||
nameEnd = 0;
|
|
||||||
while(nameEnd++ < 8)
|
|
||||||
if(eName[namePos + nameEnd] == '.')
|
|
||||||
break;
|
|
||||||
memset(lump_p->name, '\0', 9);
|
|
||||||
strncpy(lump_p->name, eName + namePos, nameEnd);
|
|
||||||
|
|
||||||
lump_p->name2 = Z_Malloc((eNameLen+1)*sizeof(char), PU_STATIC, NULL);
|
|
||||||
strncpy(lump_p->name2, eName, eNameLen);
|
|
||||||
lump_p->name2[eNameLen] = '\0';
|
|
||||||
|
|
||||||
// We set the compression type from what we're supporting so far.
|
|
||||||
switch(eCompression)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
lump_p->compression = CM_NOCOMPRESSION;
|
|
||||||
break;
|
|
||||||
case 8:
|
|
||||||
lump_p->compression = CM_DEFLATE;
|
|
||||||
break;
|
|
||||||
case 14:
|
|
||||||
lump_p->compression = CM_LZF;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
CONS_Alert(CONS_WARNING, "Lump has an unsupported compression type!\n");
|
|
||||||
lump_p->compression = CM_UNSUPPORTED;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
CONS_Debug(DBG_SETUP, "File %s, data begins at: %ld\n", eName, lump_p->position);
|
|
||||||
fseek(handle, eXFieldLen + eCommentLen, SEEK_CUR); // We skip to where we expect the next central directory entry or end marker to be.
|
|
||||||
free(eName);
|
|
||||||
}
|
|
||||||
// We found the central directory end signature?
|
|
||||||
else if (!strncmp(curHeader, endPat, 4))
|
|
||||||
{
|
|
||||||
CONS_Debug(DBG_SETUP, "Central directory end signature found at: %ld\n", ftell(handle));
|
|
||||||
|
|
||||||
/*// We will create a "virtual" marker lump at the very end of lumpinfo for convenience.
|
|
||||||
// This marker will be used by the different lump-seeking (eg. textures, sprites, etc.) in PK3-specific cases in an auxiliary way.
|
|
||||||
lumpinfo = (lumpinfo_t*) Z_Realloc(lumpinfo, (numlumps + 1)*sizeof(*lumpinfo), PU_STATIC, NULL);
|
|
||||||
strcpy(lumpinfo[numlumps].name, "PK3_ENDM\0");
|
|
||||||
lumpinfo[numlumps].name2 = Z_Malloc(14 * sizeof(char), PU_STATIC, NULL);
|
|
||||||
strcpy(lumpinfo[numlumps].name2, "PK3_ENDMARKER\0");
|
|
||||||
lumpinfo[numlumps].position = 0;
|
|
||||||
lumpinfo[numlumps].size = 0;
|
|
||||||
lumpinfo[numlumps].disksize = 0;
|
|
||||||
lumpinfo[numlumps].compression = CM_NOCOMPRESSION;
|
|
||||||
numlumps++;*/
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// ... None of them? We're only expecting either a central directory signature entry or the central directory end signature.
|
|
||||||
// The file may be broken or incomplete...
|
|
||||||
else
|
|
||||||
{
|
|
||||||
CONS_Alert(CONS_WARNING, "Expected central directory header signature, got something else!");
|
|
||||||
return INT16_MAX;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// If we've reached this far, then it means our dynamically stored lumpinfo has to be ready.
|
|
||||||
// Now we finally build our... incorrectly called wadfile.
|
|
||||||
// TODO: Maybe we should give them more generalized names, like resourcefile or resfile or something.
|
|
||||||
// Mostly for clarity and better understanding when reading the code.
|
|
||||||
}
|
}
|
||||||
// assume wad file
|
|
||||||
else
|
if (lumpinfo == 0)
|
||||||
{
|
{
|
||||||
wadinfo_t header;
|
fclose(handle);
|
||||||
lumpinfo_t *lump_p;
|
return INT16_MAX;
|
||||||
filelump_t *fileinfo;
|
|
||||||
void *fileinfov;
|
|
||||||
|
|
||||||
type = RET_WAD;
|
|
||||||
|
|
||||||
// read the header
|
|
||||||
if (fread(&header, 1, sizeof header, handle) < sizeof header)
|
|
||||||
{
|
|
||||||
CONS_Alert(CONS_ERROR, M_GetText("Can't read wad header from %s because %s\n"), filename, strerror(ferror(handle)));
|
|
||||||
if (handle)
|
|
||||||
fclose(handle);
|
|
||||||
return INT16_MAX;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (memcmp(header.identification, "ZWAD", 4) == 0)
|
|
||||||
compressed = 1;
|
|
||||||
else if (memcmp(header.identification, "IWAD", 4) != 0
|
|
||||||
&& memcmp(header.identification, "PWAD", 4) != 0
|
|
||||||
&& memcmp(header.identification, "SDLL", 4) != 0)
|
|
||||||
{
|
|
||||||
CONS_Alert(CONS_ERROR, M_GetText("%s does not have a valid WAD header\n"), filename);
|
|
||||||
if (handle)
|
|
||||||
fclose(handle);
|
|
||||||
return INT16_MAX;
|
|
||||||
}
|
|
||||||
|
|
||||||
header.numlumps = LONG(header.numlumps);
|
|
||||||
header.infotableofs = LONG(header.infotableofs);
|
|
||||||
|
|
||||||
// read wad file directory
|
|
||||||
i = header.numlumps * sizeof (*fileinfo);
|
|
||||||
fileinfov = fileinfo = malloc(i);
|
|
||||||
if (fseek(handle, header.infotableofs, SEEK_SET) == -1
|
|
||||||
|| fread(fileinfo, 1, i, handle) < i)
|
|
||||||
{
|
|
||||||
CONS_Alert(CONS_ERROR, M_GetText("Wadfile directory in %s is corrupted (%s)\n"), filename, strerror(ferror(handle)));
|
|
||||||
free(fileinfov);
|
|
||||||
if (handle)
|
|
||||||
fclose(handle);
|
|
||||||
return INT16_MAX;
|
|
||||||
}
|
|
||||||
|
|
||||||
numlumps = header.numlumps;
|
|
||||||
|
|
||||||
// fill in lumpinfo for this wad
|
|
||||||
lump_p = lumpinfo = Z_Malloc(numlumps * sizeof (*lumpinfo), PU_STATIC, NULL);
|
|
||||||
for (i = 0; i < numlumps; i++, lump_p++, fileinfo++)
|
|
||||||
{
|
|
||||||
lump_p->position = LONG(fileinfo->filepos);
|
|
||||||
lump_p->size = lump_p->disksize = LONG(fileinfo->size);
|
|
||||||
if (compressed) // wad is compressed, lump might be
|
|
||||||
{
|
|
||||||
UINT32 realsize = 0;
|
|
||||||
|
|
||||||
if (fseek(handle, lump_p->position, SEEK_SET)
|
|
||||||
== -1 || fread(&realsize, 1, sizeof realsize,
|
|
||||||
handle) < sizeof realsize)
|
|
||||||
{
|
|
||||||
I_Error("corrupt compressed file: %s; maybe %s",
|
|
||||||
filename, strerror(ferror(handle)));
|
|
||||||
}
|
|
||||||
realsize = LONG(realsize);
|
|
||||||
if (realsize != 0)
|
|
||||||
{
|
|
||||||
lump_p->size = realsize;
|
|
||||||
lump_p->compression = CM_LZF;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
lump_p->size -= 4;
|
|
||||||
lump_p->compression = CM_NOCOMPRESSION;
|
|
||||||
}
|
|
||||||
|
|
||||||
lump_p->position += 4;
|
|
||||||
lump_p->disksize -= 4;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
lump_p->compression = CM_NOCOMPRESSION;
|
|
||||||
memset(lump_p->name, 0x00, 9);
|
|
||||||
strncpy(lump_p->name, fileinfo->name, 8);
|
|
||||||
// Allocate the lump's full name.
|
|
||||||
lump_p->name2 = Z_Malloc(9 * sizeof(char), PU_STATIC, NULL);
|
|
||||||
strncpy(lump_p->name2, fileinfo->name, 8);
|
|
||||||
lump_p->name2[8] = '\0';
|
|
||||||
}
|
|
||||||
free(fileinfov);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
|
@ -60,7 +60,6 @@ typedef struct
|
||||||
char name[9]; // filelump_t name[]
|
char name[9]; // filelump_t name[]
|
||||||
char *name2; // Used by PK3s. Dynamically allocated name.
|
char *name2; // Used by PK3s. Dynamically allocated name.
|
||||||
size_t size; // real (uncompressed) size
|
size_t size; // real (uncompressed) size
|
||||||
INT32 compressed; // i
|
|
||||||
compmethod compression; // lump compression method
|
compmethod compression; // lump compression method
|
||||||
} lumpinfo_t;
|
} lumpinfo_t;
|
||||||
|
|
||||||
|
@ -84,9 +83,11 @@ typedef enum restype
|
||||||
RET_WAD,
|
RET_WAD,
|
||||||
RET_SOC,
|
RET_SOC,
|
||||||
RET_LUA,
|
RET_LUA,
|
||||||
RET_PK3
|
RET_PK3,
|
||||||
|
RET_UNKNOWN,
|
||||||
} restype_t;
|
} restype_t;
|
||||||
|
|
||||||
|
|
||||||
typedef struct wadfile_s
|
typedef struct wadfile_s
|
||||||
{
|
{
|
||||||
char *filename;
|
char *filename;
|
||||||
|
|
Loading…
Reference in a new issue