diff --git a/src/filesrch.c b/src/filesrch.c
index ff389fa3db190ea3eba9f4a5f3900cbed0f3d834..2985e8373b2b501722ecb9acfaf00d10599f317e 100644
--- a/src/filesrch.c
+++ b/src/filesrch.c
@@ -288,12 +288,12 @@ closedir (DIR * dirp)
 #endif
 
 char menupath[1024];
-size_t menupathindex[20];
-size_t menudepthleft = 20;
+size_t menupathindex[menudepth];
+size_t menudepthleft = menudepth;
 
 char **dirmenu;
 size_t sizedirmenu;
-size_t dir_on[20];
+size_t dir_on[menudepth];
 
 #if defined (_XBOX) && defined (_MSC_VER)
 filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *wantedmd5sum,
@@ -473,8 +473,7 @@ filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *want
 	return retval;
 }
 
-#define MAXEXT 5
-char ext[MAXEXT][5] = {
+char exttable[NUM_EXT_TABLE][5] = {
 	".txt", ".cfg", // exec
 	".wad", ".soc", ".lua"}; // addfile
 
@@ -518,10 +517,10 @@ boolean preparefilemenu(void)
 			if (!S_ISDIR(fsstat.st_mode))
 			{
 				size_t len = strlen(dent->d_name)+1;
-				UINT8 i;
-				for (i = 0; i < MAXEXT; i++)
-					if (!strcasecmp(ext[i], dent->d_name+len-5)) break;
-				if (i == MAXEXT) continue; // not an addfile-able (or exec-able) file
+				UINT8 ext;
+				for (ext = 0; ext < NUM_EXT_TABLE; ext++)
+					if (!strcasecmp(exttable[ext], dent->d_name+len-5)) break;
+				if (ext == NUM_EXT_TABLE) continue; // not an addfile-able (or exec-able) file
 			}
 			else
 				numfolders++;
@@ -534,6 +533,13 @@ boolean preparefilemenu(void)
 	if (!sizedirmenu)
 		return false;
 
+	if (menudepthleft != menudepth-1)
+	{
+		numfolders++;
+		sizedirmenu++;
+		folderpos++;
+	}
+
 	if (!(dirmenu = Z_Realloc(dirmenu, sizedirmenu*sizeof(char *), PU_STATIC, NULL)))
 		I_Error("Ran out of memory whilst preparing add-ons menu");
 
@@ -560,15 +566,15 @@ boolean preparefilemenu(void)
 		{
 			char *temp;
 			size_t len = strlen(dent->d_name)+1;
-			UINT8 i = 0;
+			UINT8 ext = EXT_FOLDER;
 			size_t folder;
 
 			if (!S_ISDIR(fsstat.st_mode)) // file
 			{
-				for (; i < MAXEXT; i++)
-					if (!strcasecmp(ext[i], dent->d_name+len-5)) break;
-				if (i == MAXEXT) continue; // not an addfile-able (or exec-able) file
-				i++; // i goes up so zero-index is directory instead of .txt
+				for (; ext < NUM_EXT_TABLE; ext++)
+					if (!strcasecmp(exttable[ext], dent->d_name+len-5)) break;
+				if (ext == NUM_EXT_TABLE) continue; // not an addfile-able (or exec-able) file
+				ext += EXT_START; // moving to be appropriate position
 				folder = 0;
 			}
 			else
@@ -579,7 +585,7 @@ boolean preparefilemenu(void)
 
 			if (!(temp = Z_Malloc((len+2+folder) * sizeof (char), PU_STATIC, NULL)))
 				I_Error("Ran out of memory whilst preparing add-ons menu");
-			temp[0] = i;
+			temp[0] = ext;
 			temp[1] = (UINT8)(len);
 			strlcpy(temp+2, dent->d_name, len);
 			if (folder)
@@ -592,9 +598,15 @@ boolean preparefilemenu(void)
 		}
 	}
 
+	if (menudepthleft != menudepth-1)
+		dirmenu[0] = Z_StrDup("\1\7\x1A UP...");
+
 	menupath[menupathindex[menudepthleft]] = 0;
 	sizedirmenu = (pos+folderpos); // crash prevention if things change between openings somehow
 
