Merge branch 'addfile_menu' into 'master'
Add-ons menu Does what it says on the tin! Very pretty. Would like help testing in filesystems that are not Windows, although I've recieved assurances from Sryder that since it's based on the same filesrch code, it should work cross-platform. Just want to confirm it works, though. Also, M_* is whitelisted lumpname too. root/!LatestSRB2Files/srb2win_branch_addfile.exe, requires new patch.dta. See merge request !92
This commit is contained in:
commit
2e2b71da92
|
@ -33,6 +33,7 @@
|
||||||
#include "i_system.h"
|
#include "i_system.h"
|
||||||
#include "d_main.h"
|
#include "d_main.h"
|
||||||
#include "m_menu.h"
|
#include "m_menu.h"
|
||||||
|
#include "filesrch.h"
|
||||||
|
|
||||||
#ifdef _WINDOWS
|
#ifdef _WINDOWS
|
||||||
#include "win32/win_main.h"
|
#include "win32/win_main.h"
|
||||||
|
@ -1275,12 +1276,15 @@ void CONS_Alert(alerttype_t level, const char *fmt, ...)
|
||||||
switch (level)
|
switch (level)
|
||||||
{
|
{
|
||||||
case CONS_NOTICE:
|
case CONS_NOTICE:
|
||||||
|
// no notice for notices, hehe
|
||||||
CONS_Printf("\x83" "%s" "\x80 ", M_GetText("NOTICE:"));
|
CONS_Printf("\x83" "%s" "\x80 ", M_GetText("NOTICE:"));
|
||||||
break;
|
break;
|
||||||
case CONS_WARNING:
|
case CONS_WARNING:
|
||||||
|
refreshdirmenu |= REFRESHDIR_WARNING;
|
||||||
CONS_Printf("\x82" "%s" "\x80 ", M_GetText("WARNING:"));
|
CONS_Printf("\x82" "%s" "\x80 ", M_GetText("WARNING:"));
|
||||||
break;
|
break;
|
||||||
case CONS_ERROR:
|
case CONS_ERROR:
|
||||||
|
refreshdirmenu |= REFRESHDIR_ERROR;
|
||||||
CONS_Printf("\x85" "%s" "\x80 ", M_GetText("ERROR:"));
|
CONS_Printf("\x85" "%s" "\x80 ", M_GetText("ERROR:"));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -315,6 +315,7 @@ typedef struct
|
||||||
} ATTRPACK clientconfig_pak;
|
} ATTRPACK clientconfig_pak;
|
||||||
|
|
||||||
#define MAXSERVERNAME 32
|
#define MAXSERVERNAME 32
|
||||||
|
#define MAXFILENEEDED 915
|
||||||
// This packet is too large
|
// This packet is too large
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
|
@ -336,7 +337,7 @@ typedef struct
|
||||||
unsigned char mapmd5[16];
|
unsigned char mapmd5[16];
|
||||||
UINT8 actnum;
|
UINT8 actnum;
|
||||||
UINT8 iszone;
|
UINT8 iszone;
|
||||||
UINT8 fileneeded[915]; // is filled with writexxx (byteptr.h)
|
UINT8 fileneeded[MAXFILENEEDED]; // is filled with writexxx (byteptr.h)
|
||||||
} ATTRPACK serverinfo_pak;
|
} ATTRPACK serverinfo_pak;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
|
|
10
src/d_main.c
10
src/d_main.c
|
@ -74,6 +74,7 @@ int snprintf(char *str, size_t n, const char *fmt, ...);
|
||||||
#include "m_cond.h" // condition initialization
|
#include "m_cond.h" // condition initialization
|
||||||
#include "fastcmp.h"
|
#include "fastcmp.h"
|
||||||
#include "keys.h"
|
#include "keys.h"
|
||||||
|
#include "filesrch.h" // refreshdirmenu, mainwadstally
|
||||||
|
|
||||||
#ifdef CMAKECONFIG
|
#ifdef CMAKECONFIG
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
@ -584,6 +585,8 @@ void D_SRB2Loop(void)
|
||||||
realtics = entertic - oldentertics;
|
realtics = entertic - oldentertics;
|
||||||
oldentertics = entertic;
|
oldentertics = entertic;
|
||||||
|
|
||||||
|
refreshdirmenu = 0; // not sure where to put this, here as good as any?
|
||||||
|
|
||||||
#ifdef DEBUGFILE
|
#ifdef DEBUGFILE
|
||||||
if (!realtics)
|
if (!realtics)
|
||||||
if (debugload)
|
if (debugload)
|
||||||
|
@ -870,7 +873,7 @@ static void IdentifyVersion(void)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if 1 // This section can be deleted when music_new is merged with music.dta
|
#ifdef DEVELOP // This section can be deleted when music_new is merged with music.dta
|
||||||
{
|
{
|
||||||
const char *musicfile = "music_new.dta";
|
const char *musicfile = "music_new.dta";
|
||||||
const char *musicpath = va(pandf,srb2waddir,musicfile);
|
const char *musicpath = va(pandf,srb2waddir,musicfile);
|
||||||
|
@ -1162,6 +1165,11 @@ void D_SRB2Main(void)
|
||||||
#ifdef USE_PATCH_DTA
|
#ifdef USE_PATCH_DTA
|
||||||
++mainwads; // patch.dta adds one more
|
++mainwads; // patch.dta adds one more
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef DEVELOP
|
||||||
|
++mainwads; // music_new, too
|
||||||
|
#endif
|
||||||
|
|
||||||
|
mainwadstally = packetsizetally;
|
||||||
|
|
||||||
cht_Init();
|
cht_Init();
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
#include "d_main.h"
|
#include "d_main.h"
|
||||||
#include "m_random.h"
|
#include "m_random.h"
|
||||||
#include "f_finale.h"
|
#include "f_finale.h"
|
||||||
|
#include "filesrch.h"
|
||||||
#include "mserv.h"
|
#include "mserv.h"
|
||||||
#include "md5.h"
|
#include "md5.h"
|
||||||
#include "z_zone.h"
|
#include "z_zone.h"
|
||||||
|
@ -714,6 +715,14 @@ void D_RegisterClientCommands(void)
|
||||||
CV_RegisterVar(&cv_firenaxis);
|
CV_RegisterVar(&cv_firenaxis);
|
||||||
CV_RegisterVar(&cv_firenaxis2);
|
CV_RegisterVar(&cv_firenaxis2);
|
||||||
|
|
||||||
|
// filesrch.c
|
||||||
|
CV_RegisterVar(&cv_addons_option);
|
||||||
|
CV_RegisterVar(&cv_addons_folder);
|
||||||
|
CV_RegisterVar(&cv_addons_md5);
|
||||||
|
CV_RegisterVar(&cv_addons_showall);
|
||||||
|
CV_RegisterVar(&cv_addons_search_type);
|
||||||
|
CV_RegisterVar(&cv_addons_search_case);
|
||||||
|
|
||||||
// WARNING: the order is important when initialising mouse2
|
// WARNING: the order is important when initialising mouse2
|
||||||
// we need the mouse2port
|
// we need the mouse2port
|
||||||
CV_RegisterVar(&cv_mouse2port);
|
CV_RegisterVar(&cv_mouse2port);
|
||||||
|
|
|
@ -104,6 +104,7 @@ INT32 lastfilenum = -1;
|
||||||
/** Fills a serverinfo packet with information about wad files loaded.
|
/** Fills a serverinfo packet with information about wad files loaded.
|
||||||
*
|
*
|
||||||
* \todo Give this function a better name since it is in global scope.
|
* \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
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
UINT8 *PutFileNeeded(void)
|
UINT8 *PutFileNeeded(void)
|
||||||
|
@ -112,29 +113,22 @@ UINT8 *PutFileNeeded(void)
|
||||||
UINT8 *p = netbuffer->u.serverinfo.fileneeded;
|
UINT8 *p = netbuffer->u.serverinfo.fileneeded;
|
||||||
char wadfilename[MAX_WADPATH] = "";
|
char wadfilename[MAX_WADPATH] = "";
|
||||||
UINT8 filestatus;
|
UINT8 filestatus;
|
||||||
size_t bytesused = 0;
|
|
||||||
|
|
||||||
for (i = 0; i < numwadfiles; i++)
|
for (i = 0; i < numwadfiles; i++)
|
||||||
{
|
{
|
||||||
// If it has only music/sound lumps, mark it as unimportant
|
// If it has only music/sound lumps, don't put it in the list
|
||||||
if (W_VerifyNMUSlumps(wadfiles[i]->filename))
|
if (!wadfiles[i]->important)
|
||||||
filestatus = 0;
|
continue;
|
||||||
else
|
|
||||||
filestatus = 1; // Important
|
filestatus = 1; // Importance - not really used any more, holds 1 by default for backwards compat with MS
|
||||||
|
|
||||||
// Store in the upper four bits
|
// Store in the upper four bits
|
||||||
if (!cv_downloading.value)
|
if (!cv_downloading.value)
|
||||||
filestatus += (2 << 4); // Won't send
|
filestatus += (2 << 4); // Won't send
|
||||||
else if ((wadfiles[i]->filesize > (UINT32)cv_maxsend.value * 1024))
|
else if ((wadfiles[i]->filesize <= (UINT32)cv_maxsend.value * 1024))
|
||||||
filestatus += (0 << 4); // Won't send
|
|
||||||
else
|
|
||||||
filestatus += (1 << 4); // Will send if requested
|
filestatus += (1 << 4); // Will send if requested
|
||||||
|
// else
|
||||||
bytesused += (nameonlylength(wadfilename) + 22);
|
// filestatus += (0 << 4); -- Won't send, too big
|
||||||
|
|
||||||
// Don't write too far...
|
|
||||||
if (bytesused > sizeof(netbuffer->u.serverinfo.fileneeded))
|
|
||||||
I_Error("Too many wad files added to host a game. (%s, stopped on %s)\n", sizeu1(bytesused), wadfilename);
|
|
||||||
|
|
||||||
WRITEUINT8(p, filestatus);
|
WRITEUINT8(p, filestatus);
|
||||||
|
|
||||||
|
@ -167,7 +161,6 @@ 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].status = FS_NOTFOUND; // We haven't even started looking for the file yet
|
||||||
filestatus = READUINT8(p); // The first byte is the file status
|
filestatus = READUINT8(p); // The first byte is the file status
|
||||||
fileneeded[i].important = (UINT8)(filestatus & 3);
|
|
||||||
fileneeded[i].willsend = (UINT8)(filestatus >> 4);
|
fileneeded[i].willsend = (UINT8)(filestatus >> 4);
|
||||||
fileneeded[i].totalsize = READUINT32(p); // The four next bytes are the file size
|
fileneeded[i].totalsize = READUINT32(p); // The four next bytes are the file size
|
||||||
fileneeded[i].file = NULL; // The file isn't open yet
|
fileneeded[i].file = NULL; // The file isn't open yet
|
||||||
|
@ -197,7 +190,7 @@ boolean CL_CheckDownloadable(void)
|
||||||
UINT8 i,dlstatus = 0;
|
UINT8 i,dlstatus = 0;
|
||||||
|
|
||||||
for (i = 0; i < fileneedednum; i++)
|
for (i = 0; i < fileneedednum; i++)
|
||||||
if (fileneeded[i].status != FS_FOUND && fileneeded[i].status != FS_OPEN && fileneeded[i].important)
|
if (fileneeded[i].status != FS_FOUND && fileneeded[i].status != FS_OPEN)
|
||||||
{
|
{
|
||||||
if (fileneeded[i].willsend == 1)
|
if (fileneeded[i].willsend == 1)
|
||||||
continue;
|
continue;
|
||||||
|
@ -218,7 +211,7 @@ boolean CL_CheckDownloadable(void)
|
||||||
// not downloadable, put reason in console
|
// not downloadable, put reason in console
|
||||||
CONS_Alert(CONS_NOTICE, M_GetText("You need additional files to connect to this server:\n"));
|
CONS_Alert(CONS_NOTICE, M_GetText("You need additional files to connect to this server:\n"));
|
||||||
for (i = 0; i < fileneedednum; i++)
|
for (i = 0; i < fileneedednum; i++)
|
||||||
if (fileneeded[i].status != FS_FOUND && fileneeded[i].status != FS_OPEN && fileneeded[i].important)
|
if (fileneeded[i].status != FS_FOUND && fileneeded[i].status != FS_OPEN)
|
||||||
{
|
{
|
||||||
CONS_Printf(" * \"%s\" (%dK)", fileneeded[i].filename, fileneeded[i].totalsize >> 10);
|
CONS_Printf(" * \"%s\" (%dK)", fileneeded[i].filename, fileneeded[i].totalsize >> 10);
|
||||||
|
|
||||||
|
@ -271,7 +264,7 @@ boolean CL_SendRequestFile(void)
|
||||||
|
|
||||||
for (i = 0; i < fileneedednum; i++)
|
for (i = 0; i < fileneedednum; i++)
|
||||||
if (fileneeded[i].status != FS_FOUND && fileneeded[i].status != FS_OPEN
|
if (fileneeded[i].status != FS_FOUND && fileneeded[i].status != FS_OPEN
|
||||||
&& fileneeded[i].important && (fileneeded[i].willsend == 0 || fileneeded[i].willsend == 2))
|
&& (fileneeded[i].willsend == 0 || fileneeded[i].willsend == 2))
|
||||||
{
|
{
|
||||||
I_Error("Attempted to download files that were not sendable");
|
I_Error("Attempted to download files that were not sendable");
|
||||||
}
|
}
|
||||||
|
@ -280,8 +273,7 @@ boolean CL_SendRequestFile(void)
|
||||||
netbuffer->packettype = PT_REQUESTFILE;
|
netbuffer->packettype = PT_REQUESTFILE;
|
||||||
p = (char *)netbuffer->u.textcmd;
|
p = (char *)netbuffer->u.textcmd;
|
||||||
for (i = 0; i < fileneedednum; i++)
|
for (i = 0; i < fileneedednum; i++)
|
||||||
if ((fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_MD5SUMBAD)
|
if ((fileneeded[i].status == FS_NOTFOUND || fileneeded[i].status == FS_MD5SUMBAD))
|
||||||
&& fileneeded[i].important)
|
|
||||||
{
|
{
|
||||||
totalfreespaceneeded += fileneeded[i].totalsize;
|
totalfreespaceneeded += fileneeded[i].totalsize;
|
||||||
nameonly(fileneeded[i].filename);
|
nameonly(fileneeded[i].filename);
|
||||||
|
@ -360,15 +352,9 @@ INT32 CL_CheckFiles(void)
|
||||||
CONS_Debug(DBG_NETPLAY, "game is modified; only doing basic checks\n");
|
CONS_Debug(DBG_NETPLAY, "game is modified; only doing basic checks\n");
|
||||||
for (i = 1, j = 1; i < fileneedednum || j < numwadfiles;)
|
for (i = 1, j = 1; i < fileneedednum || j < numwadfiles;)
|
||||||
{
|
{
|
||||||
if (i < fileneedednum && !fileneeded[i].important)
|
if (j < numwadfiles && !wadfiles[j]->important)
|
||||||
{
|
{
|
||||||
// Eh whatever, don't care
|
// Unimportant on our side.
|
||||||
++i;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (j < numwadfiles && W_VerifyNMUSlumps(wadfiles[j]->filename))
|
|
||||||
{
|
|
||||||
// Unimportant on our side. still don't care.
|
|
||||||
++j;
|
++j;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -411,7 +397,7 @@ INT32 CL_CheckFiles(void)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (fileneeded[i].status != FS_NOTFOUND || !fileneeded[i].important)
|
if (fileneeded[i].status != FS_NOTFOUND)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
packetsize += nameonlylength(fileneeded[i].filename) + 22;
|
packetsize += nameonlylength(fileneeded[i].filename) + 22;
|
||||||
|
@ -449,27 +435,8 @@ void CL_LoadServerFiles(void)
|
||||||
fileneeded[i].status = FS_OPEN;
|
fileneeded[i].status = FS_OPEN;
|
||||||
}
|
}
|
||||||
else if (fileneeded[i].status == FS_MD5SUMBAD)
|
else if (fileneeded[i].status == FS_MD5SUMBAD)
|
||||||
{
|
I_Error("Wrong version of file %s", fileneeded[i].filename);
|
||||||
// If the file is marked important, don't even bother proceeding.
|
else
|
||||||
if (fileneeded[i].important)
|
|
||||||
I_Error("Wrong version of important file %s", fileneeded[i].filename);
|
|
||||||
|
|
||||||
// If it isn't, no need to worry the user with a console message,
|
|
||||||
// although it can't hurt to put something in the debug file.
|
|
||||||
|
|
||||||
// ...but wait a second. What if the local version is "important"?
|
|
||||||
if (!W_VerifyNMUSlumps(fileneeded[i].filename))
|
|
||||||
I_Error("File %s should only contain music and sound effects!",
|
|
||||||
fileneeded[i].filename);
|
|
||||||
|
|
||||||
// Okay, NOW we know it's safe. Whew.
|
|
||||||
P_AddWadFile(fileneeded[i].filename, NULL);
|
|
||||||
if (fileneeded[i].important)
|
|
||||||
G_SetGameModified(true);
|
|
||||||
fileneeded[i].status = FS_OPEN;
|
|
||||||
DEBFILE(va("File %s found but with different md5sum\n", fileneeded[i].filename));
|
|
||||||
}
|
|
||||||
else if (fileneeded[i].important)
|
|
||||||
{
|
{
|
||||||
const char *s;
|
const char *s;
|
||||||
switch(fileneeded[i].status)
|
switch(fileneeded[i].status)
|
||||||
|
|
|
@ -35,7 +35,6 @@ typedef enum
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
UINT8 important;
|
|
||||||
UINT8 willsend; // Is the server willing to send it?
|
UINT8 willsend; // Is the server willing to send it?
|
||||||
char filename[MAX_WADPATH];
|
char filename[MAX_WADPATH];
|
||||||
UINT8 md5sum[16];
|
UINT8 md5sum[16];
|
||||||
|
|
335
src/filesrch.c
335
src/filesrch.c
|
@ -31,6 +31,8 @@
|
||||||
#include "filesrch.h"
|
#include "filesrch.h"
|
||||||
#include "d_netfil.h"
|
#include "d_netfil.h"
|
||||||
#include "m_misc.h"
|
#include "m_misc.h"
|
||||||
|
#include "z_zone.h"
|
||||||
|
#include "m_menu.h" // Addons_option_Onchange
|
||||||
|
|
||||||
#if (defined (_WIN32) && !defined (_WIN32_WCE)) && defined (_MSC_VER) && !defined (_XBOX)
|
#if (defined (_WIN32) && !defined (_WIN32_WCE)) && defined (_MSC_VER) && !defined (_XBOX)
|
||||||
|
|
||||||
|
@ -255,6 +257,28 @@ readdir (DIR * dirp)
|
||||||
return (struct dirent *) 0;
|
return (struct dirent *) 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* rewinddir
|
||||||
|
*
|
||||||
|
* Makes the next readdir start from the beginning.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
rewinddir (DIR * dirp)
|
||||||
|
{
|
||||||
|
errno = 0;
|
||||||
|
|
||||||
|
/* Check for valid DIR struct. */
|
||||||
|
if (!dirp)
|
||||||
|
{
|
||||||
|
errno = EFAULT;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
dirp->dd_stat = 0;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* closedir
|
* closedir
|
||||||
*
|
*
|
||||||
|
@ -285,6 +309,35 @@ closedir (DIR * dirp)
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static CV_PossibleValue_t addons_cons_t[] = {{0, "SRB2 Folder"}, /*{1, "HOME"}, {2, "SRB2 Folder"},*/ {3, "CUSTOM"}, {0, NULL}};
|
||||||
|
consvar_t cv_addons_option = {"addons_option", "SRB2 Folder", CV_SAVE|CV_CALL, addons_cons_t, Addons_option_Onchange, 0, NULL, NULL, 0, 0, NULL};
|
||||||
|
consvar_t cv_addons_folder = {"addons_folder", "./", CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||||
|
|
||||||
|
static CV_PossibleValue_t addons_md5_cons_t[] = {{0, "Name"}, {1, "Contents"}, {0, NULL}};
|
||||||
|
consvar_t cv_addons_md5 = {"addons_md5", "Name", CV_SAVE, addons_md5_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||||
|
|
||||||
|
consvar_t cv_addons_showall = {"addons_showall", "No", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||||
|
|
||||||
|
consvar_t cv_addons_search_case = {"addons_search_case", "No", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||||
|
|
||||||
|
static CV_PossibleValue_t addons_search_type_cons_t[] = {{0, "Start"}, {1, "Anywhere"}, {0, NULL}};
|
||||||
|
consvar_t cv_addons_search_type = {"addons_search_type", "Anywhere", CV_SAVE, addons_search_type_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||||
|
|
||||||
|
char menupath[1024];
|
||||||
|
size_t menupathindex[menudepth];
|
||||||
|
size_t menudepthleft = menudepth;
|
||||||
|
|
||||||
|
char menusearch[MAXSTRINGLENGTH+1];
|
||||||
|
|
||||||
|
char **dirmenu;
|
||||||
|
size_t sizedirmenu;
|
||||||
|
size_t dir_on[menudepth];
|
||||||
|
UINT8 refreshdirmenu = 0;
|
||||||
|
|
||||||
|
size_t packetsizetally = 0;
|
||||||
|
size_t mainwadstally = 0;
|
||||||
|
|
||||||
#if defined (_XBOX) && defined (_MSC_VER)
|
#if defined (_XBOX) && defined (_MSC_VER)
|
||||||
filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *wantedmd5sum,
|
filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *wantedmd5sum,
|
||||||
boolean completepath, int maxsearchdepth)
|
boolean completepath, int maxsearchdepth)
|
||||||
|
@ -296,6 +349,13 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want
|
||||||
completepath = false;
|
completepath = false;
|
||||||
return FS_NOTFOUND;
|
return FS_NOTFOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean preparefilemenu(boolean samedepth)
|
||||||
|
{
|
||||||
|
(void)samedepth;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
#elif defined (_WIN32_WCE)
|
#elif defined (_WIN32_WCE)
|
||||||
filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *wantedmd5sum,
|
filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *wantedmd5sum,
|
||||||
boolean completepath, int maxsearchdepth)
|
boolean completepath, int maxsearchdepth)
|
||||||
|
@ -346,6 +406,12 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want
|
||||||
#endif
|
#endif
|
||||||
return FS_NOTFOUND;
|
return FS_NOTFOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean preparefilemenu(boolean samedepth)
|
||||||
|
{
|
||||||
|
(void)samedepth;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *wantedmd5sum, boolean completepath, int maxsearchdepth)
|
filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *wantedmd5sum, boolean completepath, int maxsearchdepth)
|
||||||
{
|
{
|
||||||
|
@ -387,25 +453,29 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want
|
||||||
{
|
{
|
||||||
searchpath[searchpathindex[depthleft]]=0;
|
searchpath[searchpathindex[depthleft]]=0;
|
||||||
dent = readdir(dirhandle[depthleft]);
|
dent = readdir(dirhandle[depthleft]);
|
||||||
if (dent)
|
|
||||||
strcpy(&searchpath[searchpathindex[depthleft]],dent->d_name);
|
|
||||||
|
|
||||||
if (!dent)
|
if (!dent)
|
||||||
|
{
|
||||||
closedir(dirhandle[depthleft++]);
|
closedir(dirhandle[depthleft++]);
|
||||||
else if (dent->d_name[0]=='.' &&
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dent->d_name[0]=='.' &&
|
||||||
(dent->d_name[1]=='\0' ||
|
(dent->d_name[1]=='\0' ||
|
||||||
(dent->d_name[1]=='.' &&
|
(dent->d_name[1]=='.' &&
|
||||||
dent->d_name[2]=='\0')))
|
dent->d_name[2]=='\0')))
|
||||||
{
|
{
|
||||||
// we don't want to scan uptree
|
// we don't want to scan uptree
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
else if (stat(searchpath,&fsstat) < 0) // do we want to follow symlinks? if not: change it to lstat
|
|
||||||
{
|
// okay, now we actually want searchpath to incorporate d_name
|
||||||
// was the file (re)moved? can't stat it
|
strcpy(&searchpath[searchpathindex[depthleft]],dent->d_name);
|
||||||
}
|
|
||||||
|
if (stat(searchpath,&fsstat) < 0) // do we want to follow symlinks? if not: change it to lstat
|
||||||
|
; // was the file (re)moved? can't stat it
|
||||||
else if (S_ISDIR(fsstat.st_mode) && depthleft)
|
else if (S_ISDIR(fsstat.st_mode) && depthleft)
|
||||||
{
|
{
|
||||||
strcpy(&searchpath[searchpathindex[depthleft]],dent->d_name);
|
|
||||||
searchpathindex[--depthleft] = strlen(searchpath) + 1;
|
searchpathindex[--depthleft] = strlen(searchpath) + 1;
|
||||||
dirhandle[depthleft] = opendir(searchpath);
|
dirhandle[depthleft] = opendir(searchpath);
|
||||||
if (!dirhandle[depthleft])
|
if (!dirhandle[depthleft])
|
||||||
|
@ -444,6 +514,255 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want
|
||||||
free(searchname);
|
free(searchname);
|
||||||
free(searchpathindex);
|
free(searchpathindex);
|
||||||
free(dirhandle);
|
free(dirhandle);
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char exttable[NUM_EXT_TABLE][5] = {
|
||||||
|
".txt", ".cfg", // exec
|
||||||
|
".wad", ".soc", ".lua"}; // addfile
|
||||||
|
|
||||||
|
char filenamebuf[MAX_WADFILES][MAX_WADPATH];
|
||||||
|
|
||||||
|
|
||||||
|
static boolean filemenusearch(char *haystack, char *needle)
|
||||||
|
{
|
||||||
|
static char localhaystack[128];
|
||||||
|
strlcpy(localhaystack, haystack, 128);
|
||||||
|
if (!cv_addons_search_case.value)
|
||||||
|
strupr(localhaystack);
|
||||||
|
return ((cv_addons_search_type.value)
|
||||||
|
? (strstr(localhaystack, needle) != 0)
|
||||||
|
: (!strncmp(localhaystack, needle, menusearch[0])));
|
||||||
|
}
|
||||||
|
|
||||||
|
#define searchdir if (menusearch[0] && !filemenusearch(dent->d_name, localmenusearch))\
|
||||||
|
{\
|
||||||
|
rejected++;\
|
||||||
|
continue;\
|
||||||
|
}\
|
||||||
|
|
||||||
|
boolean preparefilemenu(boolean samedepth)
|
||||||
|
{
|
||||||
|
DIR *dirhandle;
|
||||||
|
struct dirent *dent;
|
||||||
|
struct stat fsstat;
|
||||||
|
size_t pos = 0, folderpos = 0, numfolders = 0, rejected = 0;
|
||||||
|
char *tempname = NULL;
|
||||||
|
boolean noresults = false;
|
||||||
|
char localmenusearch[MAXSTRINGLENGTH] = "";
|
||||||
|
|
||||||
|
if (samedepth)
|
||||||
|
{
|
||||||
|
if (dirmenu && dirmenu[dir_on[menudepthleft]])
|
||||||
|
tempname = Z_StrDup(dirmenu[dir_on[menudepthleft]]+DIR_STRING); // don't need to I_Error if can't make - not important, just QoL
|
||||||
|
}
|
||||||
|
else
|
||||||
|
menusearch[0] = menusearch[1] = 0; // clear search
|
||||||
|
|
||||||
|
for (; sizedirmenu > 0; sizedirmenu--) // clear out existing items
|
||||||
|
{
|
||||||
|
Z_Free(dirmenu[sizedirmenu-1]);
|
||||||
|
dirmenu[sizedirmenu-1] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(dirhandle = opendir(menupath))) // get directory
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (menusearch[0])
|
||||||
|
{
|
||||||
|
strcpy(localmenusearch, menusearch+1);
|
||||||
|
if (!cv_addons_search_case.value)
|
||||||
|
strupr(localmenusearch);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
menupath[menupathindex[menudepthleft]] = 0;
|
||||||
|
dent = readdir(dirhandle);
|
||||||
|
|
||||||
|
if (!dent)
|
||||||
|
break;
|
||||||
|
else if (dent->d_name[0]=='.' &&
|
||||||
|
(dent->d_name[1]=='\0' ||
|
||||||
|
(dent->d_name[1]=='.' &&
|
||||||
|
dent->d_name[2]=='\0')))
|
||||||
|
continue; // we don't want to scan uptree
|
||||||
|
|
||||||
|
strcpy(&menupath[menupathindex[menudepthleft]],dent->d_name);
|
||||||
|
|
||||||
|
if (stat(menupath,&fsstat) < 0) // do we want to follow symlinks? if not: change it to lstat
|
||||||
|
; // was the file (re)moved? can't stat it
|
||||||
|
else // is a file or directory
|
||||||
|
{
|
||||||
|
if (!S_ISDIR(fsstat.st_mode)) // file
|
||||||
|
{
|
||||||
|
if (!cv_addons_showall.value)
|
||||||
|
{
|
||||||
|
size_t len = strlen(dent->d_name)+1;
|
||||||
|
UINT8 ext;
|
||||||
|
for (ext = 0; ext < NUM_EXT_TABLE; ext++)
|
||||||
|
if (!strcasecmp(exttable[ext], dent->d_name+len-5)) break; // extension comparison
|
||||||
|
if (ext == NUM_EXT_TABLE) continue; // not an addfile-able (or exec-able) file
|
||||||
|
}
|
||||||
|
searchdir;
|
||||||
|
}
|
||||||
|
else // directory
|
||||||
|
{
|
||||||
|
searchdir;
|
||||||
|
numfolders++;
|
||||||
|
}
|
||||||
|
sizedirmenu++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!rejected && !sizedirmenu)
|
||||||
|
{
|
||||||
|
if (tempname)
|
||||||
|
Z_Free(tempname);
|
||||||
|
closedir(dirhandle);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((noresults = (menusearch[0] && !sizedirmenu)))
|
||||||
|
|| (!menusearch[0] && menudepthleft != menudepth-1)) // Make room for UP... or search entry
|
||||||
|
{
|
||||||
|
sizedirmenu++;
|
||||||
|
numfolders++;
|
||||||
|
folderpos++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(dirmenu = Z_Realloc(dirmenu, sizedirmenu*sizeof(char *), PU_STATIC, NULL)))
|
||||||
|
{
|
||||||
|
closedir(dirhandle); // just in case
|
||||||
|
I_Error("Ran out of memory whilst preparing add-ons menu");
|
||||||
|
}
|
||||||
|
|
||||||
|
rejected = 0;
|
||||||
|
rewinddir(dirhandle);
|
||||||
|
|
||||||
|
while ((pos+folderpos) < sizedirmenu)
|
||||||
|
{
|
||||||
|
menupath[menupathindex[menudepthleft]] = 0;
|
||||||
|
dent = readdir(dirhandle);
|
||||||
|
|
||||||
|
if (!dent)
|
||||||
|
break;
|
||||||
|
else if (dent->d_name[0]=='.' &&
|
||||||
|
(dent->d_name[1]=='\0' ||
|
||||||
|
(dent->d_name[1]=='.' &&
|
||||||
|
dent->d_name[2]=='\0')))
|
||||||
|
continue; // we don't want to scan uptree
|
||||||
|
|
||||||
|
strcpy(&menupath[menupathindex[menudepthleft]],dent->d_name);
|
||||||
|
|
||||||
|
if (stat(menupath,&fsstat) < 0) // do we want to follow symlinks? if not: change it to lstat
|
||||||
|
; // was the file (re)moved? can't stat it
|
||||||
|
else // is a file or directory
|
||||||
|
{
|
||||||
|
char *temp;
|
||||||
|
size_t len = strlen(dent->d_name)+1;
|
||||||
|
UINT8 ext = EXT_FOLDER;
|
||||||
|
UINT8 folder;
|
||||||
|
|
||||||
|
if (!S_ISDIR(fsstat.st_mode)) // file
|
||||||
|
{
|
||||||
|
if (!((numfolders+pos) < sizedirmenu)) continue; // crash prevention
|
||||||
|
for (; ext < NUM_EXT_TABLE; ext++)
|
||||||
|
if (!strcasecmp(exttable[ext], dent->d_name+len-5)) break; // extension comparison
|
||||||
|
if (ext == NUM_EXT_TABLE && !cv_addons_showall.value) continue; // not an addfile-able (or exec-able) file
|
||||||
|
ext += EXT_START; // moving to be appropriate position
|
||||||
|
|
||||||
|
searchdir;
|
||||||
|
|
||||||
|
if (ext >= EXT_LOADSTART)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
for (i = 0; i < numwadfiles; i++)
|
||||||
|
{
|
||||||
|
if (!filenamebuf[i][0])
|
||||||
|
{
|
||||||
|
strncpy(filenamebuf[i], wadfiles[i]->filename, MAX_WADPATH);
|
||||||
|
filenamebuf[i][MAX_WADPATH - 1] = '\0';
|
||||||
|
nameonly(filenamebuf[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(dent->d_name, filenamebuf[i]))
|
||||||
|
continue;
|
||||||
|
if (cv_addons_md5.value && !checkfilemd5(menupath, wadfiles[i]->md5sum))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ext |= EXT_LOADED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (ext == EXT_TXT)
|
||||||
|
{
|
||||||
|
if (!strcmp(dent->d_name, "log.txt") || !strcmp(dent->d_name, "errorlog.txt"))
|
||||||
|
ext |= EXT_LOADED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strcmp(dent->d_name, configfile))
|
||||||
|
ext |= EXT_LOADED;
|
||||||
|
|
||||||
|
folder = 0;
|
||||||
|
}
|
||||||
|
else // directory
|
||||||
|
{
|
||||||
|
searchdir;
|
||||||
|
len += (folder = 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len > 255)
|
||||||
|
len = 255;
|
||||||
|
|
||||||
|
if (!(temp = Z_Malloc((len+DIR_STRING+folder) * sizeof (char), PU_STATIC, NULL)))
|
||||||
|
I_Error("Ran out of memory whilst preparing add-ons menu");
|
||||||
|
temp[DIR_TYPE] = ext;
|
||||||
|
temp[DIR_LEN] = (UINT8)(len);
|
||||||
|
strlcpy(temp+DIR_STRING, dent->d_name, len);
|
||||||
|
if (folder)
|
||||||
|
{
|
||||||
|
strcpy(temp+len, "/");
|
||||||
|
dirmenu[folderpos++] = temp;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
dirmenu[numfolders + pos++] = temp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
closedir(dirhandle);
|
||||||
|
|
||||||
|
if (noresults) // no results
|
||||||
|
dirmenu[0] = Z_StrDup(va("%c\13No results...", EXT_NORESULTS));
|
||||||
|
else if (!menusearch[0] &&menudepthleft != menudepth-1) // now for UP... entry
|
||||||
|
dirmenu[0] = Z_StrDup(va("%c\5UP...", EXT_UP));
|
||||||
|
|
||||||
|
menupath[menupathindex[menudepthleft]] = 0;
|
||||||
|
sizedirmenu = (numfolders+pos); // just in case things shrink between opening and rewind
|
||||||
|
|
||||||
|
if (tempname)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
for (i = 0; i < sizedirmenu; i++)
|
||||||
|
{
|
||||||
|
if (!strcmp(dirmenu[i]+DIR_STRING, tempname))
|
||||||
|
{
|
||||||
|
dir_on[menudepthleft] = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Z_Free(tempname);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sizedirmenu)
|
||||||
|
{
|
||||||
|
dir_on[menudepthleft] = 0;
|
||||||
|
Z_Free(dirmenu);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if (dir_on[menudepthleft] >= sizedirmenu)
|
||||||
|
dir_on[menudepthleft] = sizedirmenu-1;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -6,6 +6,9 @@
|
||||||
|
|
||||||
#include "doomdef.h"
|
#include "doomdef.h"
|
||||||
#include "d_netfil.h"
|
#include "d_netfil.h"
|
||||||
|
#include "m_menu.h" // MAXSTRINGLENGTH
|
||||||
|
|
||||||
|
extern consvar_t cv_addons_option, cv_addons_folder, cv_addons_md5, cv_addons_showall, cv_addons_search_case, cv_addons_search_type;
|
||||||
|
|
||||||
/** \brief The filesearch function
|
/** \brief The filesearch function
|
||||||
|
|
||||||
|
@ -25,4 +28,64 @@
|
||||||
filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *wantedmd5sum,
|
filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *wantedmd5sum,
|
||||||
boolean completepath, int maxsearchdepth);
|
boolean completepath, int maxsearchdepth);
|
||||||
|
|
||||||
|
#define menudepth 20
|
||||||
|
|
||||||
|
extern char menupath[1024];
|
||||||
|
extern size_t menupathindex[menudepth];
|
||||||
|
extern size_t menudepthleft;
|
||||||
|
|
||||||
|
extern char menusearch[MAXSTRINGLENGTH+1];
|
||||||
|
|
||||||
|
extern char **dirmenu;
|
||||||
|
extern size_t sizedirmenu;
|
||||||
|
extern size_t dir_on[menudepth];
|
||||||
|
extern UINT8 refreshdirmenu;
|
||||||
|
|
||||||
|
extern size_t packetsizetally;
|
||||||
|
extern size_t mainwadstally;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
EXT_FOLDER = 0,
|
||||||
|
EXT_UP,
|
||||||
|
EXT_NORESULTS,
|
||||||
|
EXT_START,
|
||||||
|
EXT_TXT = EXT_START,
|
||||||
|
EXT_CFG,
|
||||||
|
EXT_LOADSTART,
|
||||||
|
EXT_WAD = EXT_LOADSTART,
|
||||||
|
EXT_SOC,
|
||||||
|
EXT_LUA, // allowed even if not HAVE_BLUA so that we can yell on load attempt
|
||||||
|
NUM_EXT,
|
||||||
|
NUM_EXT_TABLE = NUM_EXT-EXT_START,
|
||||||
|
EXT_LOADED = 0x80
|
||||||
|
/*
|
||||||
|
obviously there can only be 0x7F supported extensions in
|
||||||
|
addons menu because we're cramming this into a char out of
|
||||||
|
laziness/easy memory allocation (what's the difference?)
|
||||||
|
and have stolen a bit to show whether it's loaded or not
|
||||||
|
in practice the size of the data type is probably overkill
|
||||||
|
toast 02/05/17
|
||||||
|
*/
|
||||||
|
} ext_enum;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
DIR_TYPE = 0,
|
||||||
|
DIR_LEN,
|
||||||
|
DIR_STRING
|
||||||
|
} dirname_enum;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
REFRESHDIR_NORMAL = 1,
|
||||||
|
REFRESHDIR_ADDFILE = 2,
|
||||||
|
REFRESHDIR_WARNING = 4,
|
||||||
|
REFRESHDIR_ERROR = 8,
|
||||||
|
REFRESHDIR_NOTLOADED = 16,
|
||||||
|
REFRESHDIR_MAX = 32
|
||||||
|
} refreshdir_enum;
|
||||||
|
|
||||||
|
boolean preparefilemenu(boolean samedepth);
|
||||||
|
|
||||||
#endif // __FILESRCH_H__
|
#endif // __FILESRCH_H__
|
||||||
|
|
666
src/m_menu.c
666
src/m_menu.c
|
@ -33,6 +33,9 @@
|
||||||
#include "s_sound.h"
|
#include "s_sound.h"
|
||||||
#include "i_system.h"
|
#include "i_system.h"
|
||||||
|
|
||||||
|
// Addfile
|
||||||
|
#include "filesrch.h"
|
||||||
|
|
||||||
#include "v_video.h"
|
#include "v_video.h"
|
||||||
#include "i_video.h"
|
#include "i_video.h"
|
||||||
#include "keys.h"
|
#include "keys.h"
|
||||||
|
@ -74,7 +77,6 @@ int snprintf(char *str, size_t n, const char *fmt, ...);
|
||||||
#define SMALLLINEHEIGHT 8
|
#define SMALLLINEHEIGHT 8
|
||||||
#define SLIDER_RANGE 9
|
#define SLIDER_RANGE 9
|
||||||
#define SLIDER_WIDTH 78
|
#define SLIDER_WIDTH 78
|
||||||
#define MAXSTRINGLENGTH 32
|
|
||||||
#define SERVERS_PER_PAGE 11
|
#define SERVERS_PER_PAGE 11
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
|
@ -211,14 +213,13 @@ menu_t SPauseDef;
|
||||||
|
|
||||||
// Level Select
|
// Level Select
|
||||||
static levelselect_t levelselect = {0, NULL};
|
static levelselect_t levelselect = {0, NULL};
|
||||||
static UINT8 levelselectselect[4];
|
static UINT8 levelselectselect[3];
|
||||||
static patch_t *levselp[2][3];
|
static patch_t *levselp[2][3];
|
||||||
static INT32 lsoffs[2];
|
static INT32 lsoffs[2];
|
||||||
|
|
||||||
#define lsrow levelselectselect[0]
|
#define lsrow levelselectselect[0]
|
||||||
#define lscol levelselectselect[1]
|
#define lscol levelselectselect[1]
|
||||||
#define lstic levelselectselect[2]
|
#define lshli levelselectselect[2]
|
||||||
#define lshli levelselectselect[3]
|
|
||||||
|
|
||||||
#define lshseperation 101
|
#define lshseperation 101
|
||||||
#define lsbasevseperation 62
|
#define lsbasevseperation 62
|
||||||
|
@ -334,12 +335,20 @@ menu_t OP_MonitorToggleDef;
|
||||||
static void M_ScreenshotOptions(INT32 choice);
|
static void M_ScreenshotOptions(INT32 choice);
|
||||||
static void M_EraseData(INT32 choice);
|
static void M_EraseData(INT32 choice);
|
||||||
|
|
||||||
static void M_DrawLevelPlatterHeader(INT32 y, const char *header, boolean headerhighlight);
|
static void M_Addons(INT32 choice);
|
||||||
|
static void M_AddonsOptions(INT32 choice);
|
||||||
|
static patch_t *addonsp[NUM_EXT+6];
|
||||||
|
static UINT8 addonsresponselimit = 0;
|
||||||
|
|
||||||
|
#define numaddonsshown 4
|
||||||
|
|
||||||
|
static void M_DrawLevelPlatterHeader(INT32 y, const char *header, boolean headerhighlight, boolean allowlowercase);
|
||||||
|
|
||||||
// Drawing functions
|
// Drawing functions
|
||||||
static void M_DrawGenericMenu(void);
|
static void M_DrawGenericMenu(void);
|
||||||
static void M_DrawGenericScrollMenu(void);
|
static void M_DrawGenericScrollMenu(void);
|
||||||
static void M_DrawCenteredMenu(void);
|
static void M_DrawCenteredMenu(void);
|
||||||
|
static void M_DrawAddons(void);
|
||||||
static void M_DrawSkyRoom(void);
|
static void M_DrawSkyRoom(void);
|
||||||
static void M_DrawChecklist(void);
|
static void M_DrawChecklist(void);
|
||||||
static void M_DrawEmblemHints(void);
|
static void M_DrawEmblemHints(void);
|
||||||
|
@ -379,6 +388,7 @@ static boolean M_CancelConnect(void);
|
||||||
#endif
|
#endif
|
||||||
static boolean M_ExitPandorasBox(void);
|
static boolean M_ExitPandorasBox(void);
|
||||||
static boolean M_QuitMultiPlayerMenu(void);
|
static boolean M_QuitMultiPlayerMenu(void);
|
||||||
|
static void M_HandleAddons(INT32 choice);
|
||||||
static void M_HandleLevelPlatter(INT32 choice);
|
static void M_HandleLevelPlatter(INT32 choice);
|
||||||
static void M_HandleSoundTest(INT32 choice);
|
static void M_HandleSoundTest(INT32 choice);
|
||||||
static void M_HandleImageDef(INT32 choice);
|
static void M_HandleImageDef(INT32 choice);
|
||||||
|
@ -487,10 +497,11 @@ static consvar_t cv_dummymares = {"dummymares", "Overall", CV_HIDEN|CV_CALL, dum
|
||||||
// ---------
|
// ---------
|
||||||
static menuitem_t MainMenu[] =
|
static menuitem_t MainMenu[] =
|
||||||
{
|
{
|
||||||
{IT_CALL |IT_STRING, NULL, "Secrets", M_SecretsMenu, 84},
|
{IT_CALL |IT_STRING, NULL, "Secrets", M_SecretsMenu, 76},
|
||||||
{IT_CALL |IT_STRING, NULL, "1 player", M_SinglePlayerMenu, 92},
|
{IT_CALL |IT_STRING, NULL, "1 player", M_SinglePlayerMenu, 84},
|
||||||
{IT_SUBMENU|IT_STRING, NULL, "multiplayer", &MP_MainDef, 100},
|
{IT_SUBMENU|IT_STRING, NULL, "multiplayer", &MP_MainDef, 92},
|
||||||
{IT_CALL |IT_STRING, NULL, "options", M_Options, 108},
|
{IT_CALL |IT_STRING, NULL, "options", M_Options, 100},
|
||||||
|
{IT_CALL |IT_STRING, NULL, "addons", M_Addons, 108},
|
||||||
{IT_CALL |IT_STRING, NULL, "quit game", M_QuitSRB2, 116},
|
{IT_CALL |IT_STRING, NULL, "quit game", M_QuitSRB2, 116},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -500,9 +511,15 @@ typedef enum
|
||||||
singleplr,
|
singleplr,
|
||||||
multiplr,
|
multiplr,
|
||||||
options,
|
options,
|
||||||
|
addons,
|
||||||
quitdoom
|
quitdoom
|
||||||
} main_e;
|
} main_e;
|
||||||
|
|
||||||
|
static menuitem_t MISC_AddonsMenu[] =
|
||||||
|
{
|
||||||
|
{IT_KEYHANDLER | IT_NOTHING, NULL, "", M_HandleAddons, 0}, // dummy menuitem for the control func
|
||||||
|
};
|
||||||
|
|
||||||
// ---------------------------------
|
// ---------------------------------
|
||||||
// Pause Menu Mode Attacking Edition
|
// Pause Menu Mode Attacking Edition
|
||||||
// ---------------------------------
|
// ---------------------------------
|
||||||
|
@ -525,26 +542,28 @@ typedef enum
|
||||||
// ---------------------
|
// ---------------------
|
||||||
static menuitem_t MPauseMenu[] =
|
static menuitem_t MPauseMenu[] =
|
||||||
{
|
{
|
||||||
{IT_STRING | IT_SUBMENU, NULL, "Scramble Teams...", &MISC_ScrambleTeamDef, 16},
|
{IT_STRING | IT_CALL, NULL, "Add-ons...", M_Addons, 8},
|
||||||
{IT_STRING | IT_CALL, NULL, "Switch Gametype/Level...", M_GameTypeChange, 24},
|
{IT_STRING | IT_SUBMENU, NULL, "Scramble Teams...", &MISC_ScrambleTeamDef, 16},
|
||||||
|
{IT_STRING | IT_CALL, NULL, "Switch Gametype/Level...", M_GameTypeChange, 24},
|
||||||
|
|
||||||
{IT_CALL | IT_STRING, NULL, "Continue", M_SelectableClearMenus,40},
|
{IT_STRING | IT_CALL, NULL, "Continue", M_SelectableClearMenus,40},
|
||||||
{IT_CALL | IT_STRING, NULL, "Player 1 Setup", M_SetupMultiPlayer, 48}, // splitscreen
|
{IT_STRING | IT_CALL, NULL, "Player 1 Setup", M_SetupMultiPlayer, 48}, // splitscreen
|
||||||
{IT_CALL | IT_STRING, NULL, "Player 2 Setup", M_SetupMultiPlayer2, 56}, // splitscreen
|
{IT_STRING | IT_CALL, NULL, "Player 2 Setup", M_SetupMultiPlayer2, 56}, // splitscreen
|
||||||
|
|
||||||
{IT_STRING | IT_CALL, NULL, "Spectate", M_ConfirmSpectate, 48},
|
{IT_STRING | IT_CALL, NULL, "Spectate", M_ConfirmSpectate, 48},
|
||||||
{IT_STRING | IT_CALL, NULL, "Enter Game", M_ConfirmEnterGame, 48},
|
{IT_STRING | IT_CALL, NULL, "Enter Game", M_ConfirmEnterGame, 48},
|
||||||
{IT_STRING | IT_SUBMENU, NULL, "Switch Team...", &MISC_ChangeTeamDef, 48},
|
{IT_STRING | IT_SUBMENU, NULL, "Switch Team...", &MISC_ChangeTeamDef, 48},
|
||||||
{IT_CALL | IT_STRING, NULL, "Player Setup", M_SetupMultiPlayer, 56}, // alone
|
{IT_STRING | IT_CALL, NULL, "Player Setup", M_SetupMultiPlayer, 56}, // alone
|
||||||
{IT_CALL | IT_STRING, NULL, "Options", M_Options, 64},
|
{IT_STRING | IT_CALL, NULL, "Options", M_Options, 64},
|
||||||
|
|
||||||
{IT_CALL | IT_STRING, NULL, "Return to Title", M_EndGame, 80},
|
{IT_STRING | IT_CALL, NULL, "Return to Title", M_EndGame, 80},
|
||||||
{IT_CALL | IT_STRING, NULL, "Quit Game", M_QuitSRB2, 88},
|
{IT_STRING | IT_CALL, NULL, "Quit Game", M_QuitSRB2, 88},
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
mpause_scramble = 0,
|
mpause_addons = 0,
|
||||||
|
mpause_scramble,
|
||||||
mpause_switchmap,
|
mpause_switchmap,
|
||||||
|
|
||||||
mpause_continue,
|
mpause_continue,
|
||||||
|
@ -587,6 +606,7 @@ typedef enum
|
||||||
spause_continue,
|
spause_continue,
|
||||||
spause_retry,
|
spause_retry,
|
||||||
spause_options,
|
spause_options,
|
||||||
|
|
||||||
spause_title,
|
spause_title,
|
||||||
spause_quit
|
spause_quit
|
||||||
} spause_e;
|
} spause_e;
|
||||||
|
@ -1318,9 +1338,10 @@ static menuitem_t OP_SoundOptionsMenu[] =
|
||||||
|
|
||||||
static menuitem_t OP_DataOptionsMenu[] =
|
static menuitem_t OP_DataOptionsMenu[] =
|
||||||
{
|
{
|
||||||
{IT_STRING | IT_CALL, NULL, "Screenshot Options...", M_ScreenshotOptions, 10},
|
{IT_STRING | IT_CALL, NULL, "Add-on Options...", M_AddonsOptions, 10},
|
||||||
|
{IT_STRING | IT_CALL, NULL, "Screenshot Options...", M_ScreenshotOptions, 20},
|
||||||
|
|
||||||
{IT_STRING | IT_SUBMENU, NULL, "\x85" "Erase Data...", &OP_EraseDataDef, 20},
|
{IT_STRING | IT_SUBMENU, NULL, "\x85" "Erase Data...", &OP_EraseDataDef, 40},
|
||||||
};
|
};
|
||||||
|
|
||||||
static menuitem_t OP_ScreenshotOptionsMenu[] =
|
static menuitem_t OP_ScreenshotOptionsMenu[] =
|
||||||
|
@ -1367,6 +1388,24 @@ static menuitem_t OP_EraseDataMenu[] =
|
||||||
{IT_STRING | IT_CALL, NULL, "\x85" "Erase ALL Data", M_EraseData, 40},
|
{IT_STRING | IT_CALL, NULL, "\x85" "Erase ALL Data", M_EraseData, 40},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static menuitem_t OP_AddonsOptionsMenu[] =
|
||||||
|
{
|
||||||
|
{IT_HEADER, NULL, "Menu", NULL, 0},
|
||||||
|
{IT_STRING|IT_CVAR, NULL, "Location", &cv_addons_option, 12},
|
||||||
|
{IT_STRING|IT_CVAR|IT_CV_STRING, NULL, "Custom Folder", &cv_addons_folder, 22},
|
||||||
|
{IT_STRING|IT_CVAR, NULL, "Identify loaded files via", &cv_addons_md5, 50},
|
||||||
|
{IT_STRING|IT_CVAR, NULL, "Show unsupported file types", &cv_addons_showall, 60},
|
||||||
|
|
||||||
|
{IT_HEADER, NULL, "Search", NULL, 78},
|
||||||
|
{IT_STRING|IT_CVAR, NULL, "Matching", &cv_addons_search_type, 90},
|
||||||
|
{IT_STRING|IT_CVAR, NULL, "Case-sensitive", &cv_addons_search_case, 100},
|
||||||
|
};
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
op_addons_folder = 2,
|
||||||
|
};
|
||||||
|
|
||||||
static menuitem_t OP_ServerOptionsMenu[] =
|
static menuitem_t OP_ServerOptionsMenu[] =
|
||||||
{
|
{
|
||||||
{IT_HEADER, NULL, "General", NULL, 0},
|
{IT_HEADER, NULL, "General", NULL, 0},
|
||||||
|
@ -1441,6 +1480,18 @@ static menuitem_t OP_MonitorToggleMenu[] =
|
||||||
// Main Menu and related
|
// Main Menu and related
|
||||||
menu_t MainDef = CENTERMENUSTYLE(NULL, MainMenu, NULL, 72);
|
menu_t MainDef = CENTERMENUSTYLE(NULL, MainMenu, NULL, 72);
|
||||||
|
|
||||||
|
menu_t MISC_AddonsDef =
|
||||||
|
{
|
||||||
|
NULL,
|
||||||
|
sizeof (MISC_AddonsMenu)/sizeof (menuitem_t),
|
||||||
|
&MainDef,
|
||||||
|
MISC_AddonsMenu,
|
||||||
|
M_DrawAddons,
|
||||||
|
50, 28,
|
||||||
|
0,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
menu_t MAPauseDef = PAUSEMENUSTYLE(MAPauseMenu, 40, 72);
|
menu_t MAPauseDef = PAUSEMENUSTYLE(MAPauseMenu, 40, 72);
|
||||||
menu_t SPauseDef = PAUSEMENUSTYLE(SPauseMenu, 40, 72);
|
menu_t SPauseDef = PAUSEMENUSTYLE(SPauseMenu, 40, 72);
|
||||||
menu_t MPauseDef = PAUSEMENUSTYLE(MPauseMenu, 40, 72);
|
menu_t MPauseDef = PAUSEMENUSTYLE(MPauseMenu, 40, 72);
|
||||||
|
@ -1804,17 +1855,7 @@ menu_t OP_SoundOptionsDef =
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
menu_t OP_ServerOptionsDef =
|
menu_t OP_ServerOptionsDef = DEFAULTSCROLLMENUSTYLE("M_SERVER", OP_ServerOptionsMenu, &OP_MainDef, 30, 30);
|
||||||
{
|
|
||||||
"M_SERVER",
|
|
||||||
sizeof (OP_ServerOptionsMenu)/sizeof (menuitem_t),
|
|
||||||
&OP_MainDef,
|
|
||||||
OP_ServerOptionsMenu,
|
|
||||||
M_DrawGenericScrollMenu,
|
|
||||||
30, 30,
|
|
||||||
0,
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
menu_t OP_MonitorToggleDef =
|
menu_t OP_MonitorToggleDef =
|
||||||
{
|
{
|
||||||
|
@ -1856,7 +1897,7 @@ menu_t OP_OpenGLColorDef =
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
menu_t OP_DataOptionsDef = DEFAULTMENUSTYLE("M_DATA", OP_DataOptionsMenu, &OP_MainDef, 30, 30);
|
menu_t OP_DataOptionsDef = DEFAULTMENUSTYLE("M_DATA", OP_DataOptionsMenu, &OP_MainDef, 60, 30);
|
||||||
|
|
||||||
menu_t OP_ScreenshotOptionsDef =
|
menu_t OP_ScreenshotOptionsDef =
|
||||||
{
|
{
|
||||||
|
@ -1870,6 +1911,8 @@ menu_t OP_ScreenshotOptionsDef =
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
menu_t OP_AddonsOptionsDef = DEFAULTMENUSTYLE("M_ADDONS", OP_AddonsOptionsMenu, &OP_DataOptionsDef, 30, 30);
|
||||||
|
|
||||||
menu_t OP_EraseDataDef = DEFAULTMENUSTYLE("M_DATA", OP_EraseDataMenu, &OP_DataOptionsDef, 60, 30);
|
menu_t OP_EraseDataDef = DEFAULTMENUSTYLE("M_DATA", OP_EraseDataMenu, &OP_DataOptionsDef, 60, 30);
|
||||||
|
|
||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
|
@ -2088,6 +2131,12 @@ void Moviemode_mode_Onchange(void)
|
||||||
OP_ScreenshotOptionsMenu[i].status = IT_STRING|IT_CVAR;
|
OP_ScreenshotOptionsMenu[i].status = IT_STRING|IT_CVAR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Addons_option_Onchange(void)
|
||||||
|
{
|
||||||
|
OP_AddonsOptionsMenu[op_addons_folder].status =
|
||||||
|
(cv_addons_option.value == 3 ? IT_CVAR|IT_STRING|IT_CV_STRING : IT_DISABLED);
|
||||||
|
}
|
||||||
|
|
||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
// END ORGANIZATION STUFF.
|
// END ORGANIZATION STUFF.
|
||||||
// ==========================================================================
|
// ==========================================================================
|
||||||
|
@ -2150,9 +2199,12 @@ static void M_ChangeCvar(INT32 choice)
|
||||||
static boolean M_ChangeStringCvar(INT32 choice)
|
static boolean M_ChangeStringCvar(INT32 choice)
|
||||||
{
|
{
|
||||||
consvar_t *cv = (consvar_t *)currentMenu->menuitems[itemOn].itemaction;
|
consvar_t *cv = (consvar_t *)currentMenu->menuitems[itemOn].itemaction;
|
||||||
char buf[255];
|
char buf[MAXSTRINGLENGTH];
|
||||||
size_t len;
|
size_t len;
|
||||||
|
|
||||||
|
if (shiftdown && choice >= 32 && choice <= 127)
|
||||||
|
choice = shiftxform[choice];
|
||||||
|
|
||||||
switch (choice)
|
switch (choice)
|
||||||
{
|
{
|
||||||
case KEY_BACKSPACE:
|
case KEY_BACKSPACE:
|
||||||
|
@ -2463,8 +2515,6 @@ boolean M_Responder(event_t *ev)
|
||||||
{
|
{
|
||||||
if ((currentMenu->menuitems[itemOn].status & IT_CVARTYPE) == IT_CV_STRING)
|
if ((currentMenu->menuitems[itemOn].status & IT_CVARTYPE) == IT_CV_STRING)
|
||||||
{
|
{
|
||||||
if (shiftdown && ch >= 32 && ch <= 127)
|
|
||||||
ch = shiftxform[ch];
|
|
||||||
if (M_ChangeStringCvar(ch))
|
if (M_ChangeStringCvar(ch))
|
||||||
return true;
|
return true;
|
||||||
else
|
else
|
||||||
|
@ -2710,6 +2760,7 @@ void M_StartControlPanel(void)
|
||||||
else // multiplayer
|
else // multiplayer
|
||||||
{
|
{
|
||||||
MPauseMenu[mpause_switchmap].status = IT_DISABLED;
|
MPauseMenu[mpause_switchmap].status = IT_DISABLED;
|
||||||
|
MPauseMenu[mpause_addons].status = IT_DISABLED;
|
||||||
MPauseMenu[mpause_scramble].status = IT_DISABLED;
|
MPauseMenu[mpause_scramble].status = IT_DISABLED;
|
||||||
MPauseMenu[mpause_psetupsplit].status = IT_DISABLED;
|
MPauseMenu[mpause_psetupsplit].status = IT_DISABLED;
|
||||||
MPauseMenu[mpause_psetupsplit2].status = IT_DISABLED;
|
MPauseMenu[mpause_psetupsplit2].status = IT_DISABLED;
|
||||||
|
@ -2721,6 +2772,7 @@ void M_StartControlPanel(void)
|
||||||
if ((server || adminplayer == consoleplayer))
|
if ((server || adminplayer == consoleplayer))
|
||||||
{
|
{
|
||||||
MPauseMenu[mpause_switchmap].status = IT_STRING | IT_CALL;
|
MPauseMenu[mpause_switchmap].status = IT_STRING | IT_CALL;
|
||||||
|
MPauseMenu[mpause_addons].status = IT_STRING | IT_CALL;
|
||||||
if (G_GametypeHasTeams())
|
if (G_GametypeHasTeams())
|
||||||
MPauseMenu[mpause_scramble].status = IT_STRING | IT_SUBMENU;
|
MPauseMenu[mpause_scramble].status = IT_STRING | IT_SUBMENU;
|
||||||
}
|
}
|
||||||
|
@ -3262,7 +3314,7 @@ static void M_DrawGenericMenu(void)
|
||||||
y = currentMenu->y+currentMenu->menuitems[i].alphaKey;
|
y = currentMenu->y+currentMenu->menuitems[i].alphaKey;
|
||||||
|
|
||||||
//V_DrawString(x-16, y, V_YELLOWMAP, currentMenu->menuitems[i].text);
|
//V_DrawString(x-16, y, V_YELLOWMAP, currentMenu->menuitems[i].text);
|
||||||
M_DrawLevelPlatterHeader(y - (lsheadingheight - 12), currentMenu->menuitems[i].text, true);
|
M_DrawLevelPlatterHeader(y - (lsheadingheight - 12), currentMenu->menuitems[i].text, true, false);
|
||||||
y += SMALLLINEHEIGHT;
|
y += SMALLLINEHEIGHT;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -3402,7 +3454,7 @@ static void M_DrawGenericScrollMenu(void)
|
||||||
break;
|
break;
|
||||||
case IT_HEADERTEXT:
|
case IT_HEADERTEXT:
|
||||||
//V_DrawString(x-16, y, V_YELLOWMAP, currentMenu->menuitems[i].text);
|
//V_DrawString(x-16, y, V_YELLOWMAP, currentMenu->menuitems[i].text);
|
||||||
M_DrawLevelPlatterHeader(y - (lsheadingheight - 12), currentMenu->menuitems[i].text, true);
|
M_DrawLevelPlatterHeader(y - (lsheadingheight - 12), currentMenu->menuitems[i].text, true, false);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3912,7 +3964,7 @@ static boolean M_PrepareLevelPlatter(INT32 gt)
|
||||||
I_Error("Insufficient memory to prepare level platter");
|
I_Error("Insufficient memory to prepare level platter");
|
||||||
|
|
||||||
// done here so lsrow and lscol can be set if cv_nextmap is on the platter
|
// done here so lsrow and lscol can be set if cv_nextmap is on the platter
|
||||||
lsrow = lscol = lstic = lshli = lsoffs[0] = lsoffs[1] = 0;
|
lsrow = lscol = lshli = lsoffs[0] = lsoffs[1] = 0;
|
||||||
|
|
||||||
while (mapnum < NUMMAPS)
|
while (mapnum < NUMMAPS)
|
||||||
{
|
{
|
||||||
|
@ -4171,10 +4223,10 @@ static void M_HandleLevelPlatter(INT32 choice)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void M_DrawLevelPlatterHeader(INT32 y, const char *header, boolean headerhighlight)
|
void M_DrawLevelPlatterHeader(INT32 y, const char *header, boolean headerhighlight, boolean allowlowercase)
|
||||||
{
|
{
|
||||||
y += lsheadingheight - 12;
|
y += lsheadingheight - 12;
|
||||||
V_DrawString(19, y, (headerhighlight ? V_YELLOWMAP : 0), header);
|
V_DrawString(19, y, (headerhighlight ? V_YELLOWMAP : 0)|(allowlowercase ? V_ALLOWLOWERCASE : 0), header);
|
||||||
y += 9;
|
y += 9;
|
||||||
if ((y >= 0) && (y < 200))
|
if ((y >= 0) && (y < 200))
|
||||||
{
|
{
|
||||||
|
@ -4183,9 +4235,7 @@ void M_DrawLevelPlatterHeader(INT32 y, const char *header, boolean headerhighlig
|
||||||
}
|
}
|
||||||
y++;
|
y++;
|
||||||
if ((y >= 0) && (y < 200))
|
if ((y >= 0) && (y < 200))
|
||||||
{
|
|
||||||
V_DrawFill(19, y, 282, 1, 26);
|
V_DrawFill(19, y, 282, 1, 26);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void M_DrawLevelPlatterWideMap(UINT8 row, UINT8 col, INT32 x, INT32 y, boolean highlight)
|
static void M_DrawLevelPlatterWideMap(UINT8 row, UINT8 col, INT32 x, INT32 y, boolean highlight)
|
||||||
|
@ -4279,7 +4329,7 @@ static void M_DrawLevelPlatterRow(UINT8 row, INT32 y)
|
||||||
const boolean rowhighlight = (row == lsrow);
|
const boolean rowhighlight = (row == lsrow);
|
||||||
if (levelselect.rows[row].header[0])
|
if (levelselect.rows[row].header[0])
|
||||||
{
|
{
|
||||||
M_DrawLevelPlatterHeader(y, levelselect.rows[row].header, (rowhighlight || (row == lshli)));
|
M_DrawLevelPlatterHeader(y, levelselect.rows[row].header, (rowhighlight || (row == lshli)), false);
|
||||||
y += lsheadingheight;
|
y += lsheadingheight;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4298,9 +4348,6 @@ static void M_DrawLevelPlatterMenu(void)
|
||||||
INT32 y = lsbasey + lsoffs[0] - getheadingoffset(lsrow);
|
INT32 y = lsbasey + lsoffs[0] - getheadingoffset(lsrow);
|
||||||
const INT32 cursorx = (sizeselect ? 0 : (lscol*lshseperation));
|
const INT32 cursorx = (sizeselect ? 0 : (lscol*lshseperation));
|
||||||
|
|
||||||
if (++lstic == 32)
|
|
||||||
lstic = 0;
|
|
||||||
|
|
||||||
if (gamestate == GS_TIMEATTACK)
|
if (gamestate == GS_TIMEATTACK)
|
||||||
V_DrawPatchFill(W_CachePatchName("SRB2BACK", PU_CACHE));
|
V_DrawPatchFill(W_CachePatchName("SRB2BACK", PU_CACHE));
|
||||||
|
|
||||||
|
@ -4320,7 +4367,7 @@ static void M_DrawLevelPlatterMenu(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
// draw cursor box
|
// draw cursor box
|
||||||
V_DrawSmallScaledPatch(lsbasex + cursorx + lsoffs[1], lsbasey, 0, ((lstic & 8) ? levselp[sizeselect][0] : levselp[sizeselect][1]));
|
V_DrawSmallScaledPatch(lsbasex + cursorx + lsoffs[1], lsbasey, 0, (levselp[sizeselect][((skullAnimCounter/4) ? 1 : 0)]));
|
||||||
|
|
||||||
if (levelselect.rows[lsrow].maplist[lscol])
|
if (levelselect.rows[lsrow].maplist[lscol])
|
||||||
V_DrawScaledPatch(lsbasex + cursorx-17, lsbasey+50+lsoffs[0], 0, W_CachePatchName("M_CURSOR", PU_CACHE));
|
V_DrawScaledPatch(lsbasex + cursorx-17, lsbasey+50+lsoffs[0], 0, W_CachePatchName("M_CURSOR", PU_CACHE));
|
||||||
|
@ -4620,6 +4667,511 @@ static void M_HandleImageDef(INT32 choice)
|
||||||
// MISC MAIN MENU OPTIONS
|
// MISC MAIN MENU OPTIONS
|
||||||
// ======================
|
// ======================
|
||||||
|
|
||||||
|
static void M_AddonsOptions(INT32 choice)
|
||||||
|
{
|
||||||
|
(void)choice;
|
||||||
|
Addons_option_Onchange();
|
||||||
|
|
||||||
|
M_SetupNextMenu(&OP_AddonsOptionsDef);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define LOCATIONSTRING "Visit \x83SRB2.ORG/MODS\x80 to get & make add-ons!"
|
||||||
|
|
||||||
|
static void M_Addons(INT32 choice)
|
||||||
|
{
|
||||||
|
const char *pathname = ".";
|
||||||
|
|
||||||
|
(void)choice;
|
||||||
|
|
||||||
|
/*if (cv_addons_option.value == 0)
|
||||||
|
pathname = srb2home; usehome ? srb2home : srb2path;
|
||||||
|
else if (cv_addons_option.value == 1)
|
||||||
|
pathname = srb2home;
|
||||||
|
else if (cv_addons_option.value == 2)
|
||||||
|
pathname = srb2path;
|
||||||
|
else*/
|
||||||
|
if (cv_addons_option.value == 3 && *cv_addons_folder.string != '\0')
|
||||||
|
pathname = cv_addons_folder.string;
|
||||||
|
|
||||||
|
strlcpy(menupath, pathname, 1024);
|
||||||
|
menupathindex[(menudepthleft = menudepth-1)] = strlen(menupath) + 1;
|
||||||
|
|
||||||
|
if (menupath[menupathindex[menudepthleft]-2] != '/')
|
||||||
|
{
|
||||||
|
menupath[menupathindex[menudepthleft]-1] = '/';
|
||||||
|
menupath[menupathindex[menudepthleft]] = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
--menupathindex[menudepthleft];
|
||||||
|
|
||||||
|
if (!preparefilemenu(false))
|
||||||
|
{
|
||||||
|
M_StartMessage(M_GetText("No files/folders found.\n\n"LOCATIONSTRING"\n\n(Press a key)\n"),NULL,MM_NOTHING);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
dir_on[menudepthleft] = 0;
|
||||||
|
|
||||||
|
if (addonsp[0]) // never going to have some provided but not all, saves individually checking
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
for (i = 0; i < NUM_EXT+6; i++)
|
||||||
|
W_UnlockCachedPatch(addonsp[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
addonsp[EXT_FOLDER] = W_CachePatchName("M_FFLDR", PU_STATIC);
|
||||||
|
addonsp[EXT_UP] = W_CachePatchName("M_FBACK", PU_STATIC);
|
||||||
|
addonsp[EXT_NORESULTS] = W_CachePatchName("M_FNOPE", PU_STATIC);
|
||||||
|
addonsp[EXT_TXT] = W_CachePatchName("M_FTXT", PU_STATIC);
|
||||||
|
addonsp[EXT_CFG] = W_CachePatchName("M_FCFG", PU_STATIC);
|
||||||
|
addonsp[EXT_WAD] = W_CachePatchName("M_FWAD", PU_STATIC);
|
||||||
|
addonsp[EXT_SOC] = W_CachePatchName("M_FSOC", PU_STATIC);
|
||||||
|
addonsp[EXT_LUA] = W_CachePatchName("M_FLUA", PU_STATIC);
|
||||||
|
addonsp[NUM_EXT] = W_CachePatchName("M_FUNKN", PU_STATIC);
|
||||||
|
addonsp[NUM_EXT+1] = W_CachePatchName("M_FSEL1", PU_STATIC);
|
||||||
|
addonsp[NUM_EXT+2] = W_CachePatchName("M_FSEL2", PU_STATIC);
|
||||||
|
addonsp[NUM_EXT+3] = W_CachePatchName("M_FLOAD", PU_STATIC);
|
||||||
|
addonsp[NUM_EXT+4] = W_CachePatchName("M_FSRCH", PU_STATIC);
|
||||||
|
addonsp[NUM_EXT+5] = W_CachePatchName("M_FSAVE", PU_STATIC);
|
||||||
|
|
||||||
|
MISC_AddonsDef.prevMenu = currentMenu;
|
||||||
|
M_SetupNextMenu(&MISC_AddonsDef);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define width 4
|
||||||
|
#define vpadding 27
|
||||||
|
#define h (BASEVIDHEIGHT-(2*vpadding))
|
||||||
|
#define NUMCOLOURS 8 // when toast's coding it's british english hacker fucker
|
||||||
|
static void M_DrawTemperature(INT32 x, fixed_t t)
|
||||||
|
{
|
||||||
|
INT32 y;
|
||||||
|
|
||||||
|
// bounds check
|
||||||
|
if (t > FRACUNIT)
|
||||||
|
t = FRACUNIT;
|
||||||
|
/*else if (t < 0) -- not needed
|
||||||
|
t = 0;*/
|
||||||
|
|
||||||
|
// scale
|
||||||
|
if (t > 1)
|
||||||
|
t = (FixedMul(h<<FRACBITS, t)>>FRACBITS);
|
||||||
|
|
||||||
|
// border
|
||||||
|
V_DrawFill(x - 1, vpadding, 1, h, 3);
|
||||||
|
V_DrawFill(x + width, vpadding, 1, h, 3);
|
||||||
|
V_DrawFill(x - 1, vpadding-1, width+2, 1, 3);
|
||||||
|
V_DrawFill(x - 1, vpadding+h, width+2, 1, 3);
|
||||||
|
|
||||||
|
// bar itself
|
||||||
|
y = h;
|
||||||
|
if (t)
|
||||||
|
for (t = h - t; y > 0; y--)
|
||||||
|
{
|
||||||
|
UINT8 colours[NUMCOLOURS] = {42, 40, 58, 222, 65, 90, 97, 98};
|
||||||
|
UINT8 c;
|
||||||
|
if (y <= t) break;
|
||||||
|
if (y+vpadding >= BASEVIDHEIGHT/2)
|
||||||
|
c = 113;
|
||||||
|
else
|
||||||
|
c = colours[(NUMCOLOURS*(y-1))/(h/2)];
|
||||||
|
V_DrawFill(x, y-1 + vpadding, width, 1, c);
|
||||||
|
}
|
||||||
|
|
||||||
|
// fill the rest of the backing
|
||||||
|
if (y)
|
||||||
|
V_DrawFill(x, vpadding, width, y, 27);
|
||||||
|
}
|
||||||
|
#undef width
|
||||||
|
#undef vpadding
|
||||||
|
#undef h
|
||||||
|
#undef NUMCOLOURS
|
||||||
|
|
||||||
|
static char *M_AddonsHeaderPath(void)
|
||||||
|
{
|
||||||
|
UINT32 len;
|
||||||
|
static char header[1024];
|
||||||
|
|
||||||
|
if (menupath[0] == '.')
|
||||||
|
strlcpy(header, va("SRB2 folder%s", menupath+1), 1024);
|
||||||
|
else
|
||||||
|
strcpy(header, menupath);
|
||||||
|
|
||||||
|
len = strlen(header);
|
||||||
|
if (len > 34)
|
||||||
|
{
|
||||||
|
len = len-34;
|
||||||
|
header[len] = header[len+1] = header[len+2] = '.';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
len = 0;
|
||||||
|
|
||||||
|
return header+len;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define UNEXIST S_StartSound(NULL, sfx_lose);\
|
||||||
|
M_SetupNextMenu(MISC_AddonsDef.prevMenu);\
|
||||||
|
M_StartMessage(va("\x82%s\x80\nThis folder no longer exists!\nAborting to main menu.\n\n(Press a key)\n", M_AddonsHeaderPath()),NULL,MM_NOTHING)
|
||||||
|
|
||||||
|
// returns whether to do message draw
|
||||||
|
static boolean M_AddonsRefresh(void)
|
||||||
|
{
|
||||||
|
if ((refreshdirmenu & REFRESHDIR_NORMAL) && !preparefilemenu(true))
|
||||||
|
{
|
||||||
|
UNEXIST;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (refreshdirmenu & REFRESHDIR_ADDFILE)
|
||||||
|
{
|
||||||
|
addonsresponselimit = 0;
|
||||||
|
|
||||||
|
if (refreshdirmenu & REFRESHDIR_NOTLOADED)
|
||||||
|
{
|
||||||
|
char *message = NULL;
|
||||||
|
S_StartSound(NULL, sfx_lose);
|
||||||
|
if (refreshdirmenu & REFRESHDIR_MAX)
|
||||||
|
message = va("\x82%s\x80\nMaximum number of add-ons reached.\nThis file could not be loaded.\nIf you want to play with this add-on, restart the game to clear existing ones.\n\n(Press a key)\n", dirmenu[dir_on[menudepthleft]]+DIR_STRING);
|
||||||
|
else
|
||||||
|
message = va("\x82%s\x80\nThe file was not loaded.\nCheck the console log for more information.\n\n(Press a key)\n", dirmenu[dir_on[menudepthleft]]+DIR_STRING);
|
||||||
|
M_StartMessage(message,NULL,MM_NOTHING);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (refreshdirmenu & (REFRESHDIR_WARNING|REFRESHDIR_ERROR))
|
||||||
|
{
|
||||||
|
S_StartSound(NULL, sfx_skid);
|
||||||
|
M_StartMessage(va("\x82%s\x80\nThe file was loaded with %s.\nCheck the console log for more information.\n\n(Press a key)\n", dirmenu[dir_on[menudepthleft]]+DIR_STRING, ((refreshdirmenu & REFRESHDIR_ERROR) ? "errors" : "warnings")),NULL,MM_NOTHING);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
S_StartSound(NULL, sfx_strpst);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define offs 1
|
||||||
|
|
||||||
|
static void M_DrawAddons(void)
|
||||||
|
{
|
||||||
|
INT32 x, y;
|
||||||
|
ssize_t i, max;
|
||||||
|
|
||||||
|
// hack - need to refresh at end of frame to handle addfile...
|
||||||
|
if (refreshdirmenu & M_AddonsRefresh())
|
||||||
|
return M_DrawMessageMenu();
|
||||||
|
|
||||||
|
if (addonsresponselimit)
|
||||||
|
addonsresponselimit--;
|
||||||
|
|
||||||
|
V_DrawCenteredString(BASEVIDWIDTH/2, 4+offs, 0, (Playing()
|
||||||
|
? "\x85""Adding files mid-game may cause problems."
|
||||||
|
: LOCATIONSTRING));
|
||||||
|
|
||||||
|
if (numwadfiles <= mainwads+1)
|
||||||
|
y = 0;
|
||||||
|
else if (numwadfiles >= MAX_WADFILES)
|
||||||
|
y = FRACUNIT;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x = FixedDiv((numwadfiles - mainwads+1)<<FRACBITS, (MAX_WADFILES - mainwads+1)<<FRACBITS);
|
||||||
|
y = FixedDiv(((packetsizetally-mainwadstally)<<FRACBITS), (((MAXFILENEEDED*sizeof(UINT8)-mainwadstally)-(5+22))<<FRACBITS)); // 5+22 = (a.ext + checksum length) is minimum addition to packet size tally
|
||||||
|
if (x > y)
|
||||||
|
y = x;
|
||||||
|
if (y > FRACUNIT) // happens because of how we're shrinkin' it a little
|
||||||
|
y = FRACUNIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
M_DrawTemperature(BASEVIDWIDTH - 19 - 5, y);
|
||||||
|
|
||||||
|
// DRAW MENU
|
||||||
|
x = currentMenu->x;
|
||||||
|
y = currentMenu->y + offs;
|
||||||
|
|
||||||
|
//M_DrawLevelPlatterHeader(y - 16, M_AddonsHeaderPath(), true, true); -- wanted different width
|
||||||
|
V_DrawString(x-21, (y - 16) + (lsheadingheight - 12), V_YELLOWMAP|V_ALLOWLOWERCASE, M_AddonsHeaderPath());
|
||||||
|
V_DrawFill(x-21, (y - 16) + (lsheadingheight - 3), (MAXSTRINGLENGTH*8+6 - 1), 1, yellowmap[3]);
|
||||||
|
V_DrawFill(x-21 + (MAXSTRINGLENGTH*8+6 - 1), (y - 16) + (lsheadingheight - 3), 1, 1, 26);
|
||||||
|
V_DrawFill(x-21, (y - 16) + (lsheadingheight - 2), MAXSTRINGLENGTH*8+6, 1, 26);
|
||||||
|
|
||||||
|
V_DrawFill(x - 21, y - 1, MAXSTRINGLENGTH*8+6, (BASEVIDHEIGHT - currentMenu->y + 1 + offs) - (y - 1), 159);
|
||||||
|
|
||||||
|
// get bottom...
|
||||||
|
max = dir_on[menudepthleft] + numaddonsshown + 1;
|
||||||
|
if (max > (ssize_t)sizedirmenu)
|
||||||
|
max = sizedirmenu;
|
||||||
|
|
||||||
|
// then top...
|
||||||
|
i = max - (2*numaddonsshown + 1);
|
||||||
|
|
||||||
|
// then adjust!
|
||||||
|
if (i < 0)
|
||||||
|
{
|
||||||
|
if ((max -= i) > (ssize_t)sizedirmenu)
|
||||||
|
max = sizedirmenu;
|
||||||
|
i = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i != 0)
|
||||||
|
V_DrawString(19, y+4, V_YELLOWMAP, "\x1A");
|
||||||
|
|
||||||
|
for (; i < max; i++)
|
||||||
|
{
|
||||||
|
UINT32 flags = V_ALLOWLOWERCASE;
|
||||||
|
if (y > BASEVIDHEIGHT) break;
|
||||||
|
if (dirmenu[i])
|
||||||
|
#define type (UINT8)(dirmenu[i][DIR_TYPE])
|
||||||
|
{
|
||||||
|
if (type & EXT_LOADED)
|
||||||
|
flags |= V_TRANSLUCENT;
|
||||||
|
|
||||||
|
V_DrawSmallScaledPatch(x-(16+4), y, (flags & V_TRANSLUCENT), addonsp[((UINT8)(dirmenu[i][DIR_TYPE]) & ~EXT_LOADED)]);
|
||||||
|
|
||||||
|
if (type & EXT_LOADED)
|
||||||
|
V_DrawSmallScaledPatch(x-(16+4), y, 0, addonsp[NUM_EXT+3]);
|
||||||
|
|
||||||
|
if ((size_t)i == dir_on[menudepthleft])
|
||||||
|
{
|
||||||
|
V_DrawSmallScaledPatch(x-(16+4), y, 0, addonsp[NUM_EXT+1+((skullAnimCounter/4) ? 1 : 0)]);
|
||||||
|
flags = V_ALLOWLOWERCASE|V_YELLOWMAP;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define charsonside 14
|
||||||
|
if (dirmenu[i][DIR_LEN] > (charsonside*2 + 3))
|
||||||
|
V_DrawString(x, y+4, flags, va("%.*s...%s", charsonside, dirmenu[i]+DIR_STRING, dirmenu[i]+DIR_STRING+dirmenu[i][DIR_LEN]-(charsonside+1)));
|
||||||
|
#undef charsonside
|
||||||
|
else
|
||||||
|
V_DrawString(x, y+4, flags, dirmenu[i]+DIR_STRING);
|
||||||
|
}
|
||||||
|
#undef type
|
||||||
|
y += 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (max != (ssize_t)sizedirmenu)
|
||||||
|
V_DrawString(19, y-12, V_YELLOWMAP, "\x1B");
|
||||||
|
|
||||||
|
y = BASEVIDHEIGHT - currentMenu->y + offs;
|
||||||
|
|
||||||
|
M_DrawTextBox(x - (21 + 5), y, MAXSTRINGLENGTH, 1);
|
||||||
|
if (menusearch[0])
|
||||||
|
V_DrawString(x - 18, y + 8, V_ALLOWLOWERCASE, menusearch+1);
|
||||||
|
else
|
||||||
|
V_DrawString(x - 18, y + 8, V_ALLOWLOWERCASE|V_TRANSLUCENT, "Type to search...");
|
||||||
|
if (skullAnimCounter < 4)
|
||||||
|
V_DrawCharacter(x - 18 + V_StringWidth(menusearch+1, 0), y + 8,
|
||||||
|
'_' | 0x80, false);
|
||||||
|
|
||||||
|
x -= (21 + 5 + 16);
|
||||||
|
V_DrawSmallScaledPatch(x, y + 4, (menusearch[0] ? 0 : V_TRANSLUCENT), addonsp[NUM_EXT+4]);
|
||||||
|
|
||||||
|
#define CANSAVE (!modifiedgame || savemoddata)
|
||||||
|
x = BASEVIDWIDTH - x - 16;
|
||||||
|
V_DrawSmallScaledPatch(x, y + 4, (CANSAVE ? 0 : V_TRANSLUCENT), addonsp[NUM_EXT+5]);
|
||||||
|
|
||||||
|
if CANSAVE
|
||||||
|
V_DrawSmallScaledPatch(x, y + 4, 0, addonsp[NUM_EXT+3]);
|
||||||
|
#undef CANSAVE
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef offs
|
||||||
|
|
||||||
|
static void M_AddonExec(INT32 ch)
|
||||||
|
{
|
||||||
|
if (ch != 'y' && ch != KEY_ENTER)
|
||||||
|
return;
|
||||||
|
|
||||||
|
S_StartSound(NULL, sfx_strpst);
|
||||||
|
COM_BufAddText(va("exec %s%s", menupath, dirmenu[dir_on[menudepthleft]]+DIR_STRING));
|
||||||
|
}
|
||||||
|
|
||||||
|
#define len menusearch[0]
|
||||||
|
static boolean M_ChangeStringAddons(INT32 choice)
|
||||||
|
{
|
||||||
|
if (shiftdown && choice >= 32 && choice <= 127)
|
||||||
|
choice = shiftxform[choice];
|
||||||
|
|
||||||
|
switch (choice)
|
||||||
|
{
|
||||||
|
case KEY_DEL:
|
||||||
|
if (len)
|
||||||
|
{
|
||||||
|
len = menusearch[1] = 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case KEY_BACKSPACE:
|
||||||
|
if (len)
|
||||||
|
{
|
||||||
|
menusearch[1+--len] = 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (choice >= 32 && choice <= 127)
|
||||||
|
{
|
||||||
|
if (len < MAXSTRINGLENGTH - 1)
|
||||||
|
{
|
||||||
|
menusearch[1+len++] = (char)choice;
|
||||||
|
menusearch[1+len] = 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#undef len
|
||||||
|
|
||||||
|
static void M_HandleAddons(INT32 choice)
|
||||||
|
{
|
||||||
|
boolean exitmenu = false; // exit to previous menu
|
||||||
|
|
||||||
|
if (addonsresponselimit)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (M_ChangeStringAddons(choice))
|
||||||
|
{
|
||||||
|
if (!preparefilemenu(true))
|
||||||
|
{
|
||||||
|
UNEXIST;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (choice)
|
||||||
|
{
|
||||||
|
case KEY_DOWNARROW:
|
||||||
|
if (dir_on[menudepthleft] < sizedirmenu-1)
|
||||||
|
dir_on[menudepthleft]++;
|
||||||
|
S_StartSound(NULL, sfx_menu1);
|
||||||
|
break;
|
||||||
|
case KEY_UPARROW:
|
||||||
|
if (dir_on[menudepthleft])
|
||||||
|
dir_on[menudepthleft]--;
|
||||||
|
S_StartSound(NULL, sfx_menu1);
|
||||||
|
break;
|
||||||
|
case KEY_PGDN:
|
||||||
|
{
|
||||||
|
UINT8 i;
|
||||||
|
for (i = numaddonsshown; i && (dir_on[menudepthleft] < sizedirmenu-1); i--)
|
||||||
|
dir_on[menudepthleft]++;
|
||||||
|
}
|
||||||
|
S_StartSound(NULL, sfx_menu1);
|
||||||
|
break;
|
||||||
|
case KEY_PGUP:
|
||||||
|
{
|
||||||
|
UINT8 i;
|
||||||
|
for (i = numaddonsshown; i && (dir_on[menudepthleft]); i--)
|
||||||
|
dir_on[menudepthleft]--;
|
||||||
|
}
|
||||||
|
S_StartSound(NULL, sfx_menu1);
|
||||||
|
break;
|
||||||
|
case KEY_ENTER:
|
||||||
|
{
|
||||||
|
boolean refresh = true;
|
||||||
|
if (!dirmenu[dir_on[menudepthleft]])
|
||||||
|
S_StartSound(NULL, sfx_lose);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch (dirmenu[dir_on[menudepthleft]][DIR_TYPE])
|
||||||
|
{
|
||||||
|
case EXT_FOLDER:
|
||||||
|
strcpy(&menupath[menupathindex[menudepthleft]],dirmenu[dir_on[menudepthleft]]+DIR_STRING);
|
||||||
|
if (menudepthleft)
|
||||||
|
{
|
||||||
|
menupathindex[--menudepthleft] = strlen(menupath);
|
||||||
|
menupath[menupathindex[menudepthleft]] = 0;
|
||||||
|
|
||||||
|
if (!preparefilemenu(false))
|
||||||
|
{
|
||||||
|
S_StartSound(NULL, sfx_skid);
|
||||||
|
M_StartMessage(va("\x82%s\x80\nThis folder is empty.\n\n(Press a key)\n", M_AddonsHeaderPath()),NULL,MM_NOTHING);
|
||||||
|
menupath[menupathindex[++menudepthleft]] = 0;
|
||||||
|
|
||||||
|
if (!preparefilemenu(true))
|
||||||
|
{
|
||||||
|
UNEXIST;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
S_StartSound(NULL, sfx_menu1);
|
||||||
|
dir_on[menudepthleft] = 1;
|
||||||
|
}
|
||||||
|
refresh = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
S_StartSound(NULL, sfx_lose);
|
||||||
|
M_StartMessage(va("\x82%s\x80\nThis folder is too deep to navigate to!\n\n(Press a key)\n", M_AddonsHeaderPath()),NULL,MM_NOTHING);
|
||||||
|
menupath[menupathindex[menudepthleft]] = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case EXT_UP:
|
||||||
|
S_StartSound(NULL, sfx_menu1);
|
||||||
|
menupath[menupathindex[++menudepthleft]] = 0;
|
||||||
|
if (!preparefilemenu(false))
|
||||||
|
{
|
||||||
|
UNEXIST;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case EXT_TXT:
|
||||||
|
M_StartMessage(va("\x82%s\x80\nThis file may not be a console script.\nAttempt to run anyways? \n\n(Press 'Y' to confirm)\n", dirmenu[dir_on[menudepthleft]]+DIR_STRING),M_AddonExec,MM_YESNO);
|
||||||
|
break;
|
||||||
|
case EXT_CFG:
|
||||||
|
M_AddonExec(KEY_ENTER);
|
||||||
|
break;
|
||||||
|
case EXT_LUA:
|
||||||
|
#ifndef HAVE_BLUA
|
||||||
|
S_StartSound(NULL, sfx_lose);
|
||||||
|
M_StartMessage(va("\x82%s\x80\nThis copy of SRB2 was compiled\nwithout support for .lua files.\n\n(Press a key)\n", dirmenu[dir_on[menudepthleft]]+DIR_STRING),NULL,MM_NOTHING);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
// else intentional fallthrough
|
||||||
|
case EXT_SOC:
|
||||||
|
case EXT_WAD:
|
||||||
|
COM_BufAddText(va("addfile %s%s", menupath, dirmenu[dir_on[menudepthleft]]+DIR_STRING));
|
||||||
|
addonsresponselimit = 5;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
S_StartSound(NULL, sfx_lose);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (refresh)
|
||||||
|
refreshdirmenu |= REFRESHDIR_NORMAL;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case KEY_ESCAPE:
|
||||||
|
exitmenu = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (exitmenu)
|
||||||
|
{
|
||||||
|
for (; sizedirmenu > 0; sizedirmenu--)
|
||||||
|
{
|
||||||
|
Z_Free(dirmenu[sizedirmenu-1]);
|
||||||
|
dirmenu[sizedirmenu-1] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Z_Free(dirmenu);
|
||||||
|
dirmenu = NULL;
|
||||||
|
|
||||||
|
// secrets disabled by addfile...
|
||||||
|
MainMenu[secrets].status = (M_AnySecretUnlocked()) ? (IT_STRING | IT_CALL) : (IT_DISABLED);
|
||||||
|
|
||||||
|
if (currentMenu->prevMenu)
|
||||||
|
M_SetupNextMenu(currentMenu->prevMenu);
|
||||||
|
else
|
||||||
|
M_ClearMenus(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void M_PandorasBox(INT32 choice)
|
static void M_PandorasBox(INT32 choice)
|
||||||
{
|
{
|
||||||
(void)choice;
|
(void)choice;
|
||||||
|
@ -4722,7 +5274,7 @@ static void M_Options(INT32 choice)
|
||||||
OP_MainMenu[5].status = (Playing() && !(server || adminplayer == consoleplayer)) ? (IT_GRAYEDOUT) : (IT_STRING|IT_CALL);
|
OP_MainMenu[5].status = (Playing() && !(server || adminplayer == consoleplayer)) ? (IT_GRAYEDOUT) : (IT_STRING|IT_CALL);
|
||||||
|
|
||||||
// if the player is playing _at all_, disable the erase data options
|
// if the player is playing _at all_, disable the erase data options
|
||||||
OP_DataOptionsMenu[1].status = (Playing()) ? (IT_GRAYEDOUT) : (IT_STRING|IT_SUBMENU);
|
OP_DataOptionsMenu[2].status = (Playing()) ? (IT_GRAYEDOUT) : (IT_STRING|IT_SUBMENU);
|
||||||
|
|
||||||
OP_MainDef.prevMenu = currentMenu;
|
OP_MainDef.prevMenu = currentMenu;
|
||||||
M_SetupNextMenu(&OP_MainDef);
|
M_SetupNextMenu(&OP_MainDef);
|
||||||
|
@ -5136,9 +5688,7 @@ static void M_DrawChecklist(void)
|
||||||
|
|
||||||
finishchecklist:
|
finishchecklist:
|
||||||
if ((checklist_cangodown = ((y - currentMenu->y) > (scrollareaheight*2)))) // haaaaaaacks.
|
if ((checklist_cangodown = ((y - currentMenu->y) > (scrollareaheight*2)))) // haaaaaaacks.
|
||||||
{
|
|
||||||
V_DrawString(10, currentMenu->y+(scrollareaheight*2), V_YELLOWMAP, "\x1B");
|
V_DrawString(10, currentMenu->y+(scrollareaheight*2), V_YELLOWMAP, "\x1B");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define NUMHINTS 5
|
#define NUMHINTS 5
|
||||||
|
@ -6441,7 +6991,7 @@ void M_DrawTimeAttackMenu(void)
|
||||||
lumpnum_t lumpnum;
|
lumpnum_t lumpnum;
|
||||||
char beststr[40];
|
char beststr[40];
|
||||||
|
|
||||||
M_DrawLevelPlatterHeader(32-lsheadingheight/2, cv_nextmap.string, true);
|
M_DrawLevelPlatterHeader(32-lsheadingheight/2, cv_nextmap.string, true, false);
|
||||||
|
|
||||||
// A 160x100 image of the level as entry MAPxxP
|
// A 160x100 image of the level as entry MAPxxP
|
||||||
lumpnum = W_CheckNumForName(va("%sP", G_BuildMapName(cv_nextmap.value)));
|
lumpnum = W_CheckNumForName(va("%sP", G_BuildMapName(cv_nextmap.value)));
|
||||||
|
@ -6618,7 +7168,7 @@ void M_DrawNightsAttackMenu(void)
|
||||||
UINT32 bestscore = G_GetBestNightsScore(cv_nextmap.value, cv_dummymares.value);
|
UINT32 bestscore = G_GetBestNightsScore(cv_nextmap.value, cv_dummymares.value);
|
||||||
tic_t besttime = G_GetBestNightsTime(cv_nextmap.value, cv_dummymares.value);
|
tic_t besttime = G_GetBestNightsTime(cv_nextmap.value, cv_dummymares.value);
|
||||||
|
|
||||||
M_DrawLevelPlatterHeader(32-lsheadingheight/2, cv_nextmap.string, true);
|
M_DrawLevelPlatterHeader(32-lsheadingheight/2, cv_nextmap.string, true, false);
|
||||||
|
|
||||||
// A 160x100 image of the level as entry MAPxxP
|
// A 160x100 image of the level as entry MAPxxP
|
||||||
lumpnum = W_CheckNumForName(va("%sP", G_BuildMapName(cv_nextmap.value)));
|
lumpnum = W_CheckNumForName(va("%sP", G_BuildMapName(cv_nextmap.value)));
|
||||||
|
@ -7374,7 +7924,7 @@ static void M_DrawServerMenu(void)
|
||||||
// Room name
|
// Room name
|
||||||
if (currentMenu == &MP_ServerDef)
|
if (currentMenu == &MP_ServerDef)
|
||||||
{
|
{
|
||||||
M_DrawLevelPlatterHeader(currentMenu->y - lsheadingheight/2, "Server settings", true);
|
M_DrawLevelPlatterHeader(currentMenu->y - lsheadingheight/2, "Server settings", true, false);
|
||||||
if (ms_RoomId < 0)
|
if (ms_RoomId < 0)
|
||||||
V_DrawRightAlignedString(BASEVIDWIDTH - currentMenu->x, currentMenu->y + MP_ServerMenu[mp_server_room].alphaKey,
|
V_DrawRightAlignedString(BASEVIDWIDTH - currentMenu->x, currentMenu->y + MP_ServerMenu[mp_server_room].alphaKey,
|
||||||
V_YELLOWMAP, (itemOn == mp_server_room) ? "<Select to change>" : "<Offline Mode>");
|
V_YELLOWMAP, (itemOn == mp_server_room) ? "<Select to change>" : "<Offline Mode>");
|
||||||
|
@ -7392,7 +7942,7 @@ static void M_DrawServerMenu(void)
|
||||||
|
|
||||||
sprintf(headerstr, "%s - %s", cv_newgametype.string, cv_nextmap.string);
|
sprintf(headerstr, "%s - %s", cv_newgametype.string, cv_nextmap.string);
|
||||||
|
|
||||||
M_DrawLevelPlatterHeader(currentMenu->y + MP_ServerMenu[mp_server_levelgt].alphaKey - 10 - lsheadingheight/2, (const char *)headerstr, true);
|
M_DrawLevelPlatterHeader(currentMenu->y + MP_ServerMenu[mp_server_levelgt].alphaKey - 10 - lsheadingheight/2, (const char *)headerstr, true, false);
|
||||||
|
|
||||||
// A 160x100 image of the level as entry MAPxxP
|
// A 160x100 image of the level as entry MAPxxP
|
||||||
lumpnum = W_CheckNumForName(va("%sP", G_BuildMapName(cv_nextmap.value)));
|
lumpnum = W_CheckNumForName(va("%sP", G_BuildMapName(cv_nextmap.value)));
|
||||||
|
@ -7422,7 +7972,7 @@ static void M_GameTypeChange(INT32 choice)
|
||||||
void M_DrawGameTypeMenu(void)
|
void M_DrawGameTypeMenu(void)
|
||||||
{
|
{
|
||||||
M_DrawGenericMenu();
|
M_DrawGenericMenu();
|
||||||
M_DrawLevelPlatterHeader(currentMenu->y - lsheadingheight, "Select Gametype", true);
|
M_DrawLevelPlatterHeader(currentMenu->y - lsheadingheight, "Select Gametype", true, false);
|
||||||
|
|
||||||
if (!char_notes)
|
if (!char_notes)
|
||||||
char_notes = V_WordWrap(0, (160 - 30) - 8, V_ALLOWLOWERCASE, gametypedesc[itemOn].notes);
|
char_notes = V_WordWrap(0, (160 - 30) - 8, V_ALLOWLOWERCASE, gametypedesc[itemOn].notes);
|
||||||
|
@ -8174,7 +8724,7 @@ static void M_DrawControl(void)
|
||||||
/*else if (currentMenu->menuitems[i].status == IT_GRAYEDOUT2)
|
/*else if (currentMenu->menuitems[i].status == IT_GRAYEDOUT2)
|
||||||
V_DrawString(x, y, V_TRANSLUCENT, currentMenu->menuitems[i].text);*/
|
V_DrawString(x, y, V_TRANSLUCENT, currentMenu->menuitems[i].text);*/
|
||||||
else if ((currentMenu->menuitems[i].status == IT_HEADER) && (i != max-1))
|
else if ((currentMenu->menuitems[i].status == IT_HEADER) && (i != max-1))
|
||||||
M_DrawLevelPlatterHeader(y, currentMenu->menuitems[i].text, true);
|
M_DrawLevelPlatterHeader(y, currentMenu->menuitems[i].text, true, false);
|
||||||
|
|
||||||
y += SMALLLINEHEIGHT;
|
y += SMALLLINEHEIGHT;
|
||||||
}
|
}
|
||||||
|
@ -8749,7 +9299,7 @@ static void M_DrawColorMenu(void)
|
||||||
//V_DrawString(x-16, y, V_YELLOWMAP, currentMenu->menuitems[i].text);
|
//V_DrawString(x-16, y, V_YELLOWMAP, currentMenu->menuitems[i].text);
|
||||||
V_DrawFill(19, y, 281, 9, currentMenu->menuitems[i+1].alphaKey);
|
V_DrawFill(19, y, 281, 9, currentMenu->menuitems[i+1].alphaKey);
|
||||||
V_DrawFill(300, y, 1, 9, 26);
|
V_DrawFill(300, y, 1, 9, 26);
|
||||||
M_DrawLevelPlatterHeader(y - (lsheadingheight - 12), currentMenu->menuitems[i].text, false);
|
M_DrawLevelPlatterHeader(y - (lsheadingheight - 12), currentMenu->menuitems[i].text, false, false);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
17
src/m_menu.h
17
src/m_menu.h
|
@ -124,6 +124,8 @@ boolean M_CanShowLevelInList(INT32 mapnum, INT32 gt);
|
||||||
#define IT_HEADER (IT_SPACE +IT_HEADERTEXT)
|
#define IT_HEADER (IT_SPACE +IT_HEADERTEXT)
|
||||||
#define IT_SECRET (IT_SPACE +IT_QUESTIONMARKS)
|
#define IT_SECRET (IT_SPACE +IT_QUESTIONMARKS)
|
||||||
|
|
||||||
|
#define MAXSTRINGLENGTH 32
|
||||||
|
|
||||||
typedef union
|
typedef union
|
||||||
{
|
{
|
||||||
struct menu_s *submenu; // IT_SUBMENU
|
struct menu_s *submenu; // IT_SUBMENU
|
||||||
|
@ -249,6 +251,9 @@ void Nextmap_OnChange(void);
|
||||||
void Moviemode_mode_Onchange(void);
|
void Moviemode_mode_Onchange(void);
|
||||||
void Screenshot_option_Onchange(void);
|
void Screenshot_option_Onchange(void);
|
||||||
|
|
||||||
|
// Addons menu updating
|
||||||
|
void Addons_option_Onchange(void);
|
||||||
|
|
||||||
// These defines make it a little easier to make menus
|
// These defines make it a little easier to make menus
|
||||||
#define DEFAULTMENUSTYLE(header, source, prev, x, y)\
|
#define DEFAULTMENUSTYLE(header, source, prev, x, y)\
|
||||||
{\
|
{\
|
||||||
|
@ -262,6 +267,18 @@ void Screenshot_option_Onchange(void);
|
||||||
NULL\
|
NULL\
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define DEFAULTSCROLLMENUSTYLE(header, source, prev, x, y)\
|
||||||
|
{\
|
||||||
|
header,\
|
||||||
|
sizeof(source)/sizeof(menuitem_t),\
|
||||||
|
prev,\
|
||||||
|
source,\
|
||||||
|
M_DrawGenericScrollMenu,\
|
||||||
|
x, y,\
|
||||||
|
0,\
|
||||||
|
NULL\
|
||||||
|
}
|
||||||
|
|
||||||
#define PAUSEMENUSTYLE(source, x, y)\
|
#define PAUSEMENUSTYLE(source, x, y)\
|
||||||
{\
|
{\
|
||||||
NULL,\
|
NULL,\
|
||||||
|
|
|
@ -100,7 +100,7 @@ static CV_PossibleValue_t screenshot_cons_t[] = {{0, "Default"}, {1, "HOME"}, {2
|
||||||
consvar_t cv_screenshot_option = {"screenshot_option", "Default", CV_SAVE|CV_CALL, screenshot_cons_t, Screenshot_option_Onchange, 0, NULL, NULL, 0, 0, NULL};
|
consvar_t cv_screenshot_option = {"screenshot_option", "Default", CV_SAVE|CV_CALL, screenshot_cons_t, Screenshot_option_Onchange, 0, NULL, NULL, 0, 0, NULL};
|
||||||
consvar_t cv_screenshot_folder = {"screenshot_folder", "", CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
|
consvar_t cv_screenshot_folder = {"screenshot_folder", "", CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||||
|
|
||||||
consvar_t cv_screenshot_colorprofile = {"screenshot_colorprofile", "Yes", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
consvar_t cv_screenshot_colorprofile = {"screenshot_colorprofile", "Yes", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||||
|
|
||||||
static CV_PossibleValue_t moviemode_cons_t[] = {{MM_GIF, "GIF"}, {MM_APNG, "aPNG"}, {MM_SCREENSHOT, "Screenshots"}, {0, NULL}};
|
static CV_PossibleValue_t moviemode_cons_t[] = {{MM_GIF, "GIF"}, {MM_APNG, "aPNG"}, {MM_SCREENSHOT, "Screenshots"}, {0, NULL}};
|
||||||
consvar_t cv_moviemode = {"moviemode_mode", "GIF", CV_SAVE|CV_CALL, moviemode_cons_t, Moviemode_mode_Onchange, 0, NULL, NULL, 0, 0, NULL};
|
consvar_t cv_moviemode = {"moviemode_mode", "GIF", CV_SAVE|CV_CALL, moviemode_cons_t, Moviemode_mode_Onchange, 0, NULL, NULL, 0, 0, NULL};
|
||||||
|
|
|
@ -54,6 +54,8 @@
|
||||||
|
|
||||||
#include "v_video.h"
|
#include "v_video.h"
|
||||||
|
|
||||||
|
#include "filesrch.h" // refreshdirmenu
|
||||||
|
|
||||||
// wipes
|
// wipes
|
||||||
#include "f_finale.h"
|
#include "f_finale.h"
|
||||||
|
|
||||||
|
@ -3068,6 +3070,7 @@ boolean P_AddWadFile(const char *wadfilename, char **firstmapname)
|
||||||
|
|
||||||
if ((numlumps = W_LoadWadFile(wadfilename)) == INT16_MAX)
|
if ((numlumps = W_LoadWadFile(wadfilename)) == INT16_MAX)
|
||||||
{
|
{
|
||||||
|
refreshdirmenu |= REFRESHDIR_NOTLOADED;
|
||||||
CONS_Printf(M_GetText("Errors occured while loading %s; not added.\n"), wadfilename);
|
CONS_Printf(M_GetText("Errors occured while loading %s; not added.\n"), wadfilename);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
39
src/w_wad.c
39
src/w_wad.c
|
@ -34,6 +34,8 @@
|
||||||
#include "z_zone.h"
|
#include "z_zone.h"
|
||||||
#include "fastcmp.h"
|
#include "fastcmp.h"
|
||||||
|
|
||||||
|
#include "filesrch.h"
|
||||||
|
|
||||||
#include "i_video.h" // rendermode
|
#include "i_video.h" // rendermode
|
||||||
#include "d_netfil.h"
|
#include "d_netfil.h"
|
||||||
#include "dehacked.h"
|
#include "dehacked.h"
|
||||||
|
@ -294,12 +296,12 @@ UINT16 W_LoadWadFile(const char *filename)
|
||||||
UINT32 numlumps;
|
UINT32 numlumps;
|
||||||
size_t i;
|
size_t i;
|
||||||
INT32 compressed = 0;
|
INT32 compressed = 0;
|
||||||
size_t packetsize = 0;
|
size_t packetsize;
|
||||||
serverinfo_pak *dummycheck = NULL;
|
|
||||||
UINT8 md5sum[16];
|
UINT8 md5sum[16];
|
||||||
|
boolean important;
|
||||||
|
|
||||||
// Shut the compiler up.
|
if (!(refreshdirmenu & REFRESHDIR_ADDFILE))
|
||||||
(void)dummycheck;
|
refreshdirmenu = REFRESHDIR_NORMAL|REFRESHDIR_ADDFILE; // clean out cons_alerts that happened earlier
|
||||||
|
|
||||||
//CONS_Debug(DBG_SETUP, "Loading %s\n", filename);
|
//CONS_Debug(DBG_SETUP, "Loading %s\n", filename);
|
||||||
//
|
//
|
||||||
|
@ -308,6 +310,7 @@ UINT16 W_LoadWadFile(const char *filename)
|
||||||
if (numwadfiles >= MAX_WADFILES)
|
if (numwadfiles >= MAX_WADFILES)
|
||||||
{
|
{
|
||||||
CONS_Alert(CONS_ERROR, M_GetText("Maximum wad files reached\n"));
|
CONS_Alert(CONS_ERROR, M_GetText("Maximum wad files reached\n"));
|
||||||
|
refreshdirmenu |= REFRESHDIR_MAX;
|
||||||
return INT16_MAX;
|
return INT16_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -317,21 +320,23 @@ UINT16 W_LoadWadFile(const char *filename)
|
||||||
|
|
||||||
// Check if wad files will overflow fileneededbuffer. Only the filename part
|
// Check if wad files will overflow fileneededbuffer. Only the filename part
|
||||||
// is send in the packet; cf.
|
// is send in the packet; cf.
|
||||||
for (i = 0; i < numwadfiles; i++)
|
// see PutFileNeeded in d_netfil.c
|
||||||
|
if ((important = !W_VerifyNMUSlumps(filename)))
|
||||||
{
|
{
|
||||||
packetsize += nameonlylength(wadfiles[i]->filename);
|
packetsize = packetsizetally;
|
||||||
packetsize += 22; // MD5, etc.
|
|
||||||
}
|
|
||||||
|
|
||||||
packetsize += nameonlylength(filename);
|
packetsize += nameonlylength(filename) + 22;
|
||||||
packetsize += 22;
|
|
||||||
|
|
||||||
if (packetsize > sizeof(dummycheck->fileneeded))
|
if (packetsize > MAXFILENEEDED*sizeof(UINT8))
|
||||||
{
|
{
|
||||||
CONS_Alert(CONS_ERROR, M_GetText("Maximum wad files reached\n"));
|
CONS_Alert(CONS_ERROR, M_GetText("Maximum wad files reached\n"));
|
||||||
if (handle)
|
refreshdirmenu |= REFRESHDIR_MAX;
|
||||||
fclose(handle);
|
if (handle)
|
||||||
return INT16_MAX;
|
fclose(handle);
|
||||||
|
return INT16_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
packetsizetally = packetsize;
|
||||||
}
|
}
|
||||||
|
|
||||||
// detect dehacked file with the "soc" extension
|
// detect dehacked file with the "soc" extension
|
||||||
|
@ -470,6 +475,7 @@ UINT16 W_LoadWadFile(const char *filename)
|
||||||
wadfile->handle = handle;
|
wadfile->handle = handle;
|
||||||
wadfile->numlumps = (UINT16)numlumps;
|
wadfile->numlumps = (UINT16)numlumps;
|
||||||
wadfile->lumpinfo = lumpinfo;
|
wadfile->lumpinfo = lumpinfo;
|
||||||
|
wadfile->important = important;
|
||||||
fseek(handle, 0, SEEK_END);
|
fseek(handle, 0, SEEK_END);
|
||||||
wadfile->filesize = (unsigned)ftell(handle);
|
wadfile->filesize = (unsigned)ftell(handle);
|
||||||
|
|
||||||
|
@ -1239,6 +1245,7 @@ int W_VerifyNMUSlumps(const char *filename)
|
||||||
{"TNYFN", 5}, // Tiny console font changes
|
{"TNYFN", 5}, // Tiny console font changes
|
||||||
{"STT", 3}, // Acceptable HUD changes (Score Time Rings)
|
{"STT", 3}, // Acceptable HUD changes (Score Time Rings)
|
||||||
{"YB_", 3}, // Intermission graphics, goes with the above
|
{"YB_", 3}, // Intermission graphics, goes with the above
|
||||||
|
{"M_", 2}, // As does menu stuff
|
||||||
|
|
||||||
{NULL, 0},
|
{NULL, 0},
|
||||||
};
|
};
|
||||||
|
|
|
@ -70,6 +70,7 @@ typedef struct wadfile_s
|
||||||
FILE *handle;
|
FILE *handle;
|
||||||
UINT32 filesize; // for network
|
UINT32 filesize; // for network
|
||||||
UINT8 md5sum[16];
|
UINT8 md5sum[16];
|
||||||
|
boolean important; // also network - !W_VerifyNMUSlumps
|
||||||
} wadfile_t;
|
} wadfile_t;
|
||||||
|
|
||||||
#define WADFILENUM(lumpnum) (UINT16)((lumpnum)>>16) // wad flumpnum>>16) // wad file number in upper word
|
#define WADFILENUM(lumpnum) (UINT16)((lumpnum)>>16) // wad flumpnum>>16) // wad file number in upper word
|
||||||
|
|
Loading…
Reference in a new issue