Merge branch 'PK3-Backport' into 'PK3-BackportNext'

Pk3 backport

See merge request Nev3r/SRB2!1
This commit is contained in:
Nev3r 2018-11-24 06:02:19 -05:00
commit 6f5e3d42ff
12 changed files with 1056 additions and 332 deletions

View file

@ -1623,6 +1623,8 @@ static void SendAskInfo(INT32 node, boolean viams)
serverelem_t serverlist[MAXSERVERLIST];
UINT32 serverlistcount = 0;
#define FORCECLOSE 0x8000
static void SL_ClearServerList(INT32 connectedserver)
{
UINT32 i;
@ -1630,7 +1632,7 @@ static void SL_ClearServerList(INT32 connectedserver)
for (i = 0; i < serverlistcount; i++)
if (connectedserver != serverlist[i].node)
{
Net_CloseConnection(serverlist[i].node);
Net_CloseConnection(serverlist[i].node|FORCECLOSE);
serverlist[i].node = 0;
}
serverlistcount = 0;
@ -1712,12 +1714,25 @@ void CL_UpdateServerList(boolean internetsearch, INT32 room)
// Make sure MS version matches our own, to
// thwart nefarious servers who lie to the MS.
if(strcmp(version, server_list[i].version) == 0)
if (strcmp(version, server_list[i].version) == 0)
{
INT32 node = I_NetMakeNodewPort(server_list[i].ip, server_list[i].port);
if (node == -1)
break; // no more node free
SendAskInfo(node, true);
// Force close the connection so that servers can't eat
// up nodes forever if we never get a reply back from them
// (usually when they've not forwarded their ports).
//
// Don't worry, we'll get in contact with the working
// servers again when they send SERVERINFO to us later!
//
// (Note: as a side effect this probably means every
// server in the list will probably be using the same node (e.g. node 1),
// not that it matters which nodes they use when
// the connections are closed afterwards anyway)
// -- Monster Iestyn 12/11/18
Net_CloseConnection(node|FORCECLOSE);
}
}
}

View file

@ -3022,7 +3022,7 @@ static void Command_Addfile(void)
// Add file on your client directly if it is trivial, or you aren't in a netgame.
if (!(netgame || multiplayer) || musiconly)
{
P_AddWadFile(fn, NULL);
P_AddWadFile(fn);
return;
}
@ -3254,7 +3254,7 @@ static void Got_Addfilecmd(UINT8 **cp, INT32 playernum)
ncs = findfile(filename,md5sum,true);
if (ncs != FS_FOUND || !P_AddWadFile(filename, NULL))
if (ncs != FS_FOUND || !P_AddWadFile(filename))
{
Command_ExitGame_f();
if (ncs == FS_FOUND)

View file

@ -444,7 +444,7 @@ void CL_LoadServerFiles(void)
continue; // Already loaded
else if (fileneeded[i].status == FS_FOUND)
{
P_AddWadFile(fileneeded[i].filename, NULL);
P_AddWadFile(fileneeded[i].filename);
G_SetGameModified(true);
fileneeded[i].status = FS_OPEN;
}
@ -463,7 +463,7 @@ void CL_LoadServerFiles(void)
fileneeded[i].filename);
// Okay, NOW we know it's safe. Whew.
P_AddWadFile(fileneeded[i].filename, NULL);
P_AddWadFile(fileneeded[i].filename);
if (fileneeded[i].important)
G_SetGameModified(true);
fileneeded[i].status = FS_OPEN;

View file

