mirror of
https://git.do.srb2.org/STJr/SRB2.git
synced 2025-01-18 15:32:33 +00:00
Experimental implementation
This commit is contained in:
parent
91c9d667e1
commit
dca158096d
18 changed files with 1007 additions and 95 deletions
|
@ -274,7 +274,7 @@ static int luaB_dofile (lua_State *L) {
|
|||
UINT16 lumpnum;
|
||||
int n = lua_gettop(L);
|
||||
|
||||
if (wadfiles[numwadfiles - 1]->type != RET_PK3)
|
||||
if (!W_FileHasFolders(wadfiles[numwadfiles - 1]))
|
||||
luaL_error(L, "dofile() only works with PK3 files");
|
||||
|
||||
snprintf(fullfilename, sizeof(fullfilename), "Lua/%s", filename);
|
||||
|
|
|
@ -4486,9 +4486,9 @@ static INT16 Consistancy(void)
|
|||
{
|
||||
if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed)
|
||||
continue;
|
||||
|
||||
|
||||
mo = (mobj_t *)th;
|
||||
|
||||
|
||||
if (mo->flags & (MF_SPECIAL | MF_SOLID | MF_PUSHABLE | MF_BOSS | MF_MISSILE | MF_SPRING | MF_MONITOR | MF_FIRE | MF_ENEMY | MF_PAIN | MF_STICKY))
|
||||
{
|
||||
ret -= mo->type;
|
||||
|
|
35
src/d_main.c
35
src/d_main.c
|
@ -873,10 +873,26 @@ static void D_AddFile(char **list, const char *file)
|
|||
|
||||
newfile = malloc(strlen(file) + 1);
|
||||
if (!newfile)
|
||||
{
|
||||
I_Error("No more free memory to AddFile %s",file);
|
||||
}
|
||||
|
||||
strcpy(newfile, file);
|
||||
list[pnumwadfiles] = newfile;
|
||||
}
|
||||
|
||||
static void D_AddFolder(char **list, const char *file)
|
||||
{
|
||||
size_t pnumwadfiles, len = strlen(file);
|
||||
char *newfile;
|
||||
|
||||
for (pnumwadfiles = 0; list[pnumwadfiles]; pnumwadfiles++)
|
||||
;
|
||||
|
||||
newfile = malloc(len + 2); // NULL terminator + path separator
|
||||
if (!newfile)
|
||||
I_Error("No more free memory to AddFolder %s",file);
|
||||
|
||||
strcpy(newfile, file);
|
||||
strcat(newfile, PATHSEP);
|
||||
|
||||
list[pnumwadfiles] = newfile;
|
||||
}
|
||||
|
@ -1180,7 +1196,7 @@ void D_SRB2Main(void)
|
|||
{
|
||||
if (M_CheckParm("-file"))
|
||||
{
|
||||
// the parms after p are wadfile/lump names,
|
||||
// the parms after p are wadfile names,
|
||||
// until end of parms or another - preceded parm
|
||||
while (M_IsNextParm())
|
||||
{
|
||||
|
@ -1190,6 +1206,19 @@ void D_SRB2Main(void)
|
|||
D_AddFile(startuppwads, s);
|
||||
}
|
||||
}
|
||||
|
||||
if (M_CheckParm("-folder"))
|
||||
{
|
||||
// the parms after p are folder names,
|
||||
// until end of parms or another - preceded parm
|
||||
while (M_IsNextParm())
|
||||
{
|
||||
const char *s = M_GetNextParm();
|
||||
|
||||
if (s) // Check for NULL?
|
||||
D_AddFolder(startuppwads, s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// get map from parms
|
||||
|
|
204
src/d_netcmd.c
204
src/d_netcmd.c
|
@ -63,7 +63,9 @@ static void Got_WeaponPref(UINT8 **cp, INT32 playernum);
|
|||
static void Got_Mapcmd(UINT8 **cp, INT32 playernum);
|
||||
static void Got_ExitLevelcmd(UINT8 **cp, INT32 playernum);
|
||||
static void Got_RequestAddfilecmd(UINT8 **cp, INT32 playernum);
|
||||
static void Got_RequestAddfoldercmd(UINT8 **cp, INT32 playernum);
|
||||
static void Got_Addfilecmd(UINT8 **cp, INT32 playernum);
|
||||
static void Got_Addfoldercmd(UINT8 **cp, INT32 playernum);
|
||||
static void Got_Pause(UINT8 **cp, INT32 playernum);
|
||||
static void Got_Suicide(UINT8 **cp, INT32 playernum);
|
||||
static void Got_RandomSeed(UINT8 **cp, INT32 playernum);
|
||||
|
@ -115,6 +117,7 @@ static void Command_Map_f(void);
|
|||
static void Command_ResetCamera_f(void);
|
||||
|
||||
static void Command_Addfile(void);
|
||||
static void Command_Addfolder(void);
|
||||
static void Command_ListWADS_f(void);
|
||||
static void Command_RunSOC(void);
|
||||
static void Command_Pause(void);
|
||||
|
@ -398,16 +401,16 @@ const char *netxcmdnames[MAXNETXCMD - 1] =
|
|||
"MAP",
|
||||
"EXITLEVEL",
|
||||
"ADDFILE",
|
||||
"ADDFOLDER",
|
||||
"PAUSE",
|
||||
"ADDPLAYER",
|
||||
"TEAMCHANGE",
|
||||
"CLEARSCORES",
|
||||
"LOGIN",
|
||||
"VERIFIED",
|
||||
"RANDOMSEED",
|
||||
"RUNSOC",
|
||||
"REQADDFILE",
|
||||
"DELFILE", // replace next time we add an XD
|
||||
"REQADDFOLDER",
|
||||
"SETMOTD",
|
||||
"SUICIDE",
|
||||
"LUACMD",
|
||||
|
@ -441,7 +444,9 @@ void D_RegisterServerCommands(void)
|
|||
RegisterNetXCmd(XD_MAP, Got_Mapcmd);
|
||||
RegisterNetXCmd(XD_EXITLEVEL, Got_ExitLevelcmd);
|
||||
RegisterNetXCmd(XD_ADDFILE, Got_Addfilecmd);
|
||||
RegisterNetXCmd(XD_ADDFOLDER, Got_Addfoldercmd);
|
||||
RegisterNetXCmd(XD_REQADDFILE, Got_RequestAddfilecmd);
|
||||
RegisterNetXCmd(XD_REQADDFOLDER, Got_RequestAddfoldercmd);
|
||||
RegisterNetXCmd(XD_PAUSE, Got_Pause);
|
||||
RegisterNetXCmd(XD_SUICIDE, Got_Suicide);
|
||||
RegisterNetXCmd(XD_RUNSOC, Got_RunSOCcmd);
|
||||
|
@ -472,6 +477,7 @@ void D_RegisterServerCommands(void)
|
|||
COM_AddCommand("showmap", Command_Showmap_f);
|
||||
COM_AddCommand("mapmd5", Command_Mapmd5_f);
|
||||
|
||||
COM_AddCommand("addfolder", Command_Addfolder);
|
||||
COM_AddCommand("addfile", Command_Addfile);
|
||||
COM_AddCommand("listwad", Command_ListWADS_f);
|
||||
|
||||
|
@ -3323,9 +3329,9 @@ static void Command_Addfile(void)
|
|||
++p;
|
||||
|
||||
// check total packet size and no of files currently loaded
|
||||
// See W_LoadWadFile in w_wad.c
|
||||
// See W_InitFile in w_wad.c
|
||||
if ((numwadfiles >= MAX_WADFILES)
|
||||
|| ((packetsizetally + nameonlylength(fn) + 22) > MAXFILENEEDED*sizeof(UINT8)))
|
||||
|| ((packetsizetally + nameonlylength(fn) + FILENEEDEDSIZE) > MAXFILENEEDED*sizeof(UINT8)))
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, M_GetText("Too many files loaded to add %s\n"), fn);
|
||||
return;
|
||||
|
@ -3373,6 +3379,89 @@ static void Command_Addfile(void)
|
|||
}
|
||||
}
|
||||
|
||||
static void Command_Addfolder(void)
|
||||
{
|
||||
size_t argc = COM_Argc(); // amount of arguments total
|
||||
size_t curarg; // current argument index
|
||||
|
||||
const char *addedfolders[argc]; // list of filenames already processed
|
||||
size_t numfoldersadded = 0; // the amount of filenames processed
|
||||
|
||||
if (argc < 2)
|
||||
{
|
||||
CONS_Printf(M_GetText("addfolder <path> [path2...] [...]: Load add-ons\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
// start at one to skip command name
|
||||
for (curarg = 1; curarg < argc; curarg++)
|
||||
{
|
||||
const char *fn, *p;
|
||||
char buf[256];
|
||||
char *buf_p = buf;
|
||||
INT32 i;
|
||||
size_t ii;
|
||||
boolean folderadded = false;
|
||||
|
||||
fn = COM_Argv(curarg);
|
||||
|
||||
// For the amount of filenames previously processed...
|
||||
for (ii = 0; ii < numfoldersadded; ii++)
|
||||
{
|
||||
// If this is one of them, don't try to add it.
|
||||
if (!strcmp(fn, addedfolders[ii]))
|
||||
{
|
||||
folderadded = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If we've added this one, skip to the next one.
|
||||
if (folderadded)
|
||||
{
|
||||
CONS_Alert(CONS_WARNING, M_GetText("Already processed %s, skipping\n"), fn);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Disallow non-printing characters and semicolons.
|
||||
for (i = 0; fn[i] != '\0'; i++)
|
||||
if (!isprint(fn[i]) || fn[i] == ';')
|
||||
return;
|
||||
|
||||
// Add file on your client directly if you aren't in a netgame.
|
||||
if (!(netgame || multiplayer))
|
||||
{
|
||||
P_AddFolder(fn);
|
||||
addedfolders[numfoldersadded++] = fn;
|
||||
continue;
|
||||
}
|
||||
|
||||
p = fn+strlen(fn);
|
||||
while(--p >= fn)
|
||||
if (*p == '\\' || *p == '/' || *p == ':')
|
||||
break;
|
||||
++p;
|
||||
|
||||
// check total packet size and no of files currently loaded
|
||||
// See W_InitFile in w_wad.c
|
||||
if ((numwadfiles >= MAX_WADFILES)
|
||||
|| ((packetsizetally + strlen(fn) + FILENEEDEDSIZE) > MAXFILENEEDED*sizeof(UINT8)))
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, M_GetText("Too many files loaded to add %s\n"), fn);
|
||||
return;
|
||||
}
|
||||
|
||||
WRITESTRINGN(buf_p,p,240);
|
||||
|
||||
addedfolders[numfoldersadded++] = fn;
|
||||
|
||||
if (IsPlayerAdmin(consoleplayer) && (!server)) // Request to add file
|
||||
SendNetXCmd(XD_REQADDFOLDER, buf, buf_p - buf);
|
||||
else
|
||||
SendNetXCmd(XD_ADDFOLDER, buf, buf_p - buf);
|
||||
}
|
||||
}
|
||||
|
||||
static void Got_RequestAddfilecmd(UINT8 **cp, INT32 playernum)
|
||||
{
|
||||
char filename[241];
|
||||
|
@ -3401,9 +3490,9 @@ static void Got_RequestAddfilecmd(UINT8 **cp, INT32 playernum)
|
|||
return;
|
||||
}
|
||||
|
||||
// See W_LoadWadFile in w_wad.c
|
||||
// See W_InitFile in w_wad.c
|
||||
if ((numwadfiles >= MAX_WADFILES)
|
||||
|| ((packetsizetally + nameonlylength(filename) + 22) > MAXFILENEEDED*sizeof(UINT8)))
|
||||
|| ((packetsizetally + nameonlylength(filename) + FILENEEDEDSIZE) > MAXFILENEEDED*sizeof(UINT8)))
|
||||
toomany = true;
|
||||
else
|
||||
ncs = findfile(filename,md5sum,true);
|
||||
|
@ -3433,6 +3522,64 @@ static void Got_RequestAddfilecmd(UINT8 **cp, INT32 playernum)
|
|||
COM_BufAddText(va("addfile %s\n", filename));
|
||||
}
|
||||
|
||||
static void Got_RequestAddfoldercmd(UINT8 **cp, INT32 playernum)
|
||||
{
|
||||
char path[241];
|
||||
filestatus_t ncs = FS_NOTFOUND;
|
||||
boolean kick = false;
|
||||
boolean toomany = false;
|
||||
INT32 i,j;
|
||||
|
||||
READSTRINGN(*cp, path, 240);
|
||||
|
||||
/// \todo Integrity checks.
|
||||
|
||||
// Only the server processes this message.
|
||||
if (client)
|
||||
return;
|
||||
|
||||
// Disallow non-printing characters and semicolons.
|
||||
for (i = 0; path[i] != '\0'; i++)
|
||||
if (!isprint(path[i]) || path[i] == ';')
|
||||
kick = true;
|
||||
|
||||
if ((playernum != serverplayer && !IsPlayerAdmin(playernum)) || kick)
|
||||
{
|
||||
CONS_Alert(CONS_WARNING, M_GetText("Illegal addfolder command received from %s\n"), player_names[playernum]);
|
||||
SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY);
|
||||
return;
|
||||
}
|
||||
|
||||
// See W_InitFile in w_wad.c
|
||||
if ((numwadfiles >= MAX_WADFILES)
|
||||
|| ((packetsizetally + strlen(path) + FILENEEDEDSIZE) > MAXFILENEEDED*sizeof(UINT8)))
|
||||
toomany = true;
|
||||
else
|
||||
ncs = findfolder(path);
|
||||
|
||||
if (ncs != FS_FOUND || toomany)
|
||||
{
|
||||
char message[256];
|
||||
|
||||
if (toomany)
|
||||
sprintf(message, M_GetText("Too many files loaded to add %s\n"), path);
|
||||
else if (ncs == FS_NOTFOUND)
|
||||
sprintf(message, M_GetText("The server doesn't have %s\n"), path);
|
||||
else
|
||||
sprintf(message, M_GetText("Unknown error finding folder (%s)\n"), path);
|
||||
|
||||
CONS_Printf("%s",message);
|
||||
|
||||
for (j = 0; j < MAXPLAYERS; j++)
|
||||
if (adminplayers[j])
|
||||
COM_BufAddText(va("sayto %d %s", adminplayers[j], message));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
COM_BufAddText(va("addfolder \"%s\"\n", path));
|
||||
}
|
||||
|
||||
static void Got_Addfilecmd(UINT8 **cp, INT32 playernum)
|
||||
{
|
||||
char filename[241];
|
||||
|
@ -3481,6 +3628,49 @@ static void Got_Addfilecmd(UINT8 **cp, INT32 playernum)
|
|||
G_SetGameModified(true);
|
||||
}
|
||||
|
||||
static void Got_Addfoldercmd(UINT8 **cp, INT32 playernum)
|
||||
{
|
||||
char path[241];
|
||||
filestatus_t ncs = FS_NOTFOUND;
|
||||
|
||||
READSTRINGN(*cp, path, 240);
|
||||
|
||||
/// \todo Integrity checks.
|
||||
|
||||
if (playernum != serverplayer)
|
||||
{
|
||||
CONS_Alert(CONS_WARNING, M_GetText("Illegal addfolder command received from %s\n"), player_names[playernum]);
|
||||
if (server)
|
||||
SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY);
|
||||
return;
|
||||
}
|
||||
|
||||
ncs = findfolder(path);
|
||||
|
||||
if (ncs != FS_FOUND || !P_AddFolder(path))
|
||||
{
|
||||
Command_ExitGame_f();
|
||||
if (ncs == FS_FOUND)
|
||||
{
|
||||
CONS_Printf(M_GetText("The server tried to add %s,\nbut you have too many files added.\nRestart the game to clear loaded files\nand play on this server."), path);
|
||||
M_StartMessage(va("The server added a folder \n(%s)\nbut you have too many files added.\nRestart the game to clear loaded files.\n\nPress ESC\n",path), NULL, MM_NOTHING);
|
||||
}
|
||||
else if (ncs == FS_NOTFOUND)
|
||||
{
|
||||
CONS_Printf(M_GetText("The server tried to add %s,\nbut you don't have this file.\nYou need to find it in order\nto play on this server."), path);
|
||||
M_StartMessage(va("The server added a folder \n(%s)\nthat you do not have.\n\nPress ESC\n",path), NULL, MM_NOTHING);
|
||||
}
|
||||
else
|
||||
{
|
||||
CONS_Printf(M_GetText("Unknown error finding folder (%s) the server added.\n"), path);
|
||||
M_StartMessage(va("Unknown error trying to load a folder\nthat the server added \n(%s).\n\nPress ESC\n",path), NULL, MM_NOTHING);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
G_SetGameModified(true);
|
||||
}
|
||||
|
||||
static void Command_ListWADS_f(void)
|
||||
{
|
||||
INT32 i = numwadfiles;
|
||||
|
@ -3495,6 +3685,8 @@ static void Command_ListWADS_f(void)
|
|||
CONS_Printf("\x82 * %.2d\x80: %s\n", i, tempname);
|
||||
else if (!wadfiles[i]->important)
|
||||
CONS_Printf("\x86 %.2d: %s\n", i, tempname);
|
||||
else if (wadfiles[i]->type == RET_FOLDER)
|
||||
CONS_Printf("\x82 * %.2d\x84: %s\n", i, tempname);
|
||||
else
|
||||
CONS_Printf(" %.2d: %s\n", i, tempname);
|
||||
}
|
||||
|
|
|
@ -128,16 +128,16 @@ typedef enum
|
|||
XD_MAP, // 6
|
||||
XD_EXITLEVEL, // 7
|
||||
XD_ADDFILE, // 8
|
||||
XD_PAUSE, // 9
|
||||
XD_ADDPLAYER, // 10
|
||||
XD_TEAMCHANGE, // 11
|
||||
XD_CLEARSCORES, // 12
|
||||
// UNUSED 13 (Because I don't want to change these comments)
|
||||
XD_VERIFIED = 14,//14
|
||||
XD_ADDFOLDER, // 9
|
||||
XD_PAUSE, // 10
|
||||
XD_ADDPLAYER, // 11
|
||||
XD_TEAMCHANGE, // 12
|
||||
XD_CLEARSCORES, // 13
|
||||
XD_VERIFIED, // 14
|
||||
XD_RANDOMSEED, // 15
|
||||
XD_RUNSOC, // 16
|
||||
XD_REQADDFILE, // 17
|
||||
XD_DELFILE, // 18 - replace next time we add an XD
|
||||
XD_REQADDFOLDER,// 18
|
||||
XD_SETMOTD, // 19
|
||||
XD_SUICIDE, // 20
|
||||
XD_DEMOTED, // 21
|
||||
|
|
|
@ -120,7 +120,7 @@ char luafiledir[256 + 16] = "luafiles";
|
|||
/** Fills a serverinfo packet with information about wad files loaded.
|
||||
*
|
||||
* \todo Give this function a better name since it is in global scope.
|
||||
* Used to have size limiting built in - now handled via W_LoadWadFile in w_wad.c
|
||||
* Used to have size limiting built in - now handled via W_InitFile in w_wad.c
|
||||
*
|
||||
*/
|
||||
UINT8 *PutFileNeeded(void)
|
||||
|
@ -128,7 +128,7 @@ UINT8 *PutFileNeeded(void)
|
|||
size_t i, count = 0;
|
||||
UINT8 *p = netbuffer->u.serverinfo.fileneeded;
|
||||
char wadfilename[MAX_WADPATH] = "";
|
||||
UINT8 filestatus;
|
||||
UINT8 filestatus, folder;
|
||||
|
||||
for (i = 0; i < numwadfiles; i++)
|
||||
{
|
||||
|
@ -137,9 +137,10 @@ UINT8 *PutFileNeeded(void)
|
|||
continue;
|
||||
|
||||
filestatus = 1; // Importance - not really used any more, holds 1 by default for backwards compat with MS
|
||||
folder = (wadfiles[i]->type == RET_FOLDER);
|
||||
|
||||
// Store in the upper four bits
|
||||
if (!cv_downloading.value)
|
||||
if (!cv_downloading.value || folder) /// \todo Implement folder downloading.
|
||||
filestatus += (2 << 4); // Won't send
|
||||
else if ((wadfiles[i]->filesize <= (UINT32)cv_maxsend.value * 1024))
|
||||
filestatus += (1 << 4); // Will send if requested
|
||||
|
@ -147,6 +148,7 @@ UINT8 *PutFileNeeded(void)
|
|||
// filestatus += (0 << 4); -- Won't send, too big
|
||||
|
||||
WRITEUINT8(p, filestatus);
|
||||
WRITEUINT8(p, folder);
|
||||
|
||||
count++;
|
||||
WRITEUINT32(p, wadfiles[i]->filesize);
|
||||
|
@ -178,6 +180,7 @@ void D_ParseFileneeded(INT32 fileneedednum_parm, UINT8 *fileneededstr)
|
|||
fileneeded[i].status = FS_NOTFOUND; // We haven't even started looking for the file yet
|
||||
fileneeded[i].justdownloaded = false;
|
||||
filestatus = READUINT8(p); // The first byte is the file status
|
||||
fileneeded[i].folder = READUINT8(p); // The second byte is the folder flag
|
||||
fileneeded[i].willsend = (UINT8)(filestatus >> 4);
|
||||
fileneeded[i].totalsize = READUINT32(p); // The four next bytes are the file size
|
||||
fileneeded[i].file = NULL; // The file isn't open yet
|
||||
|
@ -420,7 +423,7 @@ INT32 CL_CheckFiles(void)
|
|||
return 1;
|
||||
}
|
||||
|
||||
// See W_LoadWadFile in w_wad.c
|
||||
// See W_InitFile in w_wad.c
|
||||
packetsize = packetsizetally;
|
||||
|
||||
for (i = 1; i < fileneedednum; i++)
|
||||
|
@ -442,7 +445,10 @@ INT32 CL_CheckFiles(void)
|
|||
if (fileneeded[i].status != FS_NOTFOUND)
|
||||
continue;
|
||||
|
||||
packetsize += nameonlylength(fileneeded[i].filename) + 22;
|
||||
if (fileneeded[i].folder)
|
||||
packetsize += strlen(fileneeded[i].filename) + FILENEEDEDSIZE;
|
||||
else
|
||||
packetsize += nameonlylength(fileneeded[i].filename) + FILENEEDEDSIZE;
|
||||
|
||||
if ((numwadfiles+filestoget >= MAX_WADFILES)
|
||||
|| (packetsize > MAXFILENEEDED*sizeof(UINT8)))
|
||||
|
@ -450,7 +456,10 @@ INT32 CL_CheckFiles(void)
|
|||
|
||||
filestoget++;
|
||||
|
||||
fileneeded[i].status = findfile(fileneeded[i].filename, fileneeded[i].md5sum, true);
|
||||
if (fileneeded[i].folder)
|
||||
fileneeded[i].status = findfolder(fileneeded[i].filename);
|
||||
else
|
||||
fileneeded[i].status = findfile(fileneeded[i].filename, fileneeded[i].md5sum, true);
|
||||
CONS_Debug(DBG_NETPLAY, "found %d\n", fileneeded[i].status);
|
||||
if (fileneeded[i].status != FS_FOUND)
|
||||
ret = 0;
|
||||
|
@ -472,7 +481,10 @@ void CL_LoadServerFiles(void)
|
|||
continue; // Already loaded
|
||||
else if (fileneeded[i].status == FS_FOUND)
|
||||
{
|
||||
P_AddWadFile(fileneeded[i].filename);
|
||||
if (fileneeded[i].folder)
|
||||
P_AddFolder(fileneeded[i].filename);
|
||||
else
|
||||
P_AddWadFile(fileneeded[i].filename);
|
||||
G_SetGameModified(true);
|
||||
fileneeded[i].status = FS_OPEN;
|
||||
}
|
||||
|
@ -757,7 +769,7 @@ static boolean AddFileToSendQueue(INT32 node, const char *filename, UINT8 fileid
|
|||
// This formerly checked if (!findfile(p->id.filename, NULL, true))
|
||||
|
||||
// Not found
|
||||
// Don't inform client (probably someone who thought they could leak 2.2 ACZ)
|
||||
// Don't inform client
|
||||
DEBFILE(va("Client %d request %s: not found\n", node, filename));
|
||||
free(p->id.filename);
|
||||
free(p);
|
||||
|
@ -1556,3 +1568,23 @@ filestatus_t findfile(char *filename, const UINT8 *wantedmd5sum, boolean complet
|
|||
|
||||
return (badmd5 ? FS_MD5SUMBAD : FS_NOTFOUND); // md5 sum bad or file not found
|
||||
}
|
||||
|
||||
filestatus_t findfolder(const char *path)
|
||||
{
|
||||
// Check the path by itself first.
|
||||
if (checkfolderpath(path, NULL, true))
|
||||
return FS_FOUND;
|
||||
|
||||
#define checkpath(startpath) { \
|
||||
if (checkfolderpath(path, startpath, true)) \
|
||||
return FS_FOUND; \
|
||||
}
|
||||
|
||||
checkpath(srb2home) // Then, look in srb2home.
|
||||
checkpath(srb2path) // Now, look in srb2path.
|
||||
checkpath(".") // Finally, look in ".".
|
||||
|
||||
#undef checkpath
|
||||
|
||||
return FS_NOTFOUND;
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@ typedef enum
|
|||
typedef struct
|
||||
{
|
||||
UINT8 willsend; // Is the server willing to send it?
|
||||
UINT8 folder; // File is a folder
|
||||
char filename[MAX_WADPATH];
|
||||
UINT8 md5sum[16];
|
||||
filestatus_t status; // The value returned by recsearch
|
||||
|
@ -54,6 +55,8 @@ typedef struct
|
|||
UINT32 ackresendposition; // Used when resuming downloads
|
||||
} fileneeded_t;
|
||||
|
||||
#define FILENEEDEDSIZE 23
|
||||
|
||||
extern INT32 fileneedednum;
|
||||
extern fileneeded_t fileneeded[MAX_WADFILES];
|
||||
extern char downloaddir[512];
|
||||
|
@ -133,6 +136,9 @@ filestatus_t findfile(char *filename, const UINT8 *wantedmd5sum,
|
|||
boolean completepath);
|
||||
filestatus_t checkfilemd5(char *filename, const UINT8 *wantedmd5sum);
|
||||
|
||||
// Searches for a folder
|
||||
filestatus_t findfolder(const char *path);
|
||||
|
||||
void nameonly(char *s);
|
||||
size_t nameonlylength(const char *s);
|
||||
|
||||
|
|
345
src/filesrch.c
345
src/filesrch.c
|
@ -29,6 +29,7 @@
|
|||
#include "m_misc.h"
|
||||
#include "z_zone.h"
|
||||
#include "m_menu.h" // Addons_option_Onchange
|
||||
#include "w_wad.h"
|
||||
|
||||
#if defined (_WIN32) && defined (_MSC_VER)
|
||||
|
||||
|
@ -340,6 +341,11 @@ char *refreshdirname = NULL;
|
|||
size_t packetsizetally = 0;
|
||||
size_t mainwadstally = 0;
|
||||
|
||||
#define folderpathlen 1024
|
||||
#define maxfolderdepth 48
|
||||
|
||||
#define isuptree(dirent) ((dirent)[0]=='.' && ((dirent)[1]=='\0' || ((dirent)[1]=='.' && (dirent)[2]=='\0')))
|
||||
|
||||
filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *wantedmd5sum, boolean completepath, int maxsearchdepth)
|
||||
{
|
||||
filestatus_t retval = FS_NOTFOUND;
|
||||
|
@ -387,10 +393,7 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want
|
|||
continue;
|
||||
}
|
||||
|
||||
if (dent->d_name[0]=='.' &&
|
||||
(dent->d_name[1]=='\0' ||
|
||||
(dent->d_name[1]=='.' &&
|
||||
dent->d_name[2]=='\0')))
|
||||
if (isuptree(dent->d_name))
|
||||
{
|
||||
// we don't want to scan uptree
|
||||
continue;
|
||||
|
@ -445,6 +448,329 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want
|
|||
return retval;
|
||||
}
|
||||
|
||||
// Called from findfolder and ResGetLumpsFolder in w_wad.c.
|
||||
// Call with cleanup true if the path has to be verified.
|
||||
boolean checkfolderpath(const char *path, const char *startpath, boolean cleanup)
|
||||
{
|
||||
char folderpath[folderpathlen], basepath[folderpathlen], *fn = NULL;
|
||||
DIR *dirhandle;
|
||||
|
||||
// Remove path separators from the filename, and don't try adding "/".
|
||||
// See also the same code in W_InitFolder.
|
||||
if (cleanup)
|
||||
{
|
||||
const char *p = path + strlen(path);
|
||||
size_t len;
|
||||
|
||||
--p;
|
||||
while (*p == '\\' || *p == '/' || *p == ':')
|
||||
{
|
||||
p--;
|
||||
if (p < path)
|
||||
return false;
|
||||
}
|
||||
++p;
|
||||
|
||||
// Allocate the new path name.
|
||||
len = (p - path) + 1;
|
||||
fn = ZZ_Alloc(len);
|
||||
strlcpy(fn, path, len);
|
||||
}
|
||||
|
||||
if (startpath)
|
||||
{
|
||||
snprintf(basepath, sizeof basepath, "%s" PATHSEP, startpath);
|
||||
|
||||
if (cleanup)
|
||||
{
|
||||
snprintf(folderpath, sizeof folderpath, "%s%s", basepath, fn);
|
||||
Z_Free(fn); // Don't need this anymore.
|
||||
}
|
||||
else
|
||||
snprintf(folderpath, sizeof folderpath, "%s%s", basepath, path);
|
||||
|
||||
// Home path and folder path are the same? Not valid.
|
||||
if (!strcmp(basepath, folderpath))
|
||||
return false;
|
||||
}
|
||||
else if (cleanup)
|
||||
{
|
||||
snprintf(folderpath, sizeof folderpath, "%s", fn);
|
||||
Z_Free(fn); // Don't need this anymore.
|
||||
}
|
||||
else
|
||||
snprintf(folderpath, sizeof folderpath, "%s", path);
|
||||
|
||||
dirhandle = opendir(folderpath);
|
||||
if (dirhandle == NULL)
|
||||
return false;
|
||||
else
|
||||
closedir(dirhandle);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
INT32 pathisfolder(const char *path)
|
||||
{
|
||||
struct stat fsstat;
|
||||
|
||||
if (stat(path, &fsstat) < 0)
|
||||
return -1;
|
||||
else if (S_ISDIR(fsstat.st_mode))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
INT32 samepaths(const char *path1, const char *path2)
|
||||
{
|
||||
struct stat stat1;
|
||||
struct stat stat2;
|
||||
|
||||
if (stat(path1, &stat1) < 0)
|
||||
return -1;
|
||||
if (stat(path2, &stat2) < 0)
|
||||
return -1;
|
||||
|
||||
if (stat1.st_dev == stat2.st_dev)
|
||||
{
|
||||
#if !defined(_WIN32)
|
||||
return (stat1.st_ino == stat2.st_ino);
|
||||
#else
|
||||
HANDLE file1 = CreateFileA(path1, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
|
||||
HANDLE file2 = CreateFileA(path2, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
|
||||
BY_HANDLE_FILE_INFORMATION file1info, file2info;
|
||||
boolean ok = false;
|
||||
|
||||
if (file1 != INVALID_HANDLE_VALUE && file2 != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
if (GetFileInformationByHandle(file1, &file1info) && GetFileInformationByHandle(file2, &file2info))
|
||||
{
|
||||
if (file1info.dwVolumeSerialNumber == file2info.dwVolumeSerialNumber
|
||||
&& file1info.nFileIndexLow == file2info.nFileIndexLow
|
||||
&& file1info.nFileIndexHigh == file2info.nFileIndexHigh)
|
||||
ok = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (file1 != INVALID_HANDLE_VALUE)
|
||||
CloseHandle(file1);
|
||||
if (file2 != INVALID_HANDLE_VALUE)
|
||||
CloseHandle(file2);
|
||||
|
||||
return ok;
|
||||
#endif
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// Folder loading
|
||||
//
|
||||
|
||||
static void initfolderpath(char *folderpath, size_t *folderpathindex, int depthleft)
|
||||
{
|
||||
folderpathindex[depthleft] = strlen(folderpath) + 1;
|
||||
|
||||
if (folderpath[folderpathindex[depthleft]-2] != PATHSEP[0])
|
||||
{
|
||||
folderpath[folderpathindex[depthleft]-1] = PATHSEP[0];
|
||||
folderpath[folderpathindex[depthleft]] = 0;
|
||||
}
|
||||
else
|
||||
folderpathindex[depthleft]--;
|
||||
}
|
||||
|
||||
lumpinfo_t *getfolderfiles(const char *path, UINT16 *nlmp, UINT16 *nfiles, UINT16 *nfolders)
|
||||
{
|
||||
DIR **dirhandle;
|
||||
struct dirent *dent;
|
||||
struct stat fsstat;
|
||||
|
||||
int rootfolder = (maxfolderdepth - 1);
|
||||
int depthleft = rootfolder;
|
||||
|
||||
char folderpath[folderpathlen];
|
||||
size_t *folderpathindex;
|
||||
|
||||
lumpinfo_t *lumpinfo, *lump_p;
|
||||
UINT16 i = 0, numlumps = (*nlmp);
|
||||
|
||||
dirhandle = (DIR **)malloc(maxfolderdepth * sizeof (DIR*));
|
||||
folderpathindex = (size_t *)malloc(maxfolderdepth * sizeof(size_t));
|
||||
|
||||
// Open the root directory
|
||||
strlcpy(folderpath, path, folderpathlen);
|
||||
dirhandle[depthleft] = opendir(folderpath);
|
||||
|
||||
if (dirhandle[depthleft] == NULL)
|
||||
{
|
||||
free(dirhandle);
|
||||
free(folderpathindex);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
initfolderpath(folderpath, folderpathindex, depthleft);
|
||||
(*nfiles) = 0;
|
||||
(*nfolders) = 0;
|
||||
|
||||
// Count files and directories
|
||||
while (depthleft < maxfolderdepth)
|
||||
{
|
||||
folderpath[folderpathindex[depthleft]] = 0;
|
||||
dent = readdir(dirhandle[depthleft]);
|
||||
|
||||
if (!dent)
|
||||
{
|
||||
if (depthleft != rootfolder) // Don't close the root directory
|
||||
closedir(dirhandle[depthleft]);
|
||||
depthleft++;
|
||||
continue;
|
||||
}
|
||||
else if (isuptree(dent->d_name))
|
||||
continue;
|
||||
|
||||
strcpy(&folderpath[folderpathindex[depthleft]], dent->d_name);
|
||||
|
||||
if (stat(folderpath, &fsstat) < 0)
|
||||
;
|
||||
else if (S_ISDIR(fsstat.st_mode) && depthleft)
|
||||
{
|
||||
folderpathindex[--depthleft] = strlen(folderpath) + 1;
|
||||
dirhandle[depthleft] = opendir(folderpath);
|
||||
|
||||
if (dirhandle[depthleft])
|
||||
{
|
||||
numlumps++;
|
||||
(*nfolders)++;
|
||||
}
|
||||
else
|
||||
depthleft++;
|
||||
|
||||
folderpath[folderpathindex[depthleft]-1] = '/';
|
||||
folderpath[folderpathindex[depthleft]] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
numlumps++;
|
||||
(*nfiles)++;
|
||||
}
|
||||
|
||||
if (numlumps == (UINT16_MAX-1))
|
||||
break;
|
||||
}
|
||||
|
||||
// Failure: No files have been found.
|
||||
if (!(*nfiles))
|
||||
{
|
||||
(*nfiles) = UINT16_MAX;
|
||||
free(folderpathindex);
|
||||
free(dirhandle);
|
||||
for (; depthleft < maxfolderdepth; closedir(dirhandle[depthleft++])); // Close any open directories.
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Create the files and directories as lump entries
|
||||
// It's possible to create lumps and count files at the same time,
|
||||
// but I didn't to constantly have to reallocate memory for every lump.
|
||||
rewinddir(dirhandle[rootfolder]);
|
||||
depthleft = rootfolder;
|
||||
|
||||
strlcpy(folderpath, path, folderpathlen);
|
||||
initfolderpath(folderpath, folderpathindex, depthleft);
|
||||
|
||||
lump_p = lumpinfo = Z_Calloc(numlumps * sizeof(lumpinfo_t), PU_STATIC, NULL);
|
||||
|
||||
while (depthleft < maxfolderdepth)
|
||||
{
|
||||
char *fullname, *trimname;
|
||||
|
||||
folderpath[folderpathindex[depthleft]] = 0;
|
||||
dent = readdir(dirhandle[depthleft]);
|
||||
|
||||
if (!dent)
|
||||
{
|
||||
closedir(dirhandle[depthleft++]);
|
||||
continue;
|
||||
}
|
||||
else if (isuptree(dent->d_name))
|
||||
continue;
|
||||
|
||||
strcpy(&folderpath[folderpathindex[depthleft]], dent->d_name);
|
||||
|
||||
if (stat(folderpath, &fsstat) < 0)
|
||||
continue;
|
||||
else if (S_ISDIR(fsstat.st_mode) && depthleft)
|
||||
{
|
||||
folderpathindex[--depthleft] = strlen(folderpath) + 1;
|
||||
dirhandle[depthleft] = opendir(folderpath);
|
||||
|
||||
if (!dirhandle[depthleft])
|
||||
{
|
||||
depthleft++;
|
||||
continue;
|
||||
}
|
||||
|
||||
folderpath[folderpathindex[depthleft]-1] = '/';
|
||||
folderpath[folderpathindex[depthleft]] = 0;
|
||||
}
|
||||
|
||||
lump_p->diskpath = Z_StrDup(folderpath); // Path in the filesystem to the file
|
||||
lump_p->compression = CM_NOCOMPRESSION; // Lump is uncompressed
|
||||
|
||||
// Remove the folder path.
|
||||
fullname = lump_p->diskpath;
|
||||
if (strstr(fullname, path))
|
||||
fullname += strlen(path) + 1;
|
||||
|
||||
// Get the 8-character long lump name.
|
||||
trimname = strrchr(fullname, '/');
|
||||
if (trimname)
|
||||
trimname++;
|
||||
else
|
||||
trimname = fullname;
|
||||
|
||||
if (trimname[0])
|
||||
{
|
||||
char *dotpos = strrchr(trimname, '.');
|
||||
if (dotpos == NULL)
|
||||
dotpos = fullname + strlen(fullname);
|
||||
|
||||
strncpy(lump_p->name, trimname, min(8, dotpos - trimname));
|
||||
|
||||
// The name of the file, without the extension.
|
||||
lump_p->longname = Z_Calloc(dotpos - trimname + 1, PU_STATIC, NULL);
|
||||
strlcpy(lump_p->longname, trimname, dotpos - trimname + 1);
|
||||
}
|
||||
else
|
||||
lump_p->longname = Z_Calloc(1, PU_STATIC, NULL);
|
||||
|
||||
// The complete name of the file, with its extension,
|
||||
// excluding the path of the folder where it resides.
|
||||
lump_p->fullname = Z_StrDup(fullname);
|
||||
|
||||
lump_p++;
|
||||
i++;
|
||||
|
||||
if (i > numlumps || i == (UINT16_MAX-1))
|
||||
{
|
||||
for (; depthleft < maxfolderdepth; closedir(dirhandle[depthleft++])); // Close any open directories.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
free(folderpathindex);
|
||||
free(dirhandle);
|
||||
|
||||
(*nlmp) = numlumps;
|
||||
return lumpinfo;
|
||||
}
|
||||
|
||||
//
|
||||
// Addons menu
|
||||
//
|
||||
|
||||
char exttable[NUM_EXT_TABLE][7] = { // maximum extension length (currently 4) plus 3 (null terminator, stop, and length including previous two)
|
||||
"\5.txt", "\5.cfg", // exec
|
||||
"\5.wad",
|
||||
|
@ -455,7 +781,6 @@ char exttable[NUM_EXT_TABLE][7] = { // maximum extension length (currently 4) pl
|
|||
|
||||
char filenamebuf[MAX_WADFILES][MAX_WADPATH];
|
||||
|
||||
|
||||
static boolean filemenucmp(char *haystack, char *needle)
|
||||
{
|
||||
static char localhaystack[128];
|
||||
|
@ -640,10 +965,7 @@ boolean preparefilemenu(boolean samedepth)
|
|||
|
||||
if (!dent)
|
||||
break;
|
||||
else if (dent->d_name[0]=='.' &&
|
||||
(dent->d_name[1]=='\0' ||
|
||||
(dent->d_name[1]=='.' &&
|
||||
dent->d_name[2]=='\0')))
|
||||
else if (isuptree(dent->d_name))
|
||||
continue; // we don't want to scan uptree
|
||||
|
||||
strcpy(&menupath[menupathindex[menudepthleft]],dent->d_name);
|
||||
|
@ -704,10 +1026,7 @@ boolean preparefilemenu(boolean samedepth)
|
|||
|
||||
if (!dent)
|
||||
break;
|
||||
else if (dent->d_name[0]=='.' &&
|
||||
(dent->d_name[1]=='\0' ||
|
||||
(dent->d_name[1]=='.' &&
|
||||
dent->d_name[2]=='\0')))
|
||||
else if (isuptree(dent->d_name))
|
||||
continue; // we don't want to scan uptree
|
||||
|
||||
strcpy(&menupath[menupathindex[menudepthleft]],dent->d_name);
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "doomdef.h"
|
||||
#include "d_netfil.h"
|
||||
#include "m_menu.h" // MAXSTRINGLENGTH
|
||||
#include "w_wad.h"
|
||||
|
||||
extern consvar_t cv_addons_option, cv_addons_folder, cv_addons_md5, cv_addons_showall, cv_addons_search_case, cv_addons_search_type;
|
||||
|
||||
|
@ -28,6 +29,12 @@ extern consvar_t cv_addons_option, cv_addons_folder, cv_addons_md5, cv_addons_sh
|
|||
filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *wantedmd5sum,
|
||||
boolean completepath, int maxsearchdepth);
|
||||
|
||||
INT32 pathisfolder(const char *path);
|
||||
boolean checkfolderpath(const char *path, const char *startpath, boolean cleanup);
|
||||
INT32 samepaths(const char *path1, const char *path2);
|
||||
|
||||
lumpinfo_t *getfolderfiles(const char *path, UINT16 *nlmp, UINT16 *nfiles, UINT16 *nfolders);
|
||||
|
||||
#define menudepth 20
|
||||
|
||||
extern char menupath[1024];
|
||||
|
@ -94,5 +101,4 @@ typedef enum
|
|||
void closefilemenu(boolean validsize);
|
||||
void searchfilemenu(char *tempname);
|
||||
boolean preparefilemenu(boolean samedepth);
|
||||
|
||||
#endif // __FILESRCH_H__
|
||||
|
|
|
@ -6681,7 +6681,7 @@ void HWR_LoadAllCustomShaders(void)
|
|||
|
||||
// read every custom shader
|
||||
for (i = 0; i < numwadfiles; i++)
|
||||
HWR_LoadCustomShadersFromFile(i, (wadfiles[i]->type == RET_PK3));
|
||||
HWR_LoadCustomShadersFromFile(i, W_FileHasFolders(wadfiles[i]));
|
||||
}
|
||||
|
||||
void HWR_LoadCustomShadersFromFile(UINT16 wadnum, boolean PK3)
|
||||
|
|
19
src/m_misc.c
19
src/m_misc.c
|
@ -2688,3 +2688,22 @@ const char * M_Ftrim (double f)
|
|||
return &dig[1];/* skip the 0 */
|
||||
}
|
||||
}
|
||||
|
||||
// Returns true if the string is empty.
|
||||
boolean M_IsStringEmpty(const char *s)
|
||||
{
|
||||
const char *ch = s;
|
||||
|
||||
if (ch == NULL || (ch && strlen(ch) < 1))
|
||||
return true;
|
||||
|
||||
for (;;ch++)
|
||||
{
|
||||
if (!(*ch))
|
||||
break;
|
||||
if (!isspace((*ch)))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -117,6 +117,9 @@ trailing zeros, or "" if the fractional part is zero.
|
|||
*/
|
||||
const char * M_Ftrim (double);
|
||||
|
||||
// Returns true if the string is empty.
|
||||
boolean M_IsStringEmpty(const char *s);
|
||||
|
||||
// counting bits, for weapon ammo code, usually
|
||||
FUNCMATH UINT8 M_CountBits(UINT32 num, UINT8 size);
|
||||
|
||||
|
|
|
@ -4385,10 +4385,9 @@ static lumpinfo_t* FindFolder(const char *folName, UINT16 *start, UINT16 *end, l
|
|||
// Add a wadfile to the active wad files,
|
||||
// replace sounds, musics, patches, textures, sprites and maps
|
||||
//
|
||||
boolean P_AddWadFile(const char *wadfilename)
|
||||
static boolean P_LoadAddon(UINT16 wadnum, UINT16 numlumps)
|
||||
{
|
||||
size_t i, j, sreplaces = 0, mreplaces = 0, digmreplaces = 0;
|
||||
UINT16 numlumps, wadnum;
|
||||
char *name;
|
||||
lumpinfo_t *lumpinfo;
|
||||
|
||||
|
@ -4409,18 +4408,10 @@ boolean P_AddWadFile(const char *wadfilename)
|
|||
// UINT16 flaPos, flaNum = 0;
|
||||
// UINT16 mapPos, mapNum = 0;
|
||||
|
||||
// Init file.
|
||||
if ((numlumps = W_InitFile(wadfilename, false, false)) == INT16_MAX)
|
||||
{
|
||||
refreshdirmenu |= REFRESHDIR_NOTLOADED;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
wadnum = (UINT16)(numwadfiles-1);
|
||||
|
||||
switch(wadfiles[wadnum]->type)
|
||||
{
|
||||
case RET_PK3:
|
||||
case RET_FOLDER:
|
||||
// Look for the lumps that act as resource delimitation markers.
|
||||
lumpinfo = wadfiles[wadnum]->lumpinfo;
|
||||
for (i = 0; i < numlumps; i++, lumpinfo++)
|
||||
|
@ -4584,3 +4575,35 @@ boolean P_AddWadFile(const char *wadfilename)
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean P_AddWadFile(const char *wadfilename)
|
||||
{
|
||||
UINT16 numlumps, wadnum;
|
||||
|
||||
// Init file.
|
||||
if ((numlumps = W_InitFile(wadfilename, false, false)) == INT16_MAX)
|
||||
{
|
||||
refreshdirmenu |= REFRESHDIR_NOTLOADED;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
wadnum = (UINT16)(numwadfiles-1);
|
||||
|
||||
return P_LoadAddon(wadnum, numlumps);
|
||||
}
|
||||
|
||||
boolean P_AddFolder(const char *folderpath)
|
||||
{
|
||||
UINT16 numlumps, wadnum;
|
||||
|
||||
// Init file.
|
||||
if ((numlumps = W_InitFolder(folderpath, false, false)) == INT16_MAX)
|
||||
{
|
||||
refreshdirmenu |= REFRESHDIR_NOTLOADED;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
wadnum = (UINT16)(numwadfiles-1);
|
||||
|
||||
return P_LoadAddon(wadnum, numlumps);
|
||||
}
|
||||
|
|
|
@ -103,6 +103,7 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate);
|
|||
void HWR_LoadLevel(void);
|
||||
#endif
|
||||
boolean P_AddWadFile(const char *wadfilename);
|
||||
boolean P_AddFolder(const char *folderpath);
|
||||
boolean P_RunSOC(const char *socfilename);
|
||||
void P_LoadSoundsRange(UINT16 wadnum, UINT16 first, UINT16 num);
|
||||
void P_LoadMusicsRange(UINT16 wadnum, UINT16 first, UINT16 num);
|
||||
|
|
|
@ -732,7 +732,7 @@ Rloadflats (INT32 i, INT32 w)
|
|||
texpatch_t *patch;
|
||||
|
||||
// Yes
|
||||
if (wadfiles[w]->type == RET_PK3)
|
||||
if (W_FileHasFolders(wadfiles[w]))
|
||||
{
|
||||
texstart = W_CheckNumForFolderStartPK3("flats/", (UINT16)w, 0);
|
||||
texend = W_CheckNumForFolderEndPK3("flats/", (UINT16)w, texstart);
|
||||
|
@ -754,7 +754,7 @@ Rloadflats (INT32 i, INT32 w)
|
|||
size_t lumplength;
|
||||
size_t flatsize = 0;
|
||||
|
||||
if (wadfiles[w]->type == RET_PK3)
|
||||
if (W_FileHasFolders(wadfiles[w]))
|
||||
{
|
||||
if (W_IsLumpFolder(wadnum, lumpnum)) // Check if lump is a folder
|
||||
continue; // If it is then SKIP IT
|
||||
|
@ -844,7 +844,7 @@ Rloadtextures (INT32 i, INT32 w)
|
|||
texpatch_t *patch;
|
||||
|
||||
// Get the lump numbers for the markers in the WAD, if they exist.
|
||||
if (wadfiles[w]->type == RET_PK3)
|
||||
if (W_FileHasFolders(wadfiles[w]))
|
||||
{
|
||||
texstart = W_CheckNumForFolderStartPK3("textures/", (UINT16)w, 0);
|
||||
texend = W_CheckNumForFolderEndPK3("textures/", (UINT16)w, texstart);
|
||||
|
@ -875,7 +875,7 @@ Rloadtextures (INT32 i, INT32 w)
|
|||
size_t lumplength;
|
||||
#endif
|
||||
|
||||
if (wadfiles[w]->type == RET_PK3)
|
||||
if (W_FileHasFolders(wadfiles[w]))
|
||||
{
|
||||
if (W_IsLumpFolder(wadnum, lumpnum)) // Check if lump is a folder
|
||||
continue; // If it is then SKIP IT
|
||||
|
@ -964,7 +964,7 @@ void R_LoadTextures(void)
|
|||
{
|
||||
#ifdef WALLFLATS
|
||||
// Count flats
|
||||
if (wadfiles[w]->type == RET_PK3)
|
||||
if (W_FileHasFolders(wadfiles[w]))
|
||||
{
|
||||
texstart = W_CheckNumForFolderStartPK3("flats/", (UINT16)w, 0);
|
||||
texend = W_CheckNumForFolderEndPK3("flats/", (UINT16)w, texstart);
|
||||
|
@ -978,7 +978,7 @@ void R_LoadTextures(void)
|
|||
if (!( texstart == INT16_MAX || texend == INT16_MAX ))
|
||||
{
|
||||
// PK3s have subfolders, so we can't just make a simple sum
|
||||
if (wadfiles[w]->type == RET_PK3)
|
||||
if (W_FileHasFolders(wadfiles[w]))
|
||||
{
|
||||
for (j = texstart; j < texend; j++)
|
||||
{
|
||||
|
@ -1002,7 +1002,7 @@ void R_LoadTextures(void)
|
|||
}
|
||||
|
||||
// Count single-patch textures
|
||||
if (wadfiles[w]->type == RET_PK3)
|
||||
if (W_FileHasFolders(wadfiles[w]))
|
||||
{
|
||||
texstart = W_CheckNumForFolderStartPK3("textures/", (UINT16)w, 0);
|
||||
texend = W_CheckNumForFolderEndPK3("textures/", (UINT16)w, texstart);
|
||||
|
@ -1017,7 +1017,7 @@ void R_LoadTextures(void)
|
|||
continue;
|
||||
|
||||
// PK3s have subfolders, so we can't just make a simple sum
|
||||
if (wadfiles[w]->type == RET_PK3)
|
||||
if (W_FileHasFolders(wadfiles[w]))
|
||||
{
|
||||
for (j = texstart; j < texend; j++)
|
||||
{
|
||||
|
@ -1558,6 +1558,7 @@ lumpnum_t R_GetFlatNumForName(const char *name)
|
|||
continue;
|
||||
break;
|
||||
case RET_PK3:
|
||||
case RET_FOLDER:
|
||||
if ((start = W_CheckNumForFolderStartPK3("Flats/", i, 0)) == INT16_MAX)
|
||||
continue;
|
||||
if ((end = W_CheckNumForFolderEndPK3("Flats/", i, start)) == INT16_MAX)
|
||||
|
|
|
@ -443,6 +443,7 @@ void R_AddSpriteDefs(UINT16 wadnum)
|
|||
end = W_CheckNumForNamePwad("SS_END",wadnum,start); //deutex compatib.
|
||||
break;
|
||||
case RET_PK3:
|
||||
case RET_FOLDER:
|
||||
start = W_CheckNumForFolderStartPK3("Sprites/", wadnum, 0);
|
||||
end = W_CheckNumForFolderEndPK3("Sprites/", wadnum, start);
|
||||
break;
|
||||
|
|
337
src/w_wad.c
337
src/w_wad.c
|
@ -50,16 +50,17 @@
|
|||
|
||||
#include "filesrch.h"
|
||||
|
||||
#include "i_video.h" // rendermode
|
||||
#include "d_main.h"
|
||||
#include "d_netfil.h"
|
||||
#include "dehacked.h"
|
||||
#include "d_clisrv.h"
|
||||
#include "dehacked.h"
|
||||
#include "r_defs.h"
|
||||
#include "r_data.h"
|
||||
#include "r_textures.h"
|
||||
#include "r_patch.h"
|
||||
#include "r_picformats.h"
|
||||
#include "i_system.h"
|
||||
#include "i_video.h" // rendermode
|
||||
#include "md5.h"
|
||||
#include "lua_script.h"
|
||||
#ifdef SCANTHINGS
|
||||
|
@ -117,10 +118,15 @@ void W_Shutdown(void)
|
|||
{
|
||||
wadfile_t *wad = wadfiles[numwadfiles];
|
||||
|
||||
fclose(wad->handle);
|
||||
if (wad->handle)
|
||||
fclose(wad->handle);
|
||||
Z_Free(wad->filename);
|
||||
if (wad->path)
|
||||
Z_Free(wad->path);
|
||||
while (wad->numlumps--)
|
||||
{
|
||||
if (wad->lumpinfo[wad->numlumps].diskpath)
|
||||
Z_Free(wad->lumpinfo[wad->numlumps].diskpath);
|
||||
Z_Free(wad->lumpinfo[wad->numlumps].longname);
|
||||
Z_Free(wad->lumpinfo[wad->numlumps].fullname);
|
||||
}
|
||||
|
@ -421,6 +427,7 @@ static lumpinfo_t* ResGetLumpsWad (FILE* handle, UINT16* nlmp, const char* filen
|
|||
{
|
||||
lump_p->position = LONG(fileinfo->filepos);
|
||||
lump_p->size = lump_p->disksize = LONG(fileinfo->size);
|
||||
lump_p->diskpath = NULL;
|
||||
if (compressed) // wad is compressed, lump might be
|
||||
{
|
||||
UINT32 realsize = 0;
|
||||
|
@ -602,6 +609,7 @@ static lumpinfo_t* ResGetLumpsZip (FILE* handle, UINT16* nlmp)
|
|||
|
||||
lump_p->position = zentry.offset; // NOT ACCURATE YET: we still need to read the local entry to find our true position
|
||||
lump_p->disksize = zentry.compsize;
|
||||
lump_p->diskpath = NULL;
|
||||
lump_p->size = zentry.size;
|
||||
|
||||
fullname = malloc(zentry.namelen + 1);
|
||||
|
@ -679,6 +687,58 @@ static lumpinfo_t* ResGetLumpsZip (FILE* handle, UINT16* nlmp)
|
|||
return lumpinfo;
|
||||
}
|
||||
|
||||
// Checks if the combination of the first path and the second path are valid.
|
||||
// If they are, the concatenated path is returned.
|
||||
static char *W_CheckFolderPath(const char *startpath, const char *path)
|
||||
{
|
||||
if (checkfolderpath(path, startpath, false))
|
||||
{
|
||||
char *fn;
|
||||
|
||||
if (startpath)
|
||||
{
|
||||
size_t len = strlen(startpath) + strlen(path) + strlen(PATHSEP) + 1;
|
||||
fn = ZZ_Alloc(len);
|
||||
snprintf(fn, len, "%s" PATHSEP "%s", startpath, path);
|
||||
}
|
||||
else
|
||||
fn = Z_StrDup(path);
|
||||
|
||||
return fn;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Returns the first valid path for a folder.
|
||||
static char *W_GetFullFolderPath(const char *path)
|
||||
{
|
||||
// Check the path by itself first.
|
||||
char *fn = W_CheckFolderPath(NULL, path);
|
||||
if (fn)
|
||||
return fn;
|
||||
|
||||
#define checkpath(startpath) { \
|
||||
fn = W_CheckFolderPath(startpath, path); \
|
||||
if (fn) \
|
||||
return fn; \
|
||||
} \
|
||||
|
||||
checkpath(srb2home) // Then, look in srb2home.
|
||||
checkpath(srb2path) // Now, look in srb2path.
|
||||
checkpath(".") // Finally, look in ".".
|
||||
|
||||
#undef checkpath
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Loads files from a folder into a lumpinfo structure.
|
||||
static lumpinfo_t *ResGetLumpsFolder(const char *path, UINT16 *nlmp, UINT16 *nfiles, UINT16 *nfolders)
|
||||
{
|
||||
return getfolderfiles(path, nlmp, nfiles, nfolders);
|
||||
}
|
||||
|
||||
static UINT16 W_InitFileError (const char *filename, boolean exitworthy)
|
||||
{
|
||||
if (exitworthy)
|
||||
|
@ -694,6 +754,19 @@ static UINT16 W_InitFileError (const char *filename, boolean exitworthy)
|
|||
return INT16_MAX;
|
||||
}
|
||||
|
||||
static void W_ReadFileShaders(wadfile_t *wadfile)
|
||||
{
|
||||
#ifdef HWRENDER
|
||||
if (rendermode == render_opengl && (vid.glstate == VID_GL_LIBRARY_LOADED))
|
||||
{
|
||||
HWR_LoadCustomShadersFromFile(numwadfiles - 1, W_FileHasFolders(wadfile));
|
||||
HWR_CompileShaders();
|
||||
}
|
||||
#else
|
||||
(void)wadfile;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Allocate a wadfile, setup the lumpinfo (directory) and
|
||||
// lumpcache, add the wadfile to the current active wadfiles
|
||||
//
|
||||
|
@ -760,7 +833,7 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup)
|
|||
// see PutFileNeeded in d_netfil.c
|
||||
if ((important = !important))
|
||||
{
|
||||
packetsize = packetsizetally + nameonlylength(filename) + 22;
|
||||
packetsize = packetsizetally + nameonlylength(filename) + FILENEEDEDSIZE;
|
||||
|
||||
if (packetsize > MAXFILENEEDED*sizeof(UINT8))
|
||||
{
|
||||
|
@ -788,7 +861,7 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup)
|
|||
{
|
||||
CONS_Alert(CONS_ERROR, M_GetText("%s is already loaded\n"), filename);
|
||||
if (important)
|
||||
packetsizetally -= nameonlylength(filename) + 22;
|
||||
packetsizetally -= nameonlylength(filename) + FILENEEDEDSIZE;
|
||||
if (handle)
|
||||
fclose(handle);
|
||||
return W_InitFileError(filename, false);
|
||||
|
@ -828,9 +901,11 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup)
|
|||
//
|
||||
wadfile = Z_Malloc(sizeof (*wadfile), PU_STATIC, NULL);
|
||||
wadfile->filename = Z_StrDup(filename);
|
||||
wadfile->path = NULL;
|
||||
wadfile->type = type;
|
||||
wadfile->handle = handle;
|
||||
wadfile->numlumps = (UINT16)numlumps;
|
||||
wadfile->numlumps = numlumps;
|
||||
wadfile->filecount = wadfile->foldercount = 0;
|
||||
wadfile->lumpinfo = lumpinfo;
|
||||
wadfile->important = important;
|
||||
fseek(handle, 0, SEEK_END);
|
||||
|
@ -853,14 +928,8 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup)
|
|||
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
|
||||
|
||||
#ifdef HWRENDER
|
||||
// Read shaders from file
|
||||
if (rendermode == render_opengl && (vid.glstate == VID_GL_LIBRARY_LOADED))
|
||||
{
|
||||
HWR_LoadCustomShadersFromFile(numwadfiles - 1, (type == RET_PK3));
|
||||
HWR_CompileShaders();
|
||||
}
|
||||
#endif // HWRENDER
|
||||
W_ReadFileShaders(wadfile);
|
||||
|
||||
// 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)
|
||||
|
@ -886,6 +955,153 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup)
|
|||
return wadfile->numlumps;
|
||||
}
|
||||
|
||||
//
|
||||
// Loads a folder as a WAD.
|
||||
//
|
||||
UINT16 W_InitFolder(const char *path, boolean mainfile, boolean startup)
|
||||
{
|
||||
lumpinfo_t *lumpinfo = NULL;
|
||||
wadfile_t *wadfile;
|
||||
UINT16 numlumps = 0;
|
||||
UINT16 filecount, foldercount;
|
||||
size_t i;
|
||||
char *fn, *fullpath;
|
||||
const char *p;
|
||||
int important;
|
||||
|
||||
if (!(refreshdirmenu & REFRESHDIR_ADDFILE))
|
||||
refreshdirmenu = REFRESHDIR_NORMAL|REFRESHDIR_ADDFILE; // clean out cons_alerts that happened earlier
|
||||
|
||||
if (refreshdirname)
|
||||
Z_Free(refreshdirname);
|
||||
if (dirmenu)
|
||||
refreshdirname = Z_StrDup(path);
|
||||
else
|
||||
refreshdirname = NULL;
|
||||
|
||||
if (numwadfiles >= MAX_WADFILES)
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, M_GetText("Maximum wad files reached\n"));
|
||||
refreshdirmenu |= REFRESHDIR_MAX;
|
||||
return W_InitFileError(path, startup);
|
||||
}
|
||||
|
||||
important = 0; // ???
|
||||
|
||||
/// \todo Implement a W_VerifyFolder.
|
||||
if ((important = !important))
|
||||
{
|
||||
size_t packetsize = packetsizetally + strlen(path) + FILENEEDEDSIZE;
|
||||
|
||||
if (packetsize > MAXFILENEEDED*sizeof(UINT8))
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, M_GetText("Maximum wad files reached\n"));
|
||||
refreshdirmenu |= REFRESHDIR_MAX;
|
||||
return W_InitFileError(path, startup);
|
||||
}
|
||||
|
||||
packetsizetally = packetsize;
|
||||
}
|
||||
|
||||
// Remove path separators from the filename, and don't try adding "/".
|
||||
p = path+strlen(path);
|
||||
--p;
|
||||
|
||||
while (*p == '\\' || *p == '/' || *p == ':')
|
||||
{
|
||||
p--;
|
||||
if (p < path)
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, M_GetText("Path %s is prohibited\n"), path);
|
||||
return W_InitFileError(path, startup);
|
||||
}
|
||||
}
|
||||
p++;
|
||||
|
||||
// Allocate the new path name.
|
||||
i = (p - path) + 1;
|
||||
fn = ZZ_Alloc(i);
|
||||
strlcpy(fn, path, i);
|
||||
|
||||
if (M_IsStringEmpty(fn))
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, M_GetText("Folder name is empty\n"));
|
||||
Z_Free(fn);
|
||||
|
||||
if (startup)
|
||||
return W_InitFileError("A folder", true);
|
||||
else
|
||||
return W_InitFileError("a folder", false);
|
||||
}
|
||||
|
||||
// Get the full path for this filename.
|
||||
fullpath = W_GetFullFolderPath(fn);
|
||||
if (fullpath == NULL)
|
||||
{
|
||||
Z_Free(fn);
|
||||
return W_InitFileError(path, false);
|
||||
}
|
||||
|
||||
for (i = 0; i < numwadfiles; i++)
|
||||
{
|
||||
if (wadfiles[i]->type != RET_FOLDER)
|
||||
continue;
|
||||
|
||||
if (samepaths(wadfiles[i]->path, fullpath) > 0)
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, M_GetText("%s is already loaded\n"), path);
|
||||
if (important)
|
||||
packetsizetally -= strlen(path) + FILENEEDEDSIZE;
|
||||
Z_Free(fn);
|
||||
Z_Free(fullpath);
|
||||
return W_InitFileError(path, false);
|
||||
}
|
||||
}
|
||||
|
||||
lumpinfo = ResGetLumpsFolder(fullpath, &numlumps, &filecount, &foldercount);
|
||||
if (lumpinfo == NULL)
|
||||
{
|
||||
if (filecount == UINT16_MAX)
|
||||
CONS_Alert(CONS_ERROR, M_GetText("Folder %s is empty\n"), path);
|
||||
|
||||
Z_Free(fn);
|
||||
Z_Free(fullpath);
|
||||
|
||||
return W_InitFileError(path, startup);
|
||||
}
|
||||
|
||||
if (important && !mainfile)
|
||||
G_SetGameModified(true);
|
||||
|
||||
wadfile = Z_Malloc(sizeof (*wadfile), PU_STATIC, NULL);
|
||||
wadfile->filename = fn;
|
||||
wadfile->path = fullpath;
|
||||
wadfile->type = RET_FOLDER;
|
||||
wadfile->handle = NULL;
|
||||
wadfile->numlumps = numlumps;
|
||||
wadfile->filecount = filecount;
|
||||
wadfile->foldercount = foldercount;
|
||||
wadfile->lumpinfo = lumpinfo;
|
||||
wadfile->important = important;
|
||||
|
||||
// Irrelevant.
|
||||
wadfile->filesize = 0;
|
||||
memset(wadfile->md5sum, 0x00, 16);
|
||||
|
||||
Z_Calloc(numlumps * sizeof (*wadfile->lumpcache), PU_STATIC, &wadfile->lumpcache);
|
||||
Z_Calloc(numlumps * sizeof (*wadfile->patchcache), PU_STATIC, &wadfile->patchcache);
|
||||
|
||||
CONS_Printf(M_GetText("Added folder %s (%u files, %u folders)\n"), fn, filecount, foldercount);
|
||||
wadfiles[numwadfiles] = wadfile;
|
||||
numwadfiles++;
|
||||
|
||||
W_ReadFileShaders(wadfile);
|
||||
W_LoadDehackedLumpsPK3(numwadfiles - 1, mainfile);
|
||||
W_InvalidateLumpnumCache();
|
||||
|
||||
return wadfile->numlumps;
|
||||
}
|
||||
|
||||
/** Tries to load a series of files.
|
||||
* All files are wads unless they have an extension of ".soc" or ".lua".
|
||||
*
|
||||
|
@ -897,11 +1113,18 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup)
|
|||
*/
|
||||
void W_InitMultipleFiles(char **filenames)
|
||||
{
|
||||
// will be realloced as lumps are added
|
||||
for (; *filenames; filenames++)
|
||||
{
|
||||
//CONS_Debug(DBG_SETUP, "Loading %s\n", *filenames);
|
||||
W_InitFile(*filenames, numwadfiles < mainwads, true);
|
||||
const char *fn = (*filenames);
|
||||
char pathsep = fn[strlen(fn) - 1];
|
||||
boolean mainfile = (numwadfiles < mainwads);
|
||||
|
||||
//CONS_Debug(DBG_SETUP, "Loading %s\n", fn);
|
||||
|
||||
if (pathsep == '\\' || pathsep == '/')
|
||||
W_InitFolder(fn, mainfile, true);
|
||||
else
|
||||
W_InitFile(fn, mainfile, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1175,7 +1398,7 @@ lumpnum_t W_CheckNumForMap(const char *name)
|
|||
if (!strncmp(name, (wadfiles[i]->lumpinfo + lumpNum)->name, 8))
|
||||
return (i<<16) + lumpNum;
|
||||
}
|
||||
else if (wadfiles[i]->type == RET_PK3)
|
||||
else if (W_FileHasFolders(wadfiles[i]))
|
||||
{
|
||||
lumpNum = W_CheckNumForFolderStartPK3("maps/", i, 0);
|
||||
if (lumpNum != INT16_MAX)
|
||||
|
@ -1273,9 +1496,34 @@ UINT8 W_LumpExists(const char *name)
|
|||
|
||||
size_t W_LumpLengthPwad(UINT16 wad, UINT16 lump)
|
||||
{
|
||||
lumpinfo_t *l;
|
||||
|
||||
if (!TestValidLump(wad, lump))
|
||||
return 0;
|
||||
return wadfiles[wad]->lumpinfo[lump].size;
|
||||
|
||||
l = wadfiles[wad]->lumpinfo + lump;
|
||||
|
||||
if (wadfiles[wad]->type == RET_FOLDER)
|
||||
{
|
||||
INT32 stat = pathisfolder(l->diskpath);
|
||||
|
||||
if (stat < 0)
|
||||
I_Error("W_LumpLengthPwad: could not stat %s", l->diskpath);
|
||||
else if (stat == 1) // Path is a folder.
|
||||
return 0;
|
||||
else
|
||||
{
|
||||
FILE *handle = fopen(l->diskpath, "rb");
|
||||
if (handle == NULL)
|
||||
I_Error("W_LumpLengthPwad: could not open file %s", l->diskpath);
|
||||
|
||||
fseek(handle, 0, SEEK_END);
|
||||
l->size = l->disksize = ftell(handle);
|
||||
fclose(handle);
|
||||
}
|
||||
}
|
||||
|
||||
return l->size;
|
||||
}
|
||||
|
||||
/** Returns the buffer size needed to load the given lump.
|
||||
|
@ -1294,7 +1542,7 @@ size_t W_LumpLength(lumpnum_t lumpnum)
|
|||
//
|
||||
boolean W_IsLumpWad(lumpnum_t lumpnum)
|
||||
{
|
||||
if (wadfiles[WADFILENUM(lumpnum)]->type == RET_PK3)
|
||||
if (W_FileHasFolders(wadfiles[WADFILENUM(lumpnum)]))
|
||||
{
|
||||
const char *lumpfullName = (wadfiles[WADFILENUM(lumpnum)]->lumpinfo + LUMPNUM(lumpnum))->fullname;
|
||||
|
||||
|
@ -1312,7 +1560,7 @@ boolean W_IsLumpWad(lumpnum_t lumpnum)
|
|||
//
|
||||
boolean W_IsLumpFolder(UINT16 wad, UINT16 lump)
|
||||
{
|
||||
if (wadfiles[wad]->type == RET_PK3)
|
||||
if (W_FileHasFolders(wadfiles[wad]))
|
||||
{
|
||||
const char *name = wadfiles[wad]->lumpinfo[lump].fullname;
|
||||
|
||||
|
@ -1362,17 +1610,44 @@ void zerr(int ret)
|
|||
*/
|
||||
size_t W_ReadLumpHeaderPwad(UINT16 wad, UINT16 lump, void *dest, size_t size, size_t offset)
|
||||
{
|
||||
size_t lumpsize;
|
||||
size_t lumpsize, bytesread;
|
||||
lumpinfo_t *l;
|
||||
FILE *handle;
|
||||
FILE *handle = NULL;
|
||||
|
||||
if (!TestValidLump(wad,lump))
|
||||
return 0;
|
||||
|
||||
l = wadfiles[wad]->lumpinfo + lump;
|
||||
|
||||
// Open the external file for this lump, if the WAD is a folder.
|
||||
if (wadfiles[wad]->type == RET_FOLDER)
|
||||
{
|
||||
INT32 stat = pathisfolder(l->diskpath);
|
||||
|
||||
if (stat < 0)
|
||||
I_Error("W_ReadLumpHeaderPwad: could not stat %s", l->diskpath);
|
||||
else if (stat == 1) // Path is a folder.
|
||||
return 0;
|
||||
else
|
||||
{
|
||||
handle = fopen(l->diskpath, "rb");
|
||||
if (handle == NULL)
|
||||
I_Error("W_ReadLumpHeaderPwad: could not open file %s", l->diskpath);
|
||||
|
||||
// Find length of file
|
||||
fseek(handle, 0, SEEK_END);
|
||||
l->size = l->disksize = ftell(handle);
|
||||
}
|
||||
}
|
||||
|
||||
lumpsize = wadfiles[wad]->lumpinfo[lump].size;
|
||||
// empty resource (usually markers like S_START, F_END ..)
|
||||
if (!lumpsize || lumpsize<offset)
|
||||
{
|
||||
if (wadfiles[wad]->type == RET_FOLDER)
|
||||
fclose(handle);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// zero size means read all the lump
|
||||
if (!size || size+offset > lumpsize)
|
||||
|
@ -1380,24 +1655,22 @@ size_t W_ReadLumpHeaderPwad(UINT16 wad, UINT16 lump, void *dest, size_t size, si
|
|||
|
||||
// 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;
|
||||
if (wadfiles[wad]->type != RET_FOLDER)
|
||||
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)
|
||||
{
|
||||
case CM_NOCOMPRESSION: // If it's uncompressed, we directly write the data into our destination, and return the bytes read.
|
||||
bytesread = fread(dest, 1, size, handle);
|
||||
if (wadfiles[wad]->type == RET_FOLDER)
|
||||
fclose(handle);
|
||||
#ifdef NO_PNG_LUMPS
|
||||
{
|
||||
size_t bytesread = fread(dest, 1, size, handle);
|
||||
if (Picture_IsLumpPNG((UINT8 *)dest, bytesread))
|
||||
Picture_ThrowPNGError(l->fullname, wadfiles[wad]->filename);
|
||||
return bytesread;
|
||||
}
|
||||
#else
|
||||
return fread(dest, 1, size, handle);
|
||||
if (Picture_IsLumpPNG((UINT8 *)dest, bytesread))
|
||||
Picture_ThrowPNGError(l->fullname, wadfiles[wad]->filename);
|
||||
#endif
|
||||
return bytesread;
|
||||
case CM_LZF: // Is it LZF compressed? Used by ZWADs.
|
||||
{
|
||||
#ifdef ZWAD
|
||||
|
|
11
src/w_wad.h
11
src/w_wad.h
|
@ -69,6 +69,7 @@ typedef struct
|
|||
char name[9]; // filelump_t name[] e.g. "LongEntr"
|
||||
char *longname; // e.g. "LongEntryName"
|
||||
char *fullname; // e.g. "Folder/Subfolder/LongEntryName.extension"
|
||||
char *diskpath; // path to the file e.g. "/usr/games/srb2/Addon/Folder/Subfolder/LongEntryName.extension"
|
||||
size_t size; // real (uncompressed) size
|
||||
compmethod compression; // lump compression method
|
||||
} lumpinfo_t;
|
||||
|
@ -109,17 +110,19 @@ typedef enum restype
|
|||
RET_SOC,
|
||||
RET_LUA,
|
||||
RET_PK3,
|
||||
RET_FOLDER,
|
||||
RET_UNKNOWN,
|
||||
} restype_t;
|
||||
|
||||
typedef struct wadfile_s
|
||||
{
|
||||
char *filename;
|
||||
char *filename, *path;
|
||||
restype_t type;
|
||||
lumpinfo_t *lumpinfo;
|
||||
lumpcache_t *lumpcache;
|
||||
lumpcache_t *patchcache;
|
||||
UINT16 numlumps; // this wad's number of resources
|
||||
UINT16 filecount, foldercount; // file and folder count
|
||||
FILE *handle;
|
||||
UINT32 filesize; // for network
|
||||
UINT8 md5sum[16];
|
||||
|
@ -127,7 +130,7 @@ typedef struct wadfile_s
|
|||
boolean important; // also network - !W_VerifyNMUSlumps
|
||||
} wadfile_t;
|
||||
|
||||
#define WADFILENUM(lumpnum) (UINT16)((lumpnum)>>16) // wad flumpnum>>16) // wad file number in upper word
|
||||
#define WADFILENUM(lumpnum) (UINT16)((lumpnum)>>16) // wad file number in upper word
|
||||
#define LUMPNUM(lumpnum) (UINT16)((lumpnum)&0xFFFF) // lump number for this pwad
|
||||
|
||||
extern UINT16 numwadfiles;
|
||||
|
@ -141,10 +144,14 @@ void W_Shutdown(void);
|
|||
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_InitFile(const char *filename, boolean mainfile, boolean startup);
|
||||
// Adds a folder as a file
|
||||
UINT16 W_InitFolder(const char *path, boolean mainfile, boolean startup);
|
||||
|
||||
// W_InitMultipleFiles exits if a file was not found, but not if all is okay.
|
||||
void W_InitMultipleFiles(char **filenames);
|
||||
|
||||
#define W_FileHasFolders(wadfile) ((wadfile)->type == RET_PK3 || (wadfile)->type == RET_FOLDER)
|
||||
|
||||
const char *W_CheckNameForNumPwad(UINT16 wad, UINT16 lump);
|
||||
const char *W_CheckNameForNum(lumpnum_t lumpnum);
|
||||
|
||||
|
|
Loading…
Reference in a new issue