+	if (dir_on[menudepthleft] >= sizedirmenu)
+		dir_on[menudepthleft] = sizedirmenu;
+
 	closedir(dirhandle);
 	return true;
 }
diff --git a/src/filesrch.h b/src/filesrch.h
index 0ce7ff94c772cd01a21931b17fbadae32a4db4ae..84932fd60761846c152ec3aade0e19334dd5d229 100644
--- a/src/filesrch.h
+++ b/src/filesrch.h
@@ -25,13 +25,29 @@
 filestatus_t filesearch(char *filename, const char *startpath, const UINT8 *wantedmd5sum,
 	boolean completepath, int maxsearchdepth);
 
+#define menudepth 20
+
 extern char menupath[1024];
-extern size_t menupathindex[20];
+extern size_t menupathindex[menudepth];
 extern size_t menudepthleft;
 
 extern char **dirmenu;
 extern size_t sizedirmenu;
-extern size_t dir_on[20];
+extern size_t dir_on[menudepth];
+
+typedef enum
+{
+	EXT_FOLDER = 0,
+	EXT_UP,
+	EXT_START,
+	EXT_TXT = EXT_START,
+	EXT_CFG,
+	EXT_WAD,
+	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_enum;
 
 boolean preparefilemenu(void);
 
diff --git a/src/hu_stuff.h b/src/hu_stuff.h
index 5356ba8acd40e3a765b9fc7e099f3f849d73c7df..c2654d2096b83c4d592210dad976d3eebfd1f31d 100644
--- a/src/hu_stuff.h
+++ b/src/hu_stuff.h
@@ -21,7 +21,7 @@
 //------------------------------------
 //           heads up font
 //------------------------------------
-#define HU_FONTSTART '\x1F' // the first font character
+#define HU_FONTSTART '\x19' // the first font character
 #define HU_FONTEND '~'
 
 #define HU_FONTSIZE (HU_FONTEND - HU_FONTSTART + 1)
diff --git a/src/m_menu.c b/src/m_menu.c
index d491712ae487fb49c1164170b58fee85f732b1db..4cee61221a4dc2e54f6294a6809eff82ed12061d 100644
--- a/src/m_menu.c
+++ b/src/m_menu.c
@@ -4444,7 +4444,7 @@ static void M_Addons(INT32 choice)
 	(void)choice;
 
 	strlcpy(menupath, srb2home, 1024);
-	menupathindex[(menudepthleft = 19)] = strlen(menupath) + 1;
+	menupathindex[(menudepthleft = menudepth-1)] = strlen(menupath) + 1;
 
 	if (menupath[menupathindex[menudepthleft]-2] != '/')
 	{
@@ -4475,17 +4475,26 @@ static void M_DrawAddons(void)
 	x = currentMenu->x;
 	y = currentMenu->y;
 
-	V_DrawString(x, y, 0, menupath);
+	V_DrawString(x, y, V_ALLOWLOWERCASE, menupath);
 	y += 2*SMALLLINEHEIGHT;
 
 	for (i = dir_on[menudepthleft]; i < sizedirmenu; i++)
 	{
 		if (y > BASEVIDHEIGHT) break;
-		V_DrawString(x, y, 0, dirmenu[i]+2);
+		V_DrawString(x, y, ((dirmenu[dir_on[menudepthleft]][0] == EXT_UP) ? 0 : V_ALLOWLOWERCASE), dirmenu[i]+2);
 		y += SMALLLINEHEIGHT;
 	}
 }
 
+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]]+2));
+}
+
 static void M_HandleAddons(INT32 choice)
 {
 	boolean exitmenu = false; // exit to previous menu
@@ -4503,48 +4512,71 @@ static void M_HandleAddons(INT32 choice)
 			S_StartSound(NULL, sfx_menu1);
 			break;
 		case KEY_ENTER:
-			if (dirmenu[dir_on[menudepthleft]][0] == 0) // folder
 			{
-				S_StartSound(NULL, sfx_strpst);
-				strcpy(&menupath[menupathindex[menudepthleft]],dirmenu[dir_on[menudepthleft]]+2);
-				menupathindex[--menudepthleft] = strlen(menupath);
-				menupath[menupathindex[menudepthleft]] = 0;
-
-				if (!preparefilemenu())
+				boolean refresh = true;
+				switch (dirmenu[dir_on[menudepthleft]][0])
 				{
-					M_StartMessage(M_GetText("Folder is empty.\n\n(Press a key)\n"),NULL,MM_NOTHING);
-					menupath[menupathindex[++menudepthleft]] = 0;
-					if (!preparefilemenu())
-					{
-						M_StartMessage(M_GetText("Folder no longer exists!\n\n(Press a key)\n"),NULL,MM_NOTHING);
-						M_SetupNextMenu(MISC_AddonsDef.prevMenu);
-						return;
-					}
+					case EXT_FOLDER:
+						if (menudepthleft)
+						{
+							strcpy(&menupath[menupathindex[menudepthleft]],dirmenu[dir_on[menudepthleft]]+2);
+							menupathindex[--menudepthleft] = strlen(menupath);
+							menupath[menupathindex[menudepthleft]] = 0;
+
+							if (!preparefilemenu())
+							{
+								S_StartSound(NULL, sfx_skid);
+								M_StartMessage(va("%s\nThis folder is empty.\n\n(Press a key)\n", menupath),NULL,MM_NOTHING);
+								menupath[menupathindex[++menudepthleft]] = 0;
+							}
+							else
+							{
+								S_StartSound(NULL, sfx_strpst);
+								dir_on[menudepthleft] = 0;
+								refresh =  false;
+							}
+						}
+						else
+						{
+							S_StartSound(NULL, sfx_lose);
+							M_StartMessage(va("%s%s\nThis folder is too deep to navigate to!\n\n(Press a key)\n", menupath, dirmenu[dir_on[menudepthleft]]+2),NULL,MM_NOTHING);
+						}
+						break;
+					case EXT_UP:
+						S_StartSound(NULL, sfx_skid);
+						menupath[menupathindex[++menudepthleft]] = 0;
+						break;
+					case EXT_TXT:
+						M_StartMessage(va("%s\nThis file may not be a console script.\nAttempt to run anyways? \n\n(Press 'Y' to confirm)\n", dirmenu[dir_on[menudepthleft]]+2),M_AddonExec,MM_YESNO);
+						break;
+					case EXT_CFG:
+						M_AddonExec(KEY_ENTER);
+						break;
+					case EXT_LUA:
+#ifdef HAVE_BLUA
+						S_StartSound(NULL, sfx_lose);
+						M_StartMessage(va("%s\nThis copy of SRB2 was compiled\nwithout support for .lua files.\n\n(Press a key)\n", dirmenu[dir_on[menudepthleft]]+2),NULL,MM_NOTHING);
+						break;
+#endif
+					// else intentional fallthrough
+					case EXT_WAD:
+					case EXT_SOC:
+						S_StartSound(NULL, sfx_strpst);
+						COM_BufAddText(va("addfile %s%s", menupath, dirmenu[dir_on[menudepthleft]]+2));
+						break;
+					default:
+						S_StartSound(NULL, sfx_lose);
 				}
-				else
-					dir_on[menudepthleft] = 0;
-			}
-			else if (dirmenu[dir_on[menudepthleft]][0] >= 3) // wad/soc/lua
-			{
-				S_StartSound(NULL, sfx_strpst);
-				COM_BufAddText(va("addfile %s%s", menupath, dirmenu[dir_on[menudepthleft]]+2));
-			}
-			else
-				S_StartSound(NULL, sfx_lose);
-			break;
-		case KEY_BACKSPACE:
-			if (menudepthleft < 19)
-			{
-				menupath[menupathindex[++menudepthleft]] = 0;
-				if (!preparefilemenu())
+				if (refresh && !preparefilemenu())
 				{
-					M_StartMessage(M_GetText("Folder no longer exists!\n\n(Press a key)\n"),NULL,MM_NOTHING);
+					S_StartSound(NULL, sfx_lose);
 					M_SetupNextMenu(MISC_AddonsDef.prevMenu);
+					M_StartMessage(va("%s\nThis folder no longer exists!\nAborting to main menu.\n\n(Press a key)\n", menupath),NULL,MM_NOTHING);
 					return;
 				}
-				break;
 			}
-			// intentional fallthrough
+			break;
+
 		case KEY_ESCAPE:
 			exitmenu = true;
 			break;