More PK3 work. Now we're getting somewhere.

-DEFLATE-compressed lumps work properly now.
-All "big" lumps are supported now with the exception of WAD maps.

Notes:
-Compiler spits out a shitload of warnings still.
-Individual lump reading clashes with folders of the same name (see TEXTURES lump, and the Textures/ folder).

Signed-off-by: Nevur <apophycens@gmail.com>
This commit is contained in:
Nevur 2017-05-07 12:30:06 +02:00
parent 8ef6d6fd9e
commit ea2846394e
4 changed files with 152 additions and 77 deletions

View file

@ -3105,9 +3105,7 @@ boolean P_AddWadFile(const char *wadfilename, char **firstmapname)
// UINT16 flaPos, flaNum = 0; // UINT16 flaPos, flaNum = 0;
// UINT16 mapPos, mapNum = 0; // UINT16 mapPos, mapNum = 0;
if ((numlumps = W_InitFile(wadfilename)) == INT16_MAX)
if ((numlumps = W_LoadWadFile(wadfilename)) == INT16_MAX)
{ {
CONS_Printf(M_GetText("Errors occured while loading %s; not added.\n"), wadfilename); CONS_Printf(M_GetText("Errors occured while loading %s; not added.\n"), wadfilename);
return false; return false;
@ -3126,7 +3124,7 @@ boolean P_AddWadFile(const char *wadfilename, char **firstmapname)
{ {
lumpinfo++; lumpinfo++;
*start = ++i; *start = ++i;
for (i; i < numlumps; i++, lumpinfo++) for (; i < numlumps; i++, lumpinfo++)
{ {
if (strnicmp(lumpinfo->name2, folName, strlen(folName))) if (strnicmp(lumpinfo->name2, folName, strlen(folName)))
{ {
@ -3172,6 +3170,8 @@ boolean P_AddWadFile(const char *wadfilename, char **firstmapname)
R_LoadSpritsRange(wadnum, sprPos, sprNum); R_LoadSpritsRange(wadnum, sprPos, sprNum);
if (texNum) // Textures. TODO: R_LoadTextures() does the folder positioning once again. New function maybe? if (texNum) // Textures. TODO: R_LoadTextures() does the folder positioning once again. New function maybe?
R_LoadTextures(); R_LoadTextures();
// if (mapNum) // Maps. TODO: Actually implement the map WAD loading code, lulz.
// P_LoadWadMapRange();
} }
break; break;
default: default:

View file

@ -571,13 +571,14 @@ void R_LoadTextures(void)
{ {
texstart = W_CheckNumForFullNamePK3("textures/", (UINT16)w, 0) + 1; texstart = W_CheckNumForFullNamePK3("textures/", (UINT16)w, 0) + 1;
texend = W_CheckNumForFolderEndPK3("textures/", (UINT16)w, texstart); texend = W_CheckNumForFolderEndPK3("textures/", (UINT16)w, texstart);
texturesLumpPos = W_CheckNumForFullNamePK3("textures", (UINT16)w, 0);
} }
else else
{ {
texstart = W_CheckNumForNamePwad(TX_START, (UINT16)w, 0) + 1; texstart = W_CheckNumForNamePwad(TX_START, (UINT16)w, 0) + 1;
texend = W_CheckNumForNamePwad(TX_END, (UINT16)w, 0); texend = W_CheckNumForNamePwad(TX_END, (UINT16)w, 0);
texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, 0);
} }
texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, 0);
if (texturesLumpPos != INT16_MAX) if (texturesLumpPos != INT16_MAX)
{ {
@ -1190,12 +1191,64 @@ static void R_InitExtraColormaps(void)
CONS_Printf(M_GetText("Number of Extra Colormaps: %s\n"), sizeu1(numcolormaplumps)); CONS_Printf(M_GetText("Number of Extra Colormaps: %s\n"), sizeu1(numcolormaplumps));
} }
// 12/14/14 -- only take flats in F_START/F_END // Search for flat name through all
lumpnum_t R_GetFlatNumForName(const char *name) lumpnum_t R_GetFlatNumForName(const char *name)
{ {
lumpnum_t lump = W_CheckNumForNameInBlock(name, "F_START", "F_END"); INT32 i;
if (lump == LUMPERROR) lumpnum_t lump;
lump = W_CheckNumForNameInBlock(name, "FF_START", "FF_END"); // deutex, some other old things lumpnum_t start;
lumpnum_t end;
// Scan wad files backwards so patched flats take preference.
for (i = numwadfiles - 1; i >= 0; i--)
{
// WAD type? use markers.
if (wadfiles[i]->type == RET_WAD)
{
// Find the ranges to work with.
start = W_CheckNumForNamePwad("F_START", (UINT16)i, 0);
if (start == INT16_MAX)
{
start = W_CheckNumForNamePwad("FF_START", (UINT16)i, 0);
if (start == INT16_MAX)
{
continue;
}
else
{
end = W_CheckNumForNamePwad("FF_END", (UINT16)i, start);
if (end == INT16_MAX)
{
continue;
}
}
}
else
{
end = W_CheckNumForNamePwad("F_END", (UINT16)i, start);
if (end == INT16_MAX)
continue;
}
}
else if (wadfiles[i]->type == RET_PK3)
{
start = W_CheckNumForFullNamePK3("Flats/", i, 0);
if (start == INT16_MAX)
continue;
end = W_CheckNumForFolderEndPK3("Flats/", i, start);
if (end == INT16_MAX)
continue;
}
// Now find lump with specified name in that range.
lump = W_CheckNumForNamePwad(name, (UINT16)i, start);
if (lump < end)
{
lump += (i<<16); // found it, in our constraints
break;
}
lump = LUMPERROR;
}
if (lump == LUMPERROR) if (lump == LUMPERROR)
{ {
if (strcmp(name, SKYFLATNAME)) if (strcmp(name, SKYFLATNAME))

View file

@ -291,7 +291,7 @@ static void W_InvalidateLumpnumCache(void)
// //
// Can now load dehacked files (.soc) // Can now load dehacked files (.soc)
// //
UINT16 W_LoadWadFile(const char *filename) UINT16 W_InitFile(const char *filename)
{ {
FILE *handle; FILE *handle;
lumpinfo_t *lumpinfo; lumpinfo_t *lumpinfo;
@ -412,12 +412,11 @@ UINT16 W_LoadWadFile(const char *filename)
numlumps = 0; numlumps = 0;
type = RET_PK3; type = RET_PK3;
CONS_Alert(CONS_NOTICE, "PK3 file detected.\n");
// Obtain the file's size. // Obtain the file's size.
fseek(handle, 0, SEEK_END); fseek(handle, 0, SEEK_END);
size = ftell(handle); size = ftell(handle);
CONS_Printf("PK3 size is: %ld\n", size); CONS_Debug(DBG_SETUP, "PK3 size is: %ld\n", size);
// We must look for the central directory through the file. // We must look for the central directory through the file.
// All of the central directory entry headers have a signature of 0x50 0x4b 0x01 0x02. // All of the central directory entry headers have a signature of 0x50 0x4b 0x01 0x02.
@ -435,7 +434,7 @@ UINT16 W_LoadWadFile(const char *filename)
{ {
matched = TRUE; matched = TRUE;
fseek(handle, -4, SEEK_CUR); fseek(handle, -4, SEEK_CUR);
CONS_Printf("Found PK3 central directory at position %ld.\n", ftell(handle)); CONS_Debug(DBG_SETUP, "Found PK3 central directory at position %ld.\n", ftell(handle));
break; break;
} }
} }
@ -451,7 +450,7 @@ UINT16 W_LoadWadFile(const char *filename)
// Since we found the central directory, now we can map our lumpinfo table. // 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 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. // We exactly know what data to expect this time, so now we don't need to do a byte-by-byte search.
CONS_Printf("Now finding central directory file headers...\n"); CONS_Debug(DBG_SETUP, "Now finding central directory file headers...\n");
while(ftell(handle) < size - 4) // Make sure we don't go past the file size! while(ftell(handle) < size - 4) // Make sure we don't go past the file size!
{ {
fread(curHeader, 1, 4, handle); fread(curHeader, 1, 4, handle);
@ -477,10 +476,10 @@ UINT16 W_LoadWadFile(const char *filename)
// We get the compression type indicator value. // We get the compression type indicator value.
fseek(handle, 6, SEEK_CUR); fseek(handle, 6, SEEK_CUR);
fread(&eCompression, 1, 2, handle); fread(&eCompression, 1, 2, handle);
// Get the // Get the size
fseek(handle, 8, SEEK_CUR); fseek(handle, 8, SEEK_CUR);
fread(&eSize, 1, 4, handle);
fread(&eCompSize, 1, 4, handle); fread(&eCompSize, 1, 4, handle);
fread(&eSize, 1, 4, handle);
// We get the variable length fields. // We get the variable length fields.
fread(&eNameLen, 1, 2, handle); fread(&eNameLen, 1, 2, handle);
fread(&eXFieldLen, 1, 2, handle); fread(&eXFieldLen, 1, 2, handle);
@ -490,7 +489,6 @@ UINT16 W_LoadWadFile(const char *filename)
eName = malloc(sizeof(char)*(eNameLen + 1)); eName = malloc(sizeof(char)*(eNameLen + 1));
fgets(eName, eNameLen + 1, handle); fgets(eName, eNameLen + 1, handle);
CONS_Printf("File %s at: %ld\n", eName, ftell(handle));
if (numlumps == 0) // First lump? Let's allocate the first lumpinfo block. if (numlumps == 0) // First lump? Let's allocate the first lumpinfo block.
lumpinfo = Z_Malloc(sizeof(*lumpinfo), PU_STATIC, NULL); lumpinfo = Z_Malloc(sizeof(*lumpinfo), PU_STATIC, NULL);
else // Otherwise, reallocate and increase by 1. Might not be optimal, though... else // Otherwise, reallocate and increase by 1. Might not be optimal, though...
@ -541,6 +539,7 @@ UINT16 W_LoadWadFile(const char *filename)
lumpinfo[numlumps].compression = CM_UNSUPPORTED; lumpinfo[numlumps].compression = CM_UNSUPPORTED;
break; break;
} }
CONS_Debug(DBG_SETUP, "File %s, data begins at: %ld\n", eName, lumpinfo[numlumps].position);
fseek(handle, eXFieldLen + eCommentLen, SEEK_CUR); // We skip to where we expect the next central directory entry or end marker to be. fseek(handle, eXFieldLen + eCommentLen, SEEK_CUR); // We skip to where we expect the next central directory entry or end marker to be.
numlumps++; numlumps++;
free(eName); free(eName);
@ -548,7 +547,7 @@ UINT16 W_LoadWadFile(const char *filename)
// We found the central directory end signature? // We found the central directory end signature?
else if (!strncmp(curHeader, endPat, 4)) else if (!strncmp(curHeader, endPat, 4))
{ {
CONS_Printf("Central directory end signature found at: %ld\n", ftell(handle)); 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. // 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. // This marker will be used by the different lump-seeking (eg. textures, sprites, etc.) in PK3-specific cases in an auxiliary way.
@ -760,7 +759,7 @@ INT32 W_InitMultipleFiles(char **filenames)
for (; *filenames; filenames++) for (; *filenames; filenames++)
{ {
//CONS_Debug(DBG_SETUP, "Loading %s\n", *filenames); //CONS_Debug(DBG_SETUP, "Loading %s\n", *filenames);
rc &= (W_LoadWadFile(*filenames) != INT16_MAX) ? 1 : 0; rc &= (W_InitFile(*filenames) != INT16_MAX) ? 1 : 0;
} }
if (!numwadfiles) if (!numwadfiles)
@ -850,8 +849,6 @@ UINT16 W_CheckNumForFolderEndPK3(const char *name, UINT16 wad, UINT16 startlump)
if (strnicmp(name, lump_p->name2, strlen(name))) if (strnicmp(name, lump_p->name2, strlen(name)))
break; break;
} }
// Not found at all?
CONS_Printf("W_CheckNumForFolderEndPK3: Folder %s end at %d.\n", name, i);
return i; return i;
} }
@ -865,7 +862,6 @@ UINT16 W_CheckNumForFullNamePK3(const char *name, UINT16 wad, UINT16 startlump)
{ {
if (!strnicmp(name, lump_p->name2, strlen(name))) if (!strnicmp(name, lump_p->name2, strlen(name)))
{ {
CONS_Printf("W_CheckNumForNamePK3: Found %s at %d.\n", name, i);
return i; return i;
} }
} }
@ -943,15 +939,20 @@ lumpnum_t W_CheckNumForNameInBlock(const char *name, const char *blockstart, con
// scan wad files backwards so patch lump files take precedence // scan wad files backwards so patch lump files take precedence
for (i = numwadfiles - 1; i >= 0; i--) for (i = numwadfiles - 1; i >= 0; i--)
{ {
bsid = W_CheckNumForNamePwad(blockstart,(UINT16)i,0); if (wadfiles[i]->type == RET_WAD)
if (bsid == INT16_MAX) {
continue; // block doesn't exist, keep going bsid = W_CheckNumForNamePwad(blockstart, (UINT16)i, 0);
beid = W_CheckNumForNamePwad(blockend,(UINT16)i,0); if (bsid == INT16_MAX)
// if block end doesn't exist, just search through everything continue; // Start block doesn't exist?
beid = W_CheckNumForNamePwad(blockend, (UINT16)i, 0);
if (beid == INT16_MAX)
continue; // End block doesn't exist?
check = W_CheckNumForNamePwad(name, (UINT16)i, bsid);
if (check < beid)
return (i<<16)+check; // found it, in our constraints
}
check = W_CheckNumForNamePwad(name,(UINT16)i,bsid);
if (check < beid)
return (i<<16)+check; // found it, in our constraints
} }
return LUMPERROR; return LUMPERROR;
} }
@ -988,6 +989,31 @@ size_t W_LumpLength(lumpnum_t lumpnum)
return W_LumpLengthPwad(WADFILENUM(lumpnum),LUMPNUM(lumpnum)); return W_LumpLengthPwad(WADFILENUM(lumpnum),LUMPNUM(lumpnum));
} }
/* report a zlib or i/o error */
void zerr(int ret)
{
CONS_Printf("zpipe: ", stderr);
switch (ret) {
case Z_ERRNO:
if (ferror(stdin))
CONS_Printf("error reading stdin\n", stderr);
if (ferror(stdout))
CONS_Printf("error writing stdout\n", stderr);
break;
case Z_STREAM_ERROR:
CONS_Printf("invalid compression level\n", stderr);
break;
case Z_DATA_ERROR:
CONS_Printf("invalid or incomplete deflate data\n", stderr);
break;
case Z_MEM_ERROR:
CONS_Printf("out of memory\n", stderr);
break;
case Z_VERSION_ERROR:
CONS_Printf("zlib version mismatch!\n", stderr);
}
}
/** Reads bytes from the head of a lump. /** Reads bytes from the head of a lump.
* Note: If the lump is compressed, the whole thing has to be read anyway. * Note: If the lump is compressed, the whole thing has to be read anyway.
* *
@ -1069,59 +1095,55 @@ size_t W_ReadLumpHeaderPwad(UINT16 wad, UINT16 lump, void *dest, size_t size, si
} }
case CM_DEFLATE: // Is it compressed via DEFLATE? Very common in ZIPs/PK3s, also what most doom-related editors support. case CM_DEFLATE: // Is it compressed via DEFLATE? Very common in ZIPs/PK3s, also what most doom-related editors support.
{ {
int ret; char *rawData; // The lump's raw data.
unsigned have; char *decData; // Lump's decompressed real data.
z_stream strm;
unsigned char in[16384]; int zErr; // Helper var.
unsigned char out[16384]; z_stream strm;
unsigned long rawSize = l->disksize;
unsigned long decSize = l->size;
rawData = Z_Malloc(rawSize, PU_STATIC, NULL);
decData = Z_Malloc(decSize, PU_STATIC, NULL);
if (fread(rawData, 1, rawSize, handle) < rawSize)
I_Error("wad %d, lump %d: cannot read compressed data", wad, lump);
/* allocate inflate state */
strm.zalloc = Z_NULL; strm.zalloc = Z_NULL;
strm.zfree = Z_NULL; strm.zfree = Z_NULL;
strm.opaque = Z_NULL; strm.opaque = Z_NULL;
strm.avail_in = 0;
strm.next_in = Z_NULL;
ret = inflateInit(&strm);
if (ret != Z_OK)
return ret;
/* decompress until deflate stream ends or end of file */ strm.total_in = strm.avail_in = rawSize;
do { strm.total_out = strm.avail_out = decSize;
strm.avail_in = fread(in, 1, 16384, handle);
if (ferror(handle)) { strm.next_in = rawData;
(void)inflateEnd(&strm); strm.next_out = decData;
return Z_ERRNO;
zErr = inflateInit2(&strm, -15);
if (zErr == Z_OK)
{
zErr = inflate(&strm, Z_FINISH);
if (zErr == Z_STREAM_END)
{
M_Memcpy(dest, decData, size);
} }
if (strm.avail_in == 0) else
break; {
strm.next_in = in; size = 0;
zerr(zErr);
(void)inflateEnd(&strm);
}
}
else
{
CONS_Printf("whopet\n");
size = 0;
zerr(zErr);
}
/* run inflate() on input until output buffer not full */ Z_Free(rawData);
do { Z_Free(decData);
strm.avail_out = 16384;
strm.next_out = out;
ret = inflate(&strm, Z_NO_FLUSH);
//assert(ret != Z_STREAM_ERROR); /* state not clobbered */
switch (ret) {
case Z_NEED_DICT:
ret = Z_DATA_ERROR; /* and fall through */
case Z_DATA_ERROR:
case Z_MEM_ERROR:
(void)inflateEnd(&strm);
return ret;
}
have = 16384 - strm.avail_out;
memcpy(dest, out, have);
} while (strm.avail_out == 0);
/* done when inflate() says it's done */
} while (ret != Z_STREAM_END);
/* clean up and return */
(void)inflateEnd(&strm);
return size; return size;
} }
default: default:

View file

@ -43,7 +43,7 @@ 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[]
char *name2; // 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 INT32 compressed; // i
enum compmethod compression; // lump compression method enum compmethod compression; // lump compression method
@ -94,7 +94,7 @@ void W_Shutdown(void);
// Opens a WAD file. Returns the FILE * handle for the file, or NULL if not found or could not be opened // Opens a WAD file. Returns the FILE * handle for the file, or NULL if not found or could not be opened
FILE *W_OpenWadFile(const char **filename, boolean useerrors); FILE *W_OpenWadFile(const char **filename, boolean useerrors);
// Load and add a wadfile to the active wad files, returns numbers of lumps, INT16_MAX on error // Load and add a wadfile to the active wad files, returns numbers of lumps, INT16_MAX on error
UINT16 W_LoadWadFile(const char *filename); UINT16 W_InitFile(const char *filename);
#ifdef DELFILE #ifdef DELFILE
void W_UnloadWadFile(UINT16 num); void W_UnloadWadFile(UINT16 num);
#endif #endif