@ -173,6 +173,7 @@ static inline void LUA_LoadFile(MYFILE *f, char *name)
LUA_ClearState();
lua_pushinteger(gL, f->wad);
lua_setfield(gL, LUA_REGISTRYINDEX, "WAD");
if (luaL_loadbuffer(gL, f->data, f->size, va("@%s",name)) || lua_pcall(gL, 0, 0, 0)) {
CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL,-1));
lua_pop(gL,1);
@ -185,21 +186,24 @@ void LUA_LoadLump(UINT16 wad, UINT16 lump)
{
MYFILE f;
char *name;
size_t len;
f.wad = wad;
f.size = W_LumpLengthPwad(wad, lump);
f.data = Z_Malloc(f.size, PU_LUA, NULL);
W_ReadLumpPwad(wad, lump, f.data);
f.curpos = f.data;
len = strlen(wadfiles[wad]->filename);
name = malloc(len+10);
strcpy(name, wadfiles[wad]->filename);
if (!fasticmp(&name[len - 4], ".lua")) {
// If it's not a .lua file, copy the lump name in too.
name[len] = '|';
M_Memcpy(name+len+1, wadfiles[wad]->lumpinfo[lump].name, 8);
name[len+9] = '\0';
if (wadfiles[wad]->type == RET_LUA)
{
name = malloc(strlen(wadfiles[wad]->filename)+1);
strcpy(name, wadfiles[wad]->filename);
}
else // If it's not a .lua file, copy the lump name in too.
{
lumpinfo_t *lump_p = &wadfiles[wad]->lumpinfo[lump];
size_t length = strlen(wadfiles[wad]->filename) + 1 + strlen(lump_p->name2); // length of file name, '|', and lump name
name = malloc(length + 1);
sprintf(name, "%s|%s", wadfiles[wad]->filename, lump_p->name2);
name[length] = '\0';
}
LUA_LoadFile(&f, name);

View file

@ -489,16 +489,34 @@ static void P_NetArchiveWorld(void)
UINT8 *put;
// reload the map just to see difference
const mapsector_t *ms;
const mapsidedef_t *msd;
const maplinedef_t *mld;
mapsector_t *ms;
mapsidedef_t *msd;
maplinedef_t *mld;
const sector_t *ss = sectors;
UINT8 diff, diff2;
WRITEUINT32(save_p, ARCHIVEBLOCK_WORLD);
put = save_p;
ms = W_CacheLumpNum(lastloadedmaplumpnum+ML_SECTORS, PU_CACHE);
if (W_IsLumpWad(lastloadedmaplumpnum)) // welp it's a map wad in a pk3
{ // HACK: Open wad file rather quickly so we can get the data from the relevant lumps
UINT8 *wadData = W_CacheLumpNum(lastloadedmaplumpnum, PU_STATIC);
filelump_t *fileinfo = (filelump_t *)(wadData + ((wadinfo_t *)wadData)->infotableofs);
#define retrieve_mapdata(d, f)\
d = Z_Malloc((f)->size, PU_CACHE, NULL); \
M_Memcpy(d, wadData + (f)->filepos, (f)->size)
retrieve_mapdata(ms, fileinfo + ML_SECTORS);
retrieve_mapdata(mld, fileinfo + ML_LINEDEFS);
retrieve_mapdata(msd, fileinfo + ML_SIDEDEFS);
#undef retrieve_mapdata
Z_Free(wadData); // we're done with this now
}
else // phew it's just a WAD
{
ms = W_CacheLumpNum(lastloadedmaplumpnum+ML_SECTORS, PU_CACHE);
mld = W_CacheLumpNum(lastloadedmaplumpnum+ML_LINEDEFS, PU_CACHE);
msd = W_CacheLumpNum(lastloadedmaplumpnum+ML_SIDEDEFS, PU_CACHE);
}
for (i = 0; i < numsectors; i++, ss++, ms++)
{

View file

@ -348,16 +348,13 @@ UINT32 P_GetScoreForGrade(INT16 map, UINT8 mare, UINT8 grade)
* \param lump VERTEXES lump number.
* \sa ML_VERTEXES
*/
static inline void P_LoadVertexes(lumpnum_t lumpnum)
static inline void P_LoadRawVertexes(UINT8 *data, size_t i)
{
UINT8 *data;
size_t i;
mapvertex_t *ml;
vertex_t *li;
// Determine number of lumps:
// total lump length / vertex record length.
numvertexes = W_LumpLength(lumpnum) / sizeof (mapvertex_t);
numvertexes = i / sizeof (mapvertex_t);
if (numvertexes <= 0)
I_Error("Level has no vertices"); // instead of crashing
@ -365,9 +362,6 @@ static inline void P_LoadVertexes(lumpnum_t lumpnum)
// Allocate zone memory for buffer.
vertexes = Z_Calloc(numvertexes * sizeof (*vertexes), PU_LEVEL, NULL);
// Load data into cache.
data = W_CacheLumpNum(lumpnum, PU_STATIC);
ml = (mapvertex_t *)data;
li = vertexes;
@ -377,11 +371,16 @@ static inline void P_LoadVertexes(lumpnum_t lumpnum)
li->x = SHORT(ml->x)<<FRACBITS;
li->y = SHORT(ml->y)<<FRACBITS;
}
}
// Free buffer memory.
static inline void P_LoadVertexes(lumpnum_t lumpnum)
{
UINT8 *data = W_CacheLumpNum(lumpnum, PU_STATIC);
P_LoadRawVertexes(data, W_LumpLength(lumpnum));
Z_Free(data);
}
//
// Computes the line length in fracunits, the OpenGL render needs this
//
@ -421,20 +420,17 @@ static inline float P_SegLengthf(seg_t *seg)
* \param lump Lump number of the SEGS resource.
* \sa ::ML_SEGS
*/
static void P_LoadSegs(lumpnum_t lumpnum)
static void P_LoadRawSegs(UINT8 *data, size_t i)
{
UINT8 *data;
size_t i;
INT32 linedef, side;
mapseg_t *ml;
seg_t *li;
line_t *ldef;
numsegs = W_LumpLength(lumpnum) / sizeof (mapseg_t);
numsegs = i / sizeof (mapseg_t);
if (numsegs <= 0)
I_Error("Level has no segs"); // instead of crashing
segs = Z_Calloc(numsegs * sizeof (*segs), PU_LEVEL, NULL);
data = W_CacheLumpNum(lumpnum, PU_STATIC);
ml = (mapseg_t *)data;
li = segs;
@ -470,27 +466,30 @@ static void P_LoadSegs(lumpnum_t lumpnum)
li->numlights = 0;
li->rlights = NULL;
}
}
static void P_LoadSegs(lumpnum_t lumpnum)
{
UINT8 *data = W_CacheLumpNum(lumpnum, PU_STATIC);
P_LoadRawSegs(data, W_LumpLength(lumpnum));
Z_Free(data);
}
/** Loads the SSECTORS resource from a level.
*
* \param lump Lump number of the SSECTORS resource.
* \sa ::ML_SSECTORS
*/
static inline void P_LoadSubsectors(lumpnum_t lumpnum)
static inline void P_LoadRawSubsectors(void *data, size_t i)
{
void *data;
size_t i;
mapsubsector_t *ms;
subsector_t *ss;
numsubsectors = W_LumpLength(lumpnum) / sizeof (mapsubsector_t);
numsubsectors = i / sizeof (mapsubsector_t);
if (numsubsectors <= 0)
I_Error("Level has no subsectors (did you forget to run it through a nodesbuilder?)");
ss = subsectors = Z_Calloc(numsubsectors * sizeof (*subsectors), PU_LEVEL, NULL);
data = W_CacheLumpNum(lumpnum,PU_STATIC);
ms = (mapsubsector_t *)data;
@ -504,7 +503,12 @@ static inline void P_LoadSubsectors(lumpnum_t lumpnum)
#endif
ss->validcount = 0;
}
}
static void P_LoadSubsectors(lumpnum_t lumpnum)
{
UINT8 *data = W_CacheLumpNum(lumpnum, PU_STATIC);
P_LoadRawSubsectors(data, W_LumpLength(lumpnum));
Z_Free(data);
}
@ -638,29 +642,31 @@ INT32 P_CheckLevelFlat(const char *flatname)
return (INT32)i;
}
static void P_LoadSectors(lumpnum_t lumpnum)
// Sets up the ingame sectors structures.
// Lumpnum is the lumpnum of a SECTORS lump.
static void P_LoadRawSectors(UINT8 *data, size_t i)
{
UINT8 *data;
size_t i;
mapsector_t *ms;
sector_t *ss;
levelflat_t *foundflats;
numsectors = W_LumpLength(lumpnum) / sizeof (mapsector_t);
// We count how many sectors we got.
numsectors = i / sizeof (mapsector_t);
if (numsectors <= 0)
I_Error("Level has no sectors");
// Allocate as much memory as we need into the global sectors table.
sectors = Z_Calloc(numsectors*sizeof (*sectors), PU_LEVEL, NULL);
data = W_CacheLumpNum(lumpnum,PU_STATIC);
//Fab : FIXME: allocate for whatever number of flats
// 512 different flats per level should be plenty
// Allocate a big chunk of memory as big as our MAXLEVELFLATS limit.
//Fab : FIXME: allocate for whatever number of flats - 512 different flats per level should be plenty
foundflats = calloc(MAXLEVELFLATS, sizeof (*foundflats));
if (foundflats == NULL)
I_Error("Ran out of memory while loading sectors\n");
numlevelflats = 0;
// For each counted sector, copy the sector raw data from our cache pointer ms, to the global table pointer ss.
ms = (mapsector_t *)data;
ss = sectors;
for (i = 0; i < numsectors; i++, ss++, ms++)
@ -668,9 +674,6 @@ static void P_LoadSectors(lumpnum_t lumpnum)
ss->floorheight = SHORT(ms->floorheight)<<FRACBITS;
ss->ceilingheight = SHORT(ms->ceilingheight)<<FRACBITS;
//
// flats
//
ss->floorpic = P_AddLevelFlat(ms->floorpic, foundflats);
ss->ceilingpic = P_AddLevelFlat(ms->ceilingpic, foundflats);
@ -735,8 +738,6 @@ static void P_LoadSectors(lumpnum_t lumpnum)
#endif // ----- end special tricks -----
}
Z_Free(data);
// set the sky flat num
skyflatnum = P_AddLevelFlat(SKYFLATNAME, foundflats);
@ -748,22 +749,26 @@ static void P_LoadSectors(lumpnum_t lumpnum)
P_SetupLevelFlatAnims();
}
static void P_LoadSectors(lumpnum_t lumpnum)
{
UINT8 *data = W_CacheLumpNum(lumpnum, PU_STATIC);
P_LoadRawSectors(data, W_LumpLength(lumpnum));
Z_Free(data);
}
//
// P_LoadNodes
//
static void P_LoadNodes(lumpnum_t lumpnum)
static void P_LoadRawNodes(UINT8 *data, size_t i)
{
UINT8 *data;
size_t i;
UINT8 j, k;
mapnode_t *mn;
node_t *no;
numnodes = W_LumpLength(lumpnum) / sizeof (mapnode_t);
numnodes = i / sizeof (mapnode_t);
if (numnodes <= 0)
I_Error("Level has no nodes");
nodes = Z_Calloc(numnodes * sizeof (*nodes), PU_LEVEL, NULL);
data = W_CacheLumpNum(lumpnum, PU_STATIC);
mn = (mapnode_t *)data;
no = nodes;
@ -781,7 +786,12 @@ static void P_LoadNodes(lumpnum_t lumpnum)
no->bbox[j][k] = SHORT(mn->bbox[j][k])<<FRACBITS;
}
}
}
static void P_LoadNodes(lumpnum_t lumpnum)
{
UINT8 *data = W_CacheLumpNum(lumpnum, PU_STATIC);
P_LoadRawNodes(data, W_LumpLength(lumpnum));
Z_Free(data);
}
@ -916,18 +926,16 @@ void P_ScanThings(INT16 mapnum, INT16 wadnum, INT16 lumpnum)
//
// P_LoadThings
//
static void P_PrepareThings(lumpnum_t lumpnum)
{
size_t i;
mapthing_t *mt;
UINT8 *data, *datastart;
nummapthings = W_LumpLength(lumpnum) / (5 * sizeof (INT16));
static void P_PrepareRawThings(UINT8 *data, size_t i)
{
mapthing_t *mt;
nummapthings = i / (5 * sizeof (INT16));
mapthings = Z_Calloc(nummapthings * sizeof (*mapthings), PU_LEVEL, NULL);
// Spawn axis points first so they are
// at the front of the list for fast searching.
data = datastart = W_CacheLumpNum(lumpnum, PU_LEVEL);
mt = mapthings;
for (i = 0; i < nummapthings; i++, mt++)
{
@ -952,8 +960,13 @@ static void P_PrepareThings(lumpnum_t lumpnum)
break;
}
}
Z_Free(datastart);
}
static void P_PrepareThings(lumpnum_t lumpnum)
{
UINT8 *data = W_CacheLumpNum(lumpnum, PU_STATIC);
P_PrepareRawThings(data, W_LumpLength(lumpnum));
Z_Free(data);
}
static void P_LoadThings(void)
@ -1140,22 +1153,16 @@ void P_WriteThings(lumpnum_t lumpnum)
CONS_Printf(M_GetText("newthings%d.lmp saved.\n"), gamemap);
}
//
// P_LoadLineDefs
//
static void P_LoadLineDefs(lumpnum_t lumpnum)
static void P_LoadRawLineDefs(UINT8 *data, size_t i)
{
UINT8 *data;
size_t i;
maplinedef_t *mld;
line_t *ld;
vertex_t *v1, *v2;
numlines = W_LumpLength(lumpnum) / sizeof (maplinedef_t);
numlines = i / sizeof (maplinedef_t);
if (numlines <= 0)
I_Error("Level has no linedefs");
lines = Z_Calloc(numlines * sizeof (*lines), PU_LEVEL, NULL);
data = W_CacheLumpNum(lumpnum, PU_STATIC);
mld = (maplinedef_t *)data;
ld = lines;
@ -1177,7 +1184,7 @@ static void P_LoadLineDefs(lumpnum_t lumpnum)
ld->slopetype = ST_VERTICAL;
else if (!ld->dy)
ld->slopetype = ST_HORIZONTAL;
else if (FixedDiv(ld->dy, ld->dx) > 0)
else if ((ld->dy > 0) == (ld->dx > 0))
ld->slopetype = ST_POSITIVE;
else
ld->slopetype = ST_NEGATIVE;
@ -1217,7 +1224,7 @@ static void P_LoadLineDefs(lumpnum_t lumpnum)
if (ld->sidenum[j] != 0xffff && ld->sidenum[j] >= (UINT16)numsides)
{
ld->sidenum[j] = 0xffff;
CONS_Debug(DBG_SETUP, "P_LoadLineDefs: linedef %s has out-of-range sidedef number\n", sizeu1(numlines-i-1));
CONS_Debug(DBG_SETUP, "P_LoadRawLineDefs: linedef %s has out-of-range sidedef number\n", sizeu1(numlines-i-1));
}
}
}
@ -1232,14 +1239,14 @@ static void P_LoadLineDefs(lumpnum_t lumpnum)
{
ld->sidenum[0] = 0; // Substitute dummy sidedef for missing right side
// cph - print a warning about the bug
CONS_Debug(DBG_SETUP, "P_LoadLineDefs: linedef %s missing first sidedef\n", sizeu1(numlines-i-1));
CONS_Debug(DBG_SETUP, "P_LoadRawLineDefs: linedef %s missing first sidedef\n", sizeu1(numlines-i-1));
}
if ((ld->sidenum[1] == 0xffff) && (ld->flags & ML_TWOSIDED))
{
ld->flags &= ~ML_TWOSIDED; // Clear 2s flag for missing left side
// cph - print a warning about the bug
CONS_Debug(DBG_SETUP, "P_LoadLineDefs: linedef %s has two-sided flag set, but no second sidedef\n", sizeu1(numlines-i-1));
CONS_Debug(DBG_SETUP, "P_LoadRawLineDefs: linedef %s has two-sided flag set, but no second sidedef\n", sizeu1(numlines-i-1));
}
if (ld->sidenum[0] != 0xffff && ld->special)
@ -1251,7 +1258,12 @@ static void P_LoadLineDefs(lumpnum_t lumpnum)
ld->polyobj = NULL;
#endif
}
}
static void P_LoadLineDefs(lumpnum_t lumpnum)
{
UINT8 *data = W_CacheLumpNum(lumpnum, PU_STATIC);
P_LoadRawLineDefs(data, W_LumpLength(lumpnum));
Z_Free(data);
}
@ -1353,22 +1365,24 @@ static void P_LoadLineDefs2(void)
}
}
//
// P_LoadSideDefs
//
static inline void P_LoadSideDefs(lumpnum_t lumpnum)
static inline void P_LoadRawSideDefs(size_t i)
{
numsides = W_LumpLength(lumpnum) / sizeof (mapsidedef_t);
numsides = i / sizeof (mapsidedef_t);
if (numsides <= 0)
I_Error("Level has no sidedefs");
sides = Z_Calloc(numsides * sizeof (*sides), PU_LEVEL, NULL);
}
// Delay loading texture names until after loaded linedefs.
static void P_LoadSideDefs2(lumpnum_t lumpnum)
static inline void P_LoadSideDefs(lumpnum_t lumpnum)
{
P_LoadRawSideDefs(W_LumpLength(lumpnum));
}
static void P_LoadRawSideDefs2(void *data)
{
UINT8 *data = W_CacheLumpNum(lumpnum, PU_STATIC);
UINT16 i;
INT32 num;
@ -1386,7 +1400,7 @@ static void P_LoadSideDefs2(lumpnum_t lumpnum)
if (sector_num >= numsectors)
{
CONS_Debug(DBG_SETUP, "P_LoadSideDefs2: sidedef %u has out-of-range sector num %u\n", i, sector_num);
CONS_Debug(DBG_SETUP, "P_LoadRawSideDefs2: sidedef %u has out-of-range sector num %u\n", i, sector_num);
sector_num = 0;
}
sd->sector = sec = &sectors[sector_num];
@ -1528,6 +1542,8 @@ static void P_LoadSideDefs2(lumpnum_t lumpnum)
sd->text[6] = 0;
break;
}
case 4: // Speed pad parameters
case 414: // Play SFX
{
sd->toptexture = sd->midtexture = sd->bottomtexture = 0;
@ -1541,6 +1557,9 @@ static void P_LoadSideDefs2(lumpnum_t lumpnum)
break;
}
case 9: // Mace parameters
case 14: // Bustable block parameters
case 15: // Fan particle spawner parameters
case 425: // Calls P_SetMobjState on calling mobj
case 434: // Custom Power
case 442: // Calls P_SetMobjState on mobjs of a given type in the tagged sectors
@ -1595,11 +1614,18 @@ static void P_LoadSideDefs2(lumpnum_t lumpnum)
break;
}
}
Z_Free(data);
R_ClearTextureNumCache(true);
}
// Delay loading texture names until after loaded linedefs.
static void P_LoadSideDefs2(lumpnum_t lumpnum)
{
UINT8 *data = W_CacheLumpNum(lumpnum, PU_STATIC);
P_LoadRawSideDefs2(data);
Z_Free(data);
}
static boolean LineInBlock(fixed_t cx1, fixed_t cy1, fixed_t cx2, fixed_t cy2, fixed_t bx1, fixed_t by1)
{
fixed_t bbox[4];
@ -1855,6 +1881,30 @@ static void P_CreateBlockMap(void)
}
}
// Split from P_LoadBlockMap for convenience
// -- Monster Iestyn 08/01/18
static void P_ReadBlockMapLump(INT16 *wadblockmaplump, size_t count)
{
size_t i;
blockmaplump = Z_Calloc(sizeof (*blockmaplump) * count, PU_LEVEL, NULL);
// killough 3/1/98: Expand wad blockmap into larger internal one,
// by treating all offsets except -1 as unsigned and zero-extending
// them. This potentially doubles the size of blockmaps allowed,
// because Doom originally considered the offsets as always signed.
blockmaplump[0] = SHORT(wadblockmaplump[0]);
blockmaplump[1] = SHORT(wadblockmaplump[1]);
blockmaplump[2] = (INT32)(SHORT(wadblockmaplump[2])) & 0xffff;
blockmaplump[3] = (INT32)(SHORT(wadblockmaplump[3])) & 0xffff;
for (i = 4; i < count; i++)
{
INT16 t = SHORT(wadblockmaplump[i]); // killough 3/1/98
blockmaplump[i] = t == -1 ? (INT32)-1 : (INT32) t & 0xffff;
}
}
//
// P_LoadBlockMap
//
@ -1881,38 +1931,20 @@ static boolean P_LoadBlockMap(lumpnum_t lumpnum)
return false;
{
size_t i;
INT16 *wadblockmaplump = malloc(count); //INT16 *wadblockmaplump = W_CacheLumpNum (lump, PU_LEVEL);
if (wadblockmaplump) W_ReadLump(lumpnum, wadblockmaplump);
else return false;
if (!wadblockmaplump)
return false;
W_ReadLump(lumpnum, wadblockmaplump);
count /= 2;
blockmaplump = Z_Calloc(sizeof (*blockmaplump) * count, PU_LEVEL, 0);
// killough 3/1/98: Expand wad blockmap into larger internal one,
// by treating all offsets except -1 as unsigned and zero-extending
// them. This potentially doubles the size of blockmaps allowed,
// because Doom originally considered the offsets as always signed.
blockmaplump[0] = SHORT(wadblockmaplump[0]);
blockmaplump[1] = SHORT(wadblockmaplump[1]);
blockmaplump[2] = (INT32)(SHORT(wadblockmaplump[2])) & 0xffff;
blockmaplump[3] = (INT32)(SHORT(wadblockmaplump[3])) & 0xffff;
for (i = 4; i < count; i++)
{
INT16 t = SHORT(wadblockmaplump[i]); // killough 3/1/98
blockmaplump[i] = t == -1 ? (INT32)-1 : (INT32) t & 0xffff;
}
P_ReadBlockMapLump(wadblockmaplump, count);
free(wadblockmaplump);
bmaporgx = blockmaplump[0]<<FRACBITS;
bmaporgy = blockmaplump[1]<<FRACBITS;
bmapwidth = blockmaplump[2];
bmapheight = blockmaplump[3];
}
bmaporgx = blockmaplump[0]<<FRACBITS;
bmaporgy = blockmaplump[1]<<FRACBITS;
bmapwidth = blockmaplump[2];
bmapheight = blockmaplump[3];
// clear out mobj chains
count = sizeof (*blocklinks)* bmapwidth*bmapheight;
blocklinks = Z_Calloc(count, PU_LEVEL, NULL);
@ -1946,6 +1978,53 @@ static boolean P_LoadBlockMap(lumpnum_t lumpnum)
#endif
}
// This needs to be a separate function
// because making both the WAD and PK3 loading code use
// the same functions is trickier than it looks for blockmap
// -- Monster Iestyn 09/01/18
static boolean P_LoadRawBlockMap(UINT8 *data, size_t count, const char *lumpname)
{
#if 0
(void)data;
(void)count;
(void)lumpname;
return false;
#else
// Check if the lump is named "BLOCKMAP"
if (!lumpname || memcmp(lumpname, "BLOCKMAP", 8) != 0)
{
CONS_Printf("No blockmap lump found for pk3!\n");
return false;
}
if (!count || count >= 0x20000)
return false;
CONS_Printf("Reading blockmap lump for pk3...\n");
// no need to malloc anything, assume the data is uncompressed for now
count /= 2;
P_ReadBlockMapLump((INT16 *)data, count);
bmaporgx = blockmaplump[0]<<FRACBITS;
bmaporgy = blockmaplump[1]<<FRACBITS;
bmapwidth = blockmaplump[2];
bmapheight = blockmaplump[3];
// clear out mobj chains
count = sizeof (*blocklinks)* bmapwidth*bmapheight;
blocklinks = Z_Calloc(count, PU_LEVEL, NULL);
blockmap = blockmaplump+4;
#ifdef POLYOBJECTS
// haleyjd 2/22/06: setup polyobject blockmap
count = sizeof(*polyblocklinks) * bmapwidth * bmapheight;
polyblocklinks = Z_Calloc(count, PU_LEVEL, NULL);
#endif
return true;
#endif
}
//
// P_GroupLines
// Builds sector line lists and subsector sector numbers.
@ -2071,6 +2150,30 @@ static void P_LoadReject(lumpnum_t lumpnum)
rejectmatrix = W_CacheLumpNum(lumpnum, PU_LEVEL);
}
// PK3 version
// -- Monster Iestyn 09/01/18
static void P_LoadRawReject(UINT8 *data, size_t count, const char *lumpname)
{
// Check if the lump is named "REJECT"
if (!lumpname || memcmp(lumpname, "REJECT\0\0", 8) != 0)
{
rejectmatrix = NULL;
CONS_Debug(DBG_SETUP, "P_LoadRawReject: No valid REJECT lump found\n");
return;
}
if (!count) // zero length, someone probably used ZDBSP
{
rejectmatrix = NULL;
CONS_Debug(DBG_SETUP, "P_LoadRawReject: REJECT lump has size 0, will not be loaded\n");
}
else
{
rejectmatrix = Z_Malloc(count, PU_LEVEL, NULL); // allocate memory for the reject matrix
M_Memcpy(rejectmatrix, data, count); // copy the data into it
}
}
#if 0
static char *levellumps[] =
{
@ -2250,7 +2353,16 @@ void P_LoadThingsOnly(void)
P_LevelInitStuff();
P_PrepareThings(lastloadedmaplumpnum + ML_THINGS);
if (W_IsLumpWad(lastloadedmaplumpnum)) // welp it's a map wad in a pk3
{ // HACK: Open wad file rather quickly so we can use the things lump
UINT8 *wadData = W_CacheLumpNum(lastloadedmaplumpnum, PU_STATIC);
filelump_t *fileinfo = (filelump_t *)(wadData + ((wadinfo_t *)wadData)->infotableofs);
fileinfo += ML_THINGS; // we only need the THINGS lump
P_PrepareRawThings(wadData + fileinfo->filepos, fileinfo->size);
Z_Free(wadData); // we're done with this now
}
else // phew it's just a WAD
P_PrepareThings(lastloadedmaplumpnum + ML_THINGS);
P_LoadThings();
P_SpawnSecretItems(true);
@ -2688,7 +2800,12 @@ boolean P_SetupLevel(boolean skipprecip)
}
// internal game map
lastloadedmaplumpnum = W_GetNumForName(maplumpname = G_BuildMapName(gamemap));
maplumpname = G_BuildMapName(gamemap);
//lastloadedmaplumpnum = LUMPERROR;
lastloadedmaplumpnum = W_CheckNumForName(maplumpname);
if (lastloadedmaplumpnum == INT16_MAX)
I_Error("Map %s not found.\n", maplumpname);
R_ReInitColormaps(mapheaderinfo[gamemap-1]->palette);
CON_SetupBackColormap();
@ -2698,38 +2815,93 @@ boolean P_SetupLevel(boolean skipprecip)
P_MakeMapMD5(lastloadedmaplumpnum, &mapmd5);
// note: most of this ordering is important
loadedbm = P_LoadBlockMap(lastloadedmaplumpnum + ML_BLOCKMAP);
// HACK ALERT: Cache the WAD, get the map data into the tables, free memory.
// As it is implemented right now, we're assuming an uncompressed WAD.
// (As in, a normal PWAD, not ZWAD or anything. The lump itself can be compressed.)
// We're not accounting for extra lumps and scrambled lump positions. Any additional data will cause an error.
if (W_IsLumpWad(lastloadedmaplumpnum))
{
// Remember that we're assuming that the WAD will have a specific set of lumps in a specific order.
UINT8 *wadData = W_CacheLumpNum(lastloadedmaplumpnum, PU_STATIC);
//filelump_t *fileinfo = wadData + ((wadinfo_t *)wadData)->infotableofs;
filelump_t *fileinfo = (filelump_t *)(wadData + ((wadinfo_t *)wadData)->infotableofs);
UINT32 numlumps = ((wadinfo_t *)wadData)->numlumps;
P_LoadVertexes(lastloadedmaplumpnum + ML_VERTEXES);
P_LoadSectors(lastloadedmaplumpnum + ML_SECTORS);
if (numlumps < ML_REJECT) // at least 9 lumps should be in the wad for a map to be loaded
{
I_Error("Bad WAD file for map %s!\n", maplumpname);
}
P_LoadSideDefs(lastloadedmaplumpnum + ML_SIDEDEFS);
if (numlumps > ML_BLOCKMAP) // enough room for a BLOCKMAP lump at least
{
loadedbm = P_LoadRawBlockMap(
wadData + (fileinfo + ML_BLOCKMAP)->filepos,
(fileinfo + ML_BLOCKMAP)->size,
(fileinfo + ML_BLOCKMAP)->name);
}
P_LoadRawVertexes(wadData + (fileinfo + ML_VERTEXES)->filepos, (fileinfo + ML_VERTEXES)->size);
P_LoadRawSectors(wadData + (fileinfo + ML_SECTORS)->filepos, (fileinfo + ML_SECTORS)->size);
P_LoadRawSideDefs((fileinfo + ML_SIDEDEFS)->size);
P_LoadRawLineDefs(wadData + (fileinfo + ML_LINEDEFS)->filepos, (fileinfo + ML_LINEDEFS)->size);
P_LoadRawSideDefs2(wadData + (fileinfo + ML_SIDEDEFS)->filepos);
P_LoadRawSubsectors(wadData + (fileinfo + ML_SSECTORS)->filepos, (fileinfo + ML_SSECTORS)->size);
P_LoadRawNodes(wadData + (fileinfo + ML_NODES)->filepos, (fileinfo + ML_NODES)->size);
P_LoadRawSegs(wadData + (fileinfo + ML_SEGS)->filepos, (fileinfo + ML_SEGS)->size);
if (numlumps > ML_REJECT) // enough room for a REJECT lump at least
{
P_LoadRawReject(
wadData + (fileinfo + ML_REJECT)->filepos,
(fileinfo + ML_REJECT)->size,
(fileinfo + ML_REJECT)->name);
}
P_LoadLineDefs(lastloadedmaplumpnum + ML_LINEDEFS);
if (!loadedbm)
P_CreateBlockMap(); // Graue 02-29-2004
P_LoadSideDefs2(lastloadedmaplumpnum + ML_SIDEDEFS);
// Important: take care of the ordering of the next functions.
if (!loadedbm)
P_CreateBlockMap(); // Graue 02-29-2004
P_LoadLineDefs2();
P_GroupLines();
numdmstarts = numredctfstarts = numbluectfstarts = 0;
P_LoadLineDefs2();
P_LoadSubsectors(lastloadedmaplumpnum + ML_SSECTORS);
P_LoadNodes(lastloadedmaplumpnum + ML_NODES);
P_LoadSegs(lastloadedmaplumpnum + ML_SEGS);
P_LoadReject(lastloadedmaplumpnum + ML_REJECT);
P_GroupLines();
// reset the player starts
for (i = 0; i < MAXPLAYERS; i++)
playerstarts[i] = NULL;
for (i = 0; i < 2; i++)
skyboxmo[i] = NULL;
P_MapStart();
numdmstarts = numredctfstarts = numbluectfstarts = 0;
P_PrepareRawThings(wadData + (fileinfo + ML_THINGS)->filepos, (fileinfo + ML_THINGS)->size);
Z_Free(wadData);
}
else
{
// Important: take care of the ordering of the next functions.
loadedbm = P_LoadBlockMap(lastloadedmaplumpnum + ML_BLOCKMAP);
P_LoadVertexes(lastloadedmaplumpnum + ML_VERTEXES);
P_LoadSectors(lastloadedmaplumpnum + ML_SECTORS);
P_LoadSideDefs(lastloadedmaplumpnum + ML_SIDEDEFS);
P_LoadLineDefs(lastloadedmaplumpnum + ML_LINEDEFS);
P_LoadSideDefs2(lastloadedmaplumpnum + ML_SIDEDEFS);
P_LoadSubsectors(lastloadedmaplumpnum + ML_SSECTORS);
P_LoadNodes(lastloadedmaplumpnum + ML_NODES);
P_LoadSegs(lastloadedmaplumpnum + ML_SEGS);
P_LoadReject(lastloadedmaplumpnum + ML_REJECT);
// reset the player starts
for (i = 0; i < MAXPLAYERS; i++)
playerstarts[i] = NULL;
// Important: take care of the ordering of the next functions.
if (!loadedbm)
P_CreateBlockMap(); // Graue 02-29-2004
for (i = 0; i < 2; i++)
skyboxmo[i] = NULL;
P_LoadLineDefs2();
P_GroupLines();
numdmstarts = numredctfstarts = numbluectfstarts = 0;
P_MapStart();
P_PrepareThings(lastloadedmaplumpnum + ML_THINGS);
// reset the player starts
for (i = 0; i < MAXPLAYERS; i++)
playerstarts[i] = NULL;
for (i = 0; i < 2; i++)
skyboxmo[i] = NULL;
P_MapStart();
P_PrepareThings(lastloadedmaplumpnum + ML_THINGS);
}
#ifdef ESLOPE
P_ResetDynamicSlopes();
@ -2977,7 +3149,7 @@ boolean P_RunSOC(const char *socfilename)
lumpnum_t lump;
if (strstr(socfilename, ".soc") != NULL)
return P_AddWadFile(socfilename, NULL);
return P_AddWadFile(socfilename);
lump = W_CheckNumForName(socfilename);
if (lump == LUMPERROR)
@ -2993,17 +3165,17 @@ boolean P_RunSOC(const char *socfilename)
// Add a wadfile to the active wad files,
// replace sounds, musics, patches, textures, sprites and maps
//
boolean P_AddWadFile(const char *wadfilename, char **firstmapname)
boolean P_AddWadFile(const char *wadfilename)
{
size_t i, j, sreplaces = 0, mreplaces = 0, digmreplaces = 0;
UINT16 numlumps, wadnum;
INT16 firstmapreplaced = 0, num;
char *name;
lumpinfo_t *lumpinfo;
boolean texturechange = false;
boolean mapsadded = false;
boolean replacedcurrentmap = false;
if ((numlumps = W_LoadWadFile(wadfilename)) == INT16_MAX)
if ((numlumps = W_InitFile(wadfilename)) == INT16_MAX)
{
CONS_Printf(M_GetText("Errors occurred while loading %s; not added.\n"), wadfilename);
return false;
@ -3059,6 +3231,7 @@ boolean P_AddWadFile(const char *wadfilename, char **firstmapname)
if (!devparm && digmreplaces)
CONS_Printf(M_GetText("%s digital musics replaced\n"), sizeu1(digmreplaces));
//
// search for sprite replacements
//
@ -3093,10 +3266,10 @@ boolean P_AddWadFile(const char *wadfilename, char **firstmapname)
for (i = 0; i < numlumps; i++, lumpinfo++)
{
name = lumpinfo->name;
num = firstmapreplaced;
if (name[0] == 'M' && name[1] == 'A' && name[2] == 'P') // Ignore the headers
{
INT16 num;
if (name[5]!='\0')
continue;
num = (INT16)M_MapNumber(name[3], name[4]);
@ -3106,16 +3279,10 @@ boolean P_AddWadFile(const char *wadfilename, char **firstmapname)
replacedcurrentmap = true;
CONS_Printf("%s\n", name);
}
if (num && (num < firstmapreplaced || !firstmapreplaced))
{
firstmapreplaced = num;
if (firstmapname)
*firstmapname = name;
mapsadded = true;
}
}
if (!firstmapreplaced)
if (!mapsadded)
CONS_Printf(M_GetText("No maps added\n"));
// reload status bar (warning should have valid player!)

View file

@ -59,7 +59,7 @@ void P_ScanThings(INT16 mapnum, INT16 wadnum, INT16 lumpnum);
#endif
void P_LoadThingsOnly(void);
boolean P_SetupLevel(boolean skipprecip);
boolean P_AddWadFile(const char *wadfilename, char **firstmapname);
boolean P_AddWadFile(const char *wadfilename);
#ifdef DELFILE
boolean P_DelWadFile(void);
#endif

View file

@ -279,10 +279,16 @@ void P_InitPicAnims(void)
Z_Free(animatedLump);
}
// Now find ANIMDEFS
animdefsLumpNum = W_CheckNumForNamePwad("ANIMDEFS", w, 0);
if (animdefsLumpNum != INT16_MAX)
P_ParseANIMDEFSLump(w, animdefsLumpNum);
for (w = numwadfiles-1; w >= 0; w--)
{
// Find ANIMDEFS lump in the WAD
animdefsLumpNum = W_CheckNumForNamePwad("ANIMDEFS", w, 0);
while (animdefsLumpNum != INT16_MAX)
{
P_ParseANIMDEFSLump(w, animdefsLumpNum);
animdefsLumpNum = W_CheckNumForNamePwad("ANIMDEFS", (UINT16)w, animdefsLumpNum + 1);
}
}
}
// Define the last one
animdefs[maxanims].istexture = -1;
@ -6243,9 +6249,21 @@ void P_SpawnSpecials(INT32 fromnetsave)
case 259: // Make-Your-Own FOF!
if (lines[i].sidenum[1] != 0xffff)
{
UINT8 *data = W_CacheLumpNum(lastloadedmaplumpnum + ML_SIDEDEFS,PU_STATIC);
UINT8 *data;
UINT16 b;
if (W_IsLumpWad(lastloadedmaplumpnum)) // welp it's a map wad in a pk3
{ // HACK: Open wad file rather quickly so we can get the data from the sidedefs lump
UINT8 *wadData = W_CacheLumpNum(lastloadedmaplumpnum, PU_STATIC);
filelump_t *fileinfo = (filelump_t *)(wadData + ((wadinfo_t *)wadData)->infotableofs);
fileinfo += ML_SIDEDEFS; // we only need the SIDEDEFS lump
data = Z_Malloc(fileinfo->size, PU_STATIC, NULL);
M_Memcpy(data, wadData + fileinfo->filepos, fileinfo->size); // copy data
Z_Free(wadData); // we're done with this now
}
else // phew it's just a WAD
data = W_CacheLumpNum(lastloadedmaplumpnum + ML_SIDEDEFS,PU_STATIC);
for (b = 0; b < (INT16)numsides; b++)
{
register mapsidedef_t *msd = (mapsidedef_t *)data + b;

View file

@ -365,8 +365,8 @@ void R_FlushTextureCache(void)
}
// Need these prototypes for later; defining them here instead of r_data.h so they're "private"
int R_CountTexturesInTEXTURESLump(UINT16 wadNum);
void R_ParseTEXTURESLump(UINT16 wadNum, INT32 *index);
int R_CountTexturesInTEXTURESLump(UINT16 wadNum, UINT16 lumpNum);
void R_ParseTEXTURESLump(UINT16 wadNum, UINT16 lumpNum, INT32 *index);
//
// R_LoadTextures
@ -404,13 +404,22 @@ void R_LoadTextures(void)
// but the alternative is to spend a ton of time checking and re-checking all previous entries just to skip any potentially patched textures.
for (w = 0, numtextures = 0; w < numwadfiles; w++)
{
texstart = W_CheckNumForNamePwad(TX_START, (UINT16)w, 0) + 1;
texend = W_CheckNumForNamePwad(TX_END, (UINT16)w, 0);
texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, 0);
if (texturesLumpPos != INT16_MAX)
if (wadfiles[w]->type == RET_PK3)
{
numtextures += R_CountTexturesInTEXTURESLump((UINT16)w);
texstart = W_CheckNumForFolderStartPK3("textures/", (UINT16)w, 0);
texend = W_CheckNumForFolderEndPK3("textures/", (UINT16)w, texstart);
}
else
{
texstart = W_CheckNumForNamePwad(TX_START, (UINT16)w, 0) + 1;
texend = W_CheckNumForNamePwad(TX_END, (UINT16)w, 0);
}
texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, 0);
while (texturesLumpPos != INT16_MAX)
{
numtextures += R_CountTexturesInTEXTURESLump((UINT16)w, (UINT16)texturesLumpPos);
texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, texturesLumpPos + 1);
}
// Add all the textures between TX_START and TX_END
@ -447,12 +456,25 @@ void R_LoadTextures(void)
for (i = 0, w = 0; w < numwadfiles; w++)
{
// Get the lump numbers for the markers in the WAD, if they exist.
texstart = W_CheckNumForNamePwad(TX_START, (UINT16)w, 0) + 1;
texend = W_CheckNumForNamePwad(TX_END, (UINT16)w, 0);
texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, 0);
if (texturesLumpPos != INT16_MAX)
R_ParseTEXTURESLump(w,&i);
if (wadfiles[w]->type == RET_PK3)
{
texstart = W_CheckNumForFolderStartPK3("textures/", (UINT16)w, 0);
texend = W_CheckNumForFolderEndPK3("textures/", (UINT16)w, texstart);
texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, 0);
while (texturesLumpPos != INT16_MAX)
{
R_ParseTEXTURESLump(w, texturesLumpPos, &i);
texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, texturesLumpPos + 1);
}
}
else
{
texstart = W_CheckNumForNamePwad(TX_START, (UINT16)w, 0) + 1;
texend = W_CheckNumForNamePwad(TX_END, (UINT16)w, 0);
texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, 0);
if (texturesLumpPos != INT16_MAX)
R_ParseTEXTURESLump(w, texturesLumpPos, &i);
}
if (texstart == INT16_MAX || texend == INT16_MAX)
continue;
@ -799,7 +821,7 @@ static texture_t *R_ParseTexture(boolean actuallyLoadTexture)
}
// Parses the TEXTURES lump... but just to count the number of textures.
int R_CountTexturesInTEXTURESLump(UINT16 wadNum)
int R_CountTexturesInTEXTURESLump(UINT16 wadNum, UINT16 lumpNum)
{
char *texturesLump;
size_t texturesLumpLength;
@ -810,11 +832,11 @@ int R_CountTexturesInTEXTURESLump(UINT16 wadNum)
// Since lumps AREN'T \0-terminated like I'd assumed they should be, I'll
// need to make a space of memory where I can ensure that it will terminate
// correctly. Start by loading the relevant data from the WAD.
texturesLump = (char *)W_CacheLumpNumPwad(wadNum,W_CheckNumForNamePwad("TEXTURES", wadNum, 0),PU_STATIC);
texturesLump = (char *)W_CacheLumpNumPwad(wadNum, lumpNum, PU_STATIC);
// If that didn't exist, we have nothing to do here.
if (texturesLump == NULL) return 0;
// If we're still here, then it DOES exist; figure out how long it is, and allot memory accordingly.
texturesLumpLength = W_LumpLengthPwad(wadNum,W_CheckNumForNamePwad("TEXTURES",wadNum,0));
texturesLumpLength = W_LumpLengthPwad(wadNum, lumpNum);
texturesText = (char *)Z_Malloc((texturesLumpLength+1)*sizeof(char),PU_STATIC,NULL);
// Now move the contents of the lump into this new location.
memmove(texturesText,texturesLump,texturesLumpLength);
@ -846,7 +868,7 @@ int R_CountTexturesInTEXTURESLump(UINT16 wadNum)
}
// Parses the TEXTURES lump... for real, this time.
void R_ParseTEXTURESLump(UINT16 wadNum, INT32 *texindex)
void R_ParseTEXTURESLump(UINT16 wadNum, UINT16 lumpNum, INT32 *texindex)
{
char *texturesLump;
size_t texturesLumpLength;
@ -859,11 +881,11 @@ void R_ParseTEXTURESLump(UINT16 wadNum, INT32 *texindex)
// Since lumps AREN'T \0-terminated like I'd assumed they should be, I'll
// need to make a space of memory where I can ensure that it will terminate
// correctly. Start by loading the relevant data from the WAD.
texturesLump = (char *)W_CacheLumpNumPwad(wadNum,W_CheckNumForNamePwad("TEXTURES", wadNum, 0),PU_STATIC);
texturesLump = (char *)W_CacheLumpNumPwad(wadNum, lumpNum, PU_STATIC);
// If that didn't exist, we have nothing to do here.
if (texturesLump == NULL) return;
// If we're still here, then it DOES exist; figure out how long it is, and allot memory accordingly.
texturesLumpLength = W_LumpLengthPwad(wadNum,W_CheckNumForNamePwad("TEXTURES",wadNum,0));
texturesLumpLength = W_LumpLengthPwad(wadNum, lumpNum);
texturesText = (char *)Z_Malloc((texturesLumpLength+1)*sizeof(char),PU_STATIC,NULL);
// Now move the contents of the lump into this new location.
memmove(texturesText,texturesLump,texturesLumpLength);
@ -950,12 +972,51 @@ static void R_InitExtraColormaps(void)
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.
lumpnum_t R_GetFlatNumForName(const char *name)
{
lumpnum_t lump = W_CheckNumForNameInBlock(name, "F_START", "F_END");
if (lump == LUMPERROR)
lump = W_CheckNumForNameInBlock(name, "FF_START", "FF_END"); // deutex, some other old things
INT32 i;
lumpnum_t lump;
lumpnum_t start;
lumpnum_t end;
// Scan wad files backwards so patched flats take preference.
for (i = numwadfiles - 1; i >= 0; i--)
{
switch (wadfiles[i]->type)
{
case RET_WAD:
if ((start = W_CheckNumForNamePwad("F_START", (UINT16)i, 0)) == INT16_MAX)
{
if ((start = W_CheckNumForNamePwad("FF_START", (UINT16)i, 0)) == INT16_MAX)
continue;
else if ((end = W_CheckNumForNamePwad("FF_END", (UINT16)i, start)) == INT16_MAX)
continue;
}
else
if ((end = W_CheckNumForNamePwad("F_END", (UINT16)i, start)) == INT16_MAX)
continue;
break;
case RET_PK3:
if ((start = W_CheckNumForFolderStartPK3("Flats/", i, 0)) == INT16_MAX)
continue;
if ((end = W_CheckNumForFolderEndPK3("Flats/", i, start)) == INT16_MAX)
continue;
break;
default:
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 (strcmp(name, SKYFLATNAME))

View file

@ -327,21 +327,28 @@ void R_AddSpriteDefs(UINT16 wadnum)
UINT16 start, end;
char wadname[MAX_WADPATH];
// find the sprites section in this pwad
// we need at least the S_END
// (not really, but for speedup)
switch (wadfiles[wadnum]->type)
{
case RET_WAD:
start = W_CheckNumForNamePwad("S_START", wadnum, 0);
if (start == INT16_MAX)
start = W_CheckNumForNamePwad("SS_START", wadnum, 0); //deutex compatib.
if (start == INT16_MAX)
start = 0; //let say S_START is lump 0
else
start++; // just after S_START
end = W_CheckNumForNamePwad("S_END",wadnum,start);
if (end == INT16_MAX)
end = W_CheckNumForNamePwad("SS_END",wadnum,start); //deutex compatib.
break;
case RET_PK3:
start = W_CheckNumForFolderStartPK3("Sprites/", wadnum, 0);
end = W_CheckNumForFolderEndPK3("Sprites/", wadnum, start);
break;
default:
return;
}
start = W_CheckNumForNamePwad("S_START", wadnum, 0);
if (start == INT16_MAX)
start = W_CheckNumForNamePwad("SS_START", wadnum, 0); //deutex compatib.
if (start == INT16_MAX)
start = 0; //let say S_START is lump 0
else
start++; // just after S_START
end = W_CheckNumForNamePwad("S_END",wadnum,start);
if (end == INT16_MAX)
end = W_CheckNumForNamePwad("SS_END",wadnum,start); //deutex compatib.
if (end == INT16_MAX)
{
CONS_Debug(DBG_SETUP, "no sprites in pwad %d\n", wadnum);

View file

@ -26,6 +26,8 @@
#include "lzf.h"
#endif
#include "zlib.h"
#include "doomdef.h"
#include "doomstat.h"
#include "doomtype.h"
@ -67,14 +69,6 @@ int snprintf(char *str, size_t n, const char *fmt, ...);
#pragma pack(1)
#endif
// a raw entry of the wad directory
typedef struct
{
UINT32 filepos; // file offset of the resource
UINT32 size; // size of the resource
char name[8]; // name of the resource
} ATTRPACK filelump_t;
#if defined(_MSC_VER)
#pragma pack()
#endif
@ -116,6 +110,8 @@ void W_Shutdown(void)
Z_Free(wadfiles[numwadfiles]->lumpinfo);
Z_Free(wadfiles[numwadfiles]->filename);
Z_Free(wadfiles[numwadfiles]);
while (wadfiles[numwadfiles]->numlumps--)
Z_Free(wadfiles[numwadfiles]->lumpinfo[wadfiles[numwadfiles]->numlumps].name2);
}
}
@ -174,6 +170,38 @@ FILE *W_OpenWadFile(const char **filename, boolean useerrors)
return handle;
}
// Look for all DEHACKED and Lua scripts inside a PK3 archive.
static inline void W_LoadDehackedLumpsPK3(UINT16 wadnum)
{
UINT16 posStart, posEnd;
posStart = W_CheckNumForFolderStartPK3("Lua/", wadnum, 0);
if (posStart != INT16_MAX)
{
posEnd = W_CheckNumForFolderEndPK3("Lua/", wadnum, posStart);
posStart++;
for (; posStart < posEnd; posStart++)
LUA_LoadLump(wadnum, posStart);
}
posStart = W_CheckNumForFolderStartPK3("SOC/", wadnum, 0);
if (posStart != INT16_MAX)
{
posEnd = W_CheckNumForFolderEndPK3("SOC/", wadnum, posStart);
posStart++;
for(; posStart < posEnd; 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
char *name = malloc(length + 1);
sprintf(name, "%s|%s", wadfiles[wadnum]->filename, lump_p->name2);
name[length] = '\0';
CONS_Printf(M_GetText("Loading SOC from %s\n"), name);
DEH_LoadDehackedLumpPwad(wadnum, posStart);
free(name);
}
}
}
// search for all DEHACKED lump in all wads and load it
static inline void W_LoadDehackedLumps(UINT16 wadnum)
{
@ -194,20 +222,13 @@ static inline void W_LoadDehackedLumps(UINT16 wadnum)
for (lump = 0; lump < wadfiles[wadnum]->numlumps; lump++, lump_p++)
if (memcmp(lump_p->name,"SOC_",4)==0) // Check for generic SOC lump
{ // shameless copy+paste of code from LUA_LoadLump
size_t len = strlen(wadfiles[wadnum]->filename);
char *name = malloc(len+10);
strcpy(name, wadfiles[wadnum]->filename);
if (!fasticmp(&name[len - 4], ".soc")) {
// If it's not a .soc file, copy the lump name in too.
name[len] = '|';
M_Memcpy(name+len+1, lump_p->name, 8);
name[len+9] = '\0';
}
size_t length = strlen(wadfiles[wadnum]->filename) + 1 + strlen(lump_p->name2); // length of file name, '|', and lump name
char *name = malloc(length + 1);
sprintf(name, "%s|%s", wadfiles[wadnum]->filename, lump_p->name2);
name[length] = '\0';
CONS_Printf(M_GetText("Loading SOC from %s\n"), name);
DEH_LoadDehackedLumpPwad(wadnum, lump);
free(name);
}
else if (memcmp(lump_p->name,"MAINCFG",8)==0) // Check for MAINCFG
@ -291,12 +312,13 @@ static void W_InvalidateLumpnumCache(void)
//
// Can now load dehacked files (.soc)
//
UINT16 W_LoadWadFile(const char *filename)
UINT16 W_InitFile(const char *filename)
{
FILE *handle;
lumpinfo_t *lumpinfo;
wadfile_t *wadfile;
UINT32 numlumps;
restype_t type;
UINT16 numlumps;
size_t i;
INT32 compressed = 0;
size_t packetsize = 0;
@ -339,12 +361,34 @@ UINT16 W_LoadWadFile(const char *filename)
return INT16_MAX;
}
#ifndef NOMD5
//
// w-waiiiit!
// Let's not add a wad file if the MD5 matches
// an MD5 of an already added WAD file!
//
W_MakeFileMD5(filename, md5sum);
for (i = 0; i < numwadfiles; i++)
{
if (!memcmp(wadfiles[i]->md5sum, md5sum, 16))
{
CONS_Alert(CONS_ERROR, M_GetText("%s is already loaded\n"), filename);
if (handle)
fclose(handle);
return INT16_MAX;
}
}
#endif
// detect dehacked file with the "soc" extension
if (!stricmp(&filename[strlen(filename) - 4], ".soc"))
{
// This code emulates a wadfile with one lump name "OBJCTCFG"
// 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_SOC;
numlumps = 1;
lumpinfo = Z_Calloc(sizeof (*lumpinfo), PU_STATIC, NULL);
lumpinfo->position = 0;
@ -352,6 +396,10 @@ UINT16 W_LoadWadFile(const char *filename)
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
// detect lua script with the "lua" extension
@ -360,6 +408,8 @@ UINT16 W_LoadWadFile(const char *filename)
// 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;
@ -367,16 +417,206 @@ UINT16 W_LoadWadFile(const char *filename)
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
else if (!stricmp(&filename[strlen(filename) - 4], ".pk3"))
{
char curHeader[4];
unsigned long size;
char seekPat[] = {0x50, 0x4b, 0x01, 0x02, 0x00};
char endPat[] = {0x50, 0x4b, 0x05, 0x06, 0x00};
char *s;
int c;
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
{
// assume wad file
wadinfo_t header;
lumpinfo_t *lump_p;
filelump_t *fileinfo;
void *fileinfov;
type = RET_WAD;
// read the header
if (fread(&header, 1, sizeof header, handle) < sizeof header)
{
@ -437,44 +677,29 @@ UINT16 W_LoadWadFile(const char *filename)
if (realsize != 0)
{
lump_p->size = realsize;
lump_p->compressed = 1;
lump_p->compression = CM_LZF;
}
else
{
lump_p->size -= 4;
lump_p->compressed = 0;
lump_p->compression = CM_NOCOMPRESSION;
}
lump_p->position += 4;
lump_p->disksize -= 4;
}
else lump_p->compressed = 0;
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);
}
#ifndef NOMD5
//
// w-waiiiit!
// Let's not add a wad file if the MD5 matches
// an MD5 of an already added WAD file!
//
W_MakeFileMD5(filename, md5sum);
for (i = 0; i < numwadfiles; i++)
{
if (!memcmp(wadfiles[i]->md5sum, md5sum, 16))
{
CONS_Alert(CONS_ERROR, M_GetText("%s is already loaded\n"), filename);
if (handle)
fclose(handle);
return INT16_MAX;
}
}
#endif
//
// link wad file to search files
//
@ -485,6 +710,7 @@ UINT16 W_LoadWadFile(const char *filename)
wadfile->lumpinfo = lumpinfo;
fseek(handle, 0, SEEK_END);
wadfile->filesize = (unsigned)ftell(handle);
wadfile->type = type;
// already generated, just copy it over
M_Memcpy(&wadfile->md5sum, &md5sum, 16);
@ -505,10 +731,28 @@ UINT16 W_LoadWadFile(const char *filename)
CONS_Printf(M_GetText("Added file %s (%u lumps)\n"), filename, numlumps);
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
W_LoadDehackedLumps(numwadfiles-1);
// 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)
{
case RET_WAD:
W_LoadDehackedLumps(numwadfiles - 1);
break;
case RET_PK3:
W_LoadDehackedLumpsPK3(numwadfiles - 1);
break;
case RET_SOC:
CONS_Printf(M_GetText("Loading SOC from %s\n"), wadfile->filename);
DEH_LoadDehackedLumpPwad(numwadfiles - 1, 0);
break;
case RET_LUA:
LUA_LoadLump(numwadfiles - 1, 0);
break;
default:
break;
}
W_InvalidateLumpnumCache();
return wadfile->numlumps;
}
@ -566,7 +810,7 @@ INT32 W_InitMultipleFiles(char **filenames)
for (; *filenames; 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)
@ -644,6 +888,51 @@ UINT16 W_CheckNumForNamePwad(const char *name, UINT16 wad, UINT16 startlump)
return INT16_MAX;
}
// Look for the first lump from a folder.
UINT16 W_CheckNumForFolderStartPK3(const char *name, UINT16 wad, UINT16 startlump)
{
INT32 i;
lumpinfo_t *lump_p = wadfiles[wad]->lumpinfo + startlump;
for (i = startlump; i < wadfiles[wad]->numlumps; i++, lump_p++)
{
if (strnicmp(name, lump_p->name2, strlen(name)) == 0)
break;
}
return i;
}
// In a PK3 type of resource file, it looks for the next lumpinfo entry that doesn't share the specified pathfile.
// Useful for finding folder ends.
// Returns the position of the lumpinfo entry.
UINT16 W_CheckNumForFolderEndPK3(const char *name, UINT16 wad, UINT16 startlump)
{
INT32 i;
lumpinfo_t *lump_p = wadfiles[wad]->lumpinfo + startlump;
for (i = startlump; i < wadfiles[wad]->numlumps; i++, lump_p++)
{
if (strnicmp(name, lump_p->name2, strlen(name)))
break;
}
return i;
}
// In a PK3 type of resource file, it looks for an entry with the specified full name.
// Returns lump position in PK3's lumpinfo, or INT16_MAX if not found.
UINT16 W_CheckNumForFullNamePK3(const char *name, UINT16 wad, UINT16 startlump)
{
INT32 i;
lumpinfo_t *lump_p = wadfiles[wad]->lumpinfo + startlump;
for (i = startlump; i < wadfiles[wad]->numlumps; i++, lump_p++)
{
if (!strnicmp(name, lump_p->name2, strlen(name)))
{
return i;
}
}
// Not found at all?
return INT16_MAX;
}
//
// W_CheckNumForName
// Returns LUMPERROR if name not found.
@ -684,6 +973,37 @@ lumpnum_t W_CheckNumForName(const char *name)
}
}
// 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.
// TODO: Make it search through cache first, maybe...?
lumpnum_t W_CheckNumForMap(const char *name)
{
UINT16 lumpNum, end;
UINT32 i;
for (i = numwadfiles - 1; i < numwadfiles; i--)
{
if (wadfiles[i]->type == RET_WAD)
{
for (lumpNum = 0; lumpNum < wadfiles[i]->numlumps; lumpNum++)
if (!strncmp(name, (wadfiles[i]->lumpinfo + lumpNum)->name, 8))
return (i<<16) + lumpNum;
}
else if (wadfiles[i]->type == RET_PK3)
{
lumpNum = W_CheckNumForFolderStartPK3("maps/", i, 0);
if (lumpNum != INT16_MAX)
end = W_CheckNumForFolderEndPK3("maps/", i, lumpNum);
else
continue;
// Now look for the specified map.
for (++lumpNum; lumpNum < end; lumpNum++)
if (!strnicmp(name, (wadfiles[i]->lumpinfo + lumpNum)->name, 8))
return (i<<16) + lumpNum;
}
}
return LUMPERROR;
}
//
// W_GetNumForName
//
@ -714,15 +1034,19 @@ lumpnum_t W_CheckNumForNameInBlock(const char *name, const char *blockstart, con
// scan wad files backwards so patch lump files take precedence
for (i = numwadfiles - 1; i >= 0; i--)
{
bsid = W_CheckNumForNamePwad(blockstart,(UINT16)i,0);
if (bsid == INT16_MAX)
continue; // block doesn't exist, keep going
beid = W_CheckNumForNamePwad(blockend,(UINT16)i,0);
// if block end doesn't exist, just search through everything
if (wadfiles[i]->type == RET_WAD)
{
bsid = W_CheckNumForNamePwad(blockstart, (UINT16)i, 0);
if (bsid == INT16_MAX)
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;
}
@ -759,80 +1083,53 @@ size_t W_LumpLength(lumpnum_t lumpnum)
return W_LumpLengthPwad(WADFILENUM(lumpnum),LUMPNUM(lumpnum));
}
/** Reads bytes from the head of a lump, without doing decompression.
*
* \param wad Wad number to read from.
* \param lump Lump number to read from, within wad.
* \param dest Buffer in memory to serve as destination.
* \param size Number of bytes to read.
* \param offest Number of bytes to offset.
* \return Number of bytes read (should equal size).
* \sa W_ReadLumpHeader
*/
static size_t W_RawReadLumpHeader(UINT16 wad, UINT16 lump, void *dest, size_t size, size_t offset)
//
// W_IsLumpWad
// Is the lump a WAD? (presumably in a PK3)
//
boolean W_IsLumpWad(lumpnum_t lumpnum)
{
size_t bytesread;
lumpinfo_t *l;
FILE *handle;
if (wadfiles[WADFILENUM(lumpnum)]->type == RET_PK3)
{
const char *lumpfullName = (wadfiles[WADFILENUM(lumpnum)]->lumpinfo + LUMPNUM(lumpnum))->name2;
l = wadfiles[wad]->lumpinfo + lump;
if (strlen(lumpfullName) < 4)
return false; // can't possibly be a WAD can it?
return !strnicmp(lumpfullName + strlen(lumpfullName) - 4, ".wad", 4);
}
handle = wadfiles[wad]->handle;
fseek(handle, (long)(l->position + offset), SEEK_SET);
bytesread = fread(dest, 1, size, handle);
return bytesread;
return false; // WADs should never be inside non-PK3s as far as SRB2 is concerned
}
// Read a compressed lump; return it in newly Z_Malloc'd memory.
// wad is number of wad file, lump is number of lump in wad.
static void *W_ReadCompressedLump(UINT16 wad, UINT16 lump)
/* report a zlib or i/o error */
void zerr(int ret)
{
#ifdef ZWAD
char *compressed, *data;
const lumpinfo_t *l = &wadfiles[wad]->lumpinfo[lump];
size_t retval;
compressed = Z_Malloc(l->disksize, PU_STATIC, NULL);
data = Z_Malloc(l->size, PU_STATIC, NULL);
if (W_RawReadLumpHeader(wad, lump, compressed, l->disksize, 0)
< l->disksize)
{
I_Error("wad %d, lump %d: cannot read compressed data",
wad, lump);
}
retval = lzf_decompress(compressed, l->disksize, data, l->size);
#ifndef AVOID_ERRNO
if (retval == 0 && errno == E2BIG)
{
I_Error("wad %d, lump %d: compressed data too big "
"(bigger than %s)", wad, lump, sizeu1(l->size));
}
else if (retval == 0 && errno == EINVAL)
I_Error("wad %d, lump %d: invalid compressed data", wad, lump);
else
#endif
if (retval != l->size)
{
I_Error("wad %d, lump %d: decompressed to wrong number of "
"bytes (expected %s, got %s)", wad, lump,
sizeu1(l->size), sizeu2(retval));
}
Z_Free(compressed);
return data;
#else
(void)wad;
(void)lump;
//I_Error("ZWAD files not supported on this platform.");
return NULL;
#endif
CONS_Printf("zpipe: ");
switch (ret) {
case Z_ERRNO:
if (ferror(stdin))
CONS_Printf("error reading stdin\n");
if (ferror(stdout))
CONS_Printf("error writing stdout\n");
break;
case Z_STREAM_ERROR:
CONS_Printf("invalid compression level\n");
break;
case Z_DATA_ERROR:
CONS_Printf("invalid or incomplete deflate data\n");
break;
case Z_MEM_ERROR:
CONS_Printf("out of memory\n");
break;
case Z_VERSION_ERROR:
CONS_Printf("zlib version mismatch!\n");
}
}
/** Reads bytes from the head of a lump.
* Note: If the lump is compressed, the whole thing has to be read anyway.
*
* \param wad Wad number to read from.
* \param lump Lump number to read from.
* \param dest Buffer in memory to serve as destination.
* \param size Number of bytes to read.
@ -843,6 +1140,8 @@ static void *W_ReadCompressedLump(UINT16 wad, UINT16 lump)
size_t W_ReadLumpHeaderPwad(UINT16 wad, UINT16 lump, void *dest, size_t size, size_t offset)
{
size_t lumpsize;
lumpinfo_t *l;
FILE *handle;
if (!TestValidLump(wad,lump))
return 0;
@ -856,17 +1155,112 @@ size_t W_ReadLumpHeaderPwad(UINT16 wad, UINT16 lump, void *dest, size_t size, si
if (!size || size+offset > lumpsize)
size = lumpsize - offset;
if (wadfiles[wad]->lumpinfo[lump].compressed)
// Let's get the raw lump data.
// We setup the desired file handle to read the lump data.
l = wadfiles[wad]->lumpinfo + lump;
handle = wadfiles[wad]->handle;
fseek(handle, (long)(l->position + offset), SEEK_SET);
// But let's not copy it yet. We support different compression formats on lumps, so we need to take that into account.
switch(wadfiles[wad]->lumpinfo[lump].compression)
{
UINT8 *data;
data = W_ReadCompressedLump(wad, lump);
if (!data) return 0;
M_Memcpy(dest, data+offset, size);
Z_Free(data);
return size;
case CM_NOCOMPRESSION: // If it's uncompressed, we directly write the data into our destination, and return the bytes read.
return fread(dest, 1, size, handle);
case CM_LZF: // Is it LZF compressed? Used by ZWADs.
{
#ifdef ZWAD
char *rawData; // The lump's raw data.
char *decData; // Lump's decompressed real data.
size_t retval; // Helper var, lzf_decompress returns 0 when an error occurs.
rawData = Z_Malloc(l->disksize, PU_STATIC, NULL);
decData = Z_Malloc(l->size, PU_STATIC, NULL);
if (fread(rawData, 1, l->disksize, handle) < l->disksize)
I_Error("wad %d, lump %d: cannot read compressed data", wad, lump);
retval = lzf_decompress(rawData, l->disksize, decData, l->size);
#ifndef AVOID_ERRNO
if (retval == 0 && errno == E2BIG) // errno is a global var set by the lzf functions when something goes wrong.
{
I_Error("wad %d, lump %d: compressed data too big (bigger than %s)", wad, lump, sizeu1(l->size));
}
else if (retval == 0 && errno == EINVAL)
I_Error("wad %d, lump %d: invalid compressed data", wad, lump);
else
#endif
if (retval != l->size)
{
I_Error("wad %d, lump %d: decompressed to wrong number of bytes (expected %s, got %s)", wad, lump, sizeu1(l->size), sizeu2(retval));
}
#else
(void)wad;
(void)lump;
//I_Error("ZWAD files not supported on this platform.");
return NULL;
#endif
if (!decData) // Did we get no data at all?
return 0;
M_Memcpy(dest, decData + offset, size);
Z_Free(rawData);
Z_Free(decData);
return size;
}
case CM_DEFLATE: // Is it compressed via DEFLATE? Very common in ZIPs/PK3s, also what most doom-related editors support.
{
z_const Bytef *rawData; // The lump's raw data.
Bytef *decData; // Lump's decompressed real data.
int zErr; // Helper var.
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);
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
strm.total_in = strm.avail_in = rawSize;
strm.total_out = strm.avail_out = decSize;
strm.next_in = rawData;
strm.next_out = decData;
zErr = inflateInit2(&strm, -15);
if (zErr == Z_OK)
{
zErr = inflate(&strm, Z_FINISH);
if (zErr == Z_STREAM_END)
{
M_Memcpy(dest, decData, size);
}
else
{
size = 0;
zerr(zErr);
(void)inflateEnd(&strm);
}
}
else
{
CONS_Printf("whopet\n");
size = 0;
zerr(zErr);
}
Z_Free(rawData);
Z_Free(decData);
return size;
}
default:
I_Error("wad %d, lump %d: unsupported compression type!", wad, lump);
}
else
return W_RawReadLumpHeader(wad, lump, dest, size, offset);
}
size_t W_ReadLumpHeader(lumpnum_t lumpnum, void *dest, size_t size, size_t offset)
@ -1150,12 +1544,12 @@ static int W_VerifyFile(const char *filename, lumpchecklist_t *checklist,
if ((handle = W_OpenWadFile(&filename, false)) == NULL)
return -1;
// detect dehacked file with the "soc" extension
if (stricmp(&filename[strlen(filename) - 4], ".soc") != 0
// detect wad file by the absence of the other supported extensions
if (stricmp(&filename[strlen(filename) - 4], ".soc")
#ifdef HAVE_BLUA
&& stricmp(&filename[strlen(filename) - 4], ".lua") != 0
&& stricmp(&filename[strlen(filename) - 4], ".lua")
#endif
)
&& stricmp(&filename[strlen(filename) - 4], ".pk3"))
{
// assume wad file
wadinfo_t header;

View file

@ -22,6 +22,15 @@
#pragma interface
#endif
// a raw entry of the wad directory
// NOTE: This sits here and not in w_wad.c because p_setup.c makes use of it to load map WADs inside PK3s.
typedef struct
{
UINT32 filepos; // file offset of the resource
UINT32 size; // size of the resource
char name[8]; // name of the resource
} ATTRPACK filelump_t;
// ==============================================================
// WAD FILE STRUCTURE DEFINITIONS
// ==============================================================
@ -34,14 +43,25 @@ typedef struct
UINT32 infotableofs; // the 'directory' of resources
} wadinfo_t;
// Available compression methods for lumps.
typedef enum
{
CM_NOCOMPRESSION,
CM_DEFLATE,
CM_LZF,
CM_UNSUPPORTED
} compmethod;
// a memory entry of the wad directory
typedef struct
{
unsigned long position; // filelump_t filepos
unsigned long disksize; // filelump_t size
char name[9]; // filelump_t name[]
char *name2; // Used by PK3s. Dynamically allocated name.
size_t size; // real (uncompressed) size
INT32 compressed; // i
compmethod compression; // lump compression method
} lumpinfo_t;
// =========================================================================
@ -58,9 +78,19 @@ typedef struct
#include "m_aatree.h"
#endif
// Resource type of the WAD. Yeah, I know this sounds dumb, but I'll leave it like this until I clean up the code further.
typedef enum restype
{
RET_WAD,
RET_SOC,
RET_LUA,
RET_PK3
} restype_t;
typedef struct wadfile_s
{
char *filename;
restype_t type;
lumpinfo_t *lumpinfo;
lumpcache_t *lumpcache;
#ifdef HWRENDER
@ -85,7 +115,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
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
UINT16 W_LoadWadFile(const char *filename);
UINT16 W_InitFile(const char *filename);
#ifdef DELFILE
void W_UnloadWadFile(UINT16 num);
#endif
@ -98,6 +128,12 @@ const char *W_CheckNameForNumPwad(UINT16 wad, UINT16 lump);
const char *W_CheckNameForNum(lumpnum_t lumpnum);
UINT16 W_CheckNumForNamePwad(const char *name, UINT16 wad, UINT16 startlump); // checks only in one pwad
UINT16 W_CheckNumForFullNamePK3(const char *name, UINT16 wad, UINT16 startlump);
UINT16 W_CheckNumForFolderStartPK3(const char *name, UINT16 wad, UINT16 startlump);
UINT16 W_CheckNumForFolderEndPK3(const char *name, UINT16 wad, UINT16 startlump);
lumpnum_t W_CheckNumForMap(const char *name);
lumpnum_t W_CheckNumForName(const char *name);
lumpnum_t W_GetNumForName(const char *name); // like W_CheckNumForName but I_Error on LUMPERROR
lumpnum_t W_CheckNumForNameInBlock(const char *name, const char *blockstart, const char *blockend);
@ -106,6 +142,10 @@ UINT8 W_LumpExists(const char *name); // Lua uses this.
size_t W_LumpLengthPwad(UINT16 wad, UINT16 lump);
size_t W_LumpLength(lumpnum_t lumpnum);
boolean W_IsLumpWad(lumpnum_t lumpnum); // for loading maps from WADs in PK3s
void zerr(int ret); // zlib error checking
size_t W_ReadLumpHeaderPwad(UINT16 wad, UINT16 lump, void *dest, size_t size, size_t offset);
size_t W_ReadLumpHeader(lumpnum_t lump, void *dest, size_t size, size_t offest); // read all or a part of a lump
void W_ReadLumpPwad(UINT16 wad, UINT16 lump, void *dest);