diff --git a/src/deh_lua.c b/src/deh_lua.c
index 48f737a1ff5c6587414b2efe2edbc566c9c25034..68dd03855b1ff1a3772dbbde9c26defd02b39977 100644
--- a/src/deh_lua.c
+++ b/src/deh_lua.c
@@ -12,6 +12,10 @@
 
 #include "deh_lua.h"
 
+#ifdef MUSICSLOT_COMPATIBILITY
+#include "deh_soc.h" // for get_mus
+#endif
+
 // freeslot takes a name (string only!)
 // and allocates it to the appropriate free slot.
 // Returns the slot number allocated for it or nil if failed.
@@ -519,6 +523,29 @@ static int ScanConstants(lua_State *L, boolean mathlib, const char *word)
 		if (mathlib) return luaL_error(L, "sfx '%s' could not be found.\n", word);
 		return 0;
 	}
+#ifdef MUSICSLOT_COMPATIBILITY
+	else if (!mathlib && fastncmp("mus_",word,4)) {
+		p = word+4;
+		if ((i = get_mus(p, false)) == 0)
+			return 0;
+		lua_pushinteger(L, i);
+		return 1;
+	}
+	else if (mathlib && fastncmp("MUS_",word,4)) { // SOCs are ALL CAPS!
+		p = word+4;
+		if ((i = get_mus(p, false)) == 0)
+			return luaL_error(L, "music '%s' could not be found.\n", word);
+		lua_pushinteger(L, i);
+		return 1;
+	}
+	else if (mathlib && (fastncmp("O_",word,2) || fastncmp("D_",word,2))) {
+		p = word+2;
+		if ((i = get_mus(p, false)) == 0)
+			return luaL_error(L, "music '%s' could not be found.\n", word);
+		lua_pushinteger(L, i);
+		return 1;
+	}
+#endif
 	else if (!mathlib && fastncmp("pw_",word,3)) {
 		p = word+3;
 		for (i = 0; i < NUMPOWERS; i++)
diff --git a/src/deh_soc.c b/src/deh_soc.c
index 343beb3012676b93256af35c0bd57ff6ba7e9076..ccd71eaca1a279a1fdcf94edcd09b49f14bdc7c5 100644
--- a/src/deh_soc.c
+++ b/src/deh_soc.c
@@ -1645,8 +1645,19 @@ void readlevelheader(MYFILE *f, INT32 num)
 				}
 			}
 			// TODO: 2.3: Delete
+#ifdef MUSICSLOT_COMPATIBILITY
 			else if (fastcmp(word, "MUSICSLOT"))
-				deh_warning("Level header %d: MusicSlot parameter is deprecated and will be removed.\nUse \"Music\" instead.", num);
+			{
+				i = get_mus(word2, true);
+				if (i && i <= 1035)
+					snprintf(mapheaderinfo[num-1]->musname, 7, "%sM", G_BuildMapName(i));
+				else if (i && i <= 1050)
+					strncpy(mapheaderinfo[num-1]->musname, compat_special_music_slots[i - 1036], 7);
+				else
+					mapheaderinfo[num-1]->musname[0] = 0; // becomes empty string
+				mapheaderinfo[num-1]->musname[6] = 0;
+			}
+#endif
 			else if (fastcmp(word, "MUSICTRACK"))
 				mapheaderinfo[num-1]->mustrack = ((UINT16)i - 1);
 			else if (fastcmp(word, "MUSICPOS"))
@@ -2032,6 +2043,19 @@ static void readcutscenescene(MYFILE *f, INT32 num, INT32 scenenum)
 					sizeof cutscenes[num]->scene[scenenum].musswitch,
 					va("Cutscene %d, scene %d: music", num + 1, scenenum + 1));
 			}
+#ifdef MUSICSLOT_COMPATIBILITY
+			else if (fastcmp(word, "MUSICSLOT"))
+			{
+				i = get_mus(word2, true);
+				if (i && i <= 1035)
+					snprintf(cutscenes[num]->scene[scenenum].musswitch, 7, "%sM", G_BuildMapName(i));
+				else if (i && i <= 1050)
+					strncpy(cutscenes[num]->scene[scenenum].musswitch, compat_special_music_slots[i - 1036], 7);
+				else
+					cutscenes[num]->scene[scenenum].musswitch[0] = 0; // becomes empty string
+				cutscenes[num]->scene[scenenum].musswitch[6] = 0;
+			}
+#endif
 			else if (fastcmp(word, "MUSICTRACK"))
 			{
 				cutscenes[num]->scene[scenenum].musswitchflags = ((UINT16)i) & MUSIC_TRACKMASK;
@@ -2301,6 +2325,19 @@ static void readtextpromptpage(MYFILE *f, INT32 num, INT32 pagenum)
 					sizeof textprompts[num]->page[pagenum].musswitch,
 					va("Text prompt %d, page %d: music", num + 1, pagenum + 1));
 			}
+#ifdef MUSICSLOT_COMPATIBILITY
+			else if (fastcmp(word, "MUSICSLOT"))
+			{
+				i = get_mus(word2, true);
+				if (i && i <= 1035)
+					snprintf(textprompts[num]->page[pagenum].musswitch, 7, "%sM", G_BuildMapName(i));
+				else if (i && i <= 1050)
+					strncpy(textprompts[num]->page[pagenum].musswitch, compat_special_music_slots[i - 1036], 7);
+				else
+					textprompts[num]->page[pagenum].musswitch[0] = 0; // becomes empty string
+				textprompts[num]->page[pagenum].musswitch[6] = 0;
+			}
+#endif
 			else if (fastcmp(word, "MUSICTRACK"))
 			{
 				textprompts[num]->page[pagenum].musswitchflags = ((UINT16)i) & MUSIC_TRACKMASK;
@@ -2642,6 +2679,20 @@ void readmenu(MYFILE *f, INT32 num)
 					sizeof menupres[num].musname, va("Menu %d: music", num));
 				titlechanged = true;
 			}
+#ifdef MUSICSLOT_COMPATIBILITY
+			else if (fastcmp(word, "MUSICSLOT"))
+			{
+				value = get_mus(word2, true);
+				if (value && value <= 1035)
+					snprintf(menupres[num].musname, 7, "%sM", G_BuildMapName(value));
+				else if (value && value <= 1050)
+					strncpy(menupres[num].musname, compat_special_music_slots[value - 1036], 7);
+				else
+					menupres[num].musname[0] = 0; // becomes empty string
+				menupres[num].musname[6] = 0;
+				titlechanged = true;
+			}
+#endif
 			else if (fastcmp(word, "MUSICTRACK"))
 			{
 				menupres[num].mustrack = ((UINT16)value - 1);
@@ -4255,6 +4306,46 @@ sfxenum_t get_sfx(const char *word)
 	return sfx_None;
 }
 
+#ifdef MUSICSLOT_COMPATIBILITY
+UINT16 get_mus(const char *word, UINT8 dehacked_mode)
+{ // Returns the value of MUS_ enumerations
+	UINT16 i;
+	char lumptmp[4];
+
+	if (*word >= '0' && *word <= '9')
+		return atoi(word);
+	if (!word[2] && toupper(word[0]) >= 'A' && toupper(word[0]) <= 'Z')
+		return (UINT16)M_MapNumber(word[0], word[1]);
+
+	if (fastncmp("MUS_",word,4))
+		word += 4; // take off the MUS_
+	else if (fastncmp("O_",word,2) || fastncmp("D_",word,2))
+		word += 2; // take off the O_ or D_
+
+	strncpy(lumptmp, word, 4);
+	lumptmp[3] = 0;
+	if (fasticmp("MAP",lumptmp))
+	{
+		word += 3;
+		if (toupper(word[0]) >= 'A' && toupper(word[0]) <= 'Z')
+			return (UINT16)M_MapNumber(word[0], word[1]);
+		else if ((i = atoi(word)))
+			return i;
+
+		word -= 3;
+		if (dehacked_mode)
+			deh_warning("Couldn't find music named 'MUS_%s'",word);
+		return 0;
+	}
+	for (i = 0; compat_special_music_slots[i][0]; ++i)
+		if (fasticmp(word, compat_special_music_slots[i]))
+			return i + 1036;
+	if (dehacked_mode)
+		deh_warning("Couldn't find music named 'MUS_%s'",word);
+	return 0;
+}
+#endif
+
 hudnum_t get_huditem(const char *word)
 { // Returns the value of HUD_ enumerations
 	hudnum_t i;
@@ -4485,6 +4576,13 @@ static fixed_t find_const(const char **rword)
 		free(word);
 		return r;
 	}
+#ifdef MUSICSLOT_COMPATIBILITY
+	else if (fastncmp("MUS_",word,4) || fastncmp("O_",word,2)) {
+		r = get_mus(word, true);
+		free(word);
+		return r;
+	}
+#endif
 	else if (fastncmp("PW_",word,3)) {
 		r = get_power(word);
 		free(word);
diff --git a/src/deh_soc.h b/src/deh_soc.h
index 029390133761c597c88cefb679cc847f8ce5e520..7b8d4eb34bc5b062121f547d8f906617b881f65b 100644
--- a/src/deh_soc.h
+++ b/src/deh_soc.h
@@ -43,7 +43,7 @@
 
 #include "info.h"
 #include "dehacked.h"
-#include "doomdef.h" // HWRENDER
+#include "doomdef.h" // MUSICSLOT_COMPATIBILITY, HWRENDER
 
 // Crazy word-reading stuff
 /// \todo Put these in a seperate file or something.
@@ -52,6 +52,9 @@ statenum_t get_state(const char *word);
 spritenum_t get_sprite(const char *word);
 playersprite_t get_sprite2(const char *word);
 sfxenum_t get_sfx(const char *word);
+#ifdef MUSICSLOT_COMPATIBILITY
+UINT16 get_mus(const char *word, UINT8 dehacked_mode);
+#endif
 hudnum_t get_huditem(const char *word);
 menutype_t get_menutype(const char *word);
 //INT16 get_gametype(const char *word);
diff --git a/src/doomdef.h b/src/doomdef.h
index 81ab7bbfb5505507f3df07b6b5709b6d4f995e81..87b20561a890caf96bb74b69f7ac7040a3b5a4a6 100644
--- a/src/doomdef.h
+++ b/src/doomdef.h
@@ -708,6 +708,10 @@ extern int
 /// Experimental tweaks to analog mode. (Needs a lot of work before it's ready for primetime.)
 //#define REDSANALOG
 
+/// Backwards compatibility with musicslots.
+/// \note	You should leave this enabled unless you're working with a future SRB2 version.
+#define MUSICSLOT_COMPATIBILITY
+
 /// Experimental attempts at preventing MF_PAPERCOLLISION objects from getting stuck in walls.
 //#define PAPER_COLLISIONCORRECTION
 
diff --git a/src/lua_baselib.c b/src/lua_baselib.c
index 1ffa3968be16bf8ae67b04461f12b4a6d8d1f77b..90b4f5f34a2449efaeeb5033eaa5e76ea596b9fd 100644
--- a/src/lua_baselib.c
+++ b/src/lua_baselib.c
@@ -3346,13 +3346,46 @@ static int lib_sStopSoundByID(lua_State *L)
 
 static int lib_sChangeMusic(lua_State *L)
 {
-	UINT32 position, prefadems, fadeinms;
+#ifdef MUSICSLOT_COMPATIBILITY
+	const char *music_name;
+	UINT32 music_num, position, prefadems, fadeinms;
+	char music_compat_name[7];
 
+	boolean looping;
+	player_t *player = NULL;
+	UINT16 music_flags = 0;
+	//NOHUD
+
+	if (lua_isnumber(L, 1))
+	{
+		music_num = (UINT32)luaL_checkinteger(L, 1);
+		music_flags = (UINT16)(music_num & 0x0000FFFF);
+		if (music_flags && music_flags <= 1035)
+			snprintf(music_compat_name, 7, "%sM", G_BuildMapName((INT32)music_flags));
+		else if (music_flags && music_flags <= 1050)
+			strncpy(music_compat_name, compat_special_music_slots[music_flags - 1036], 7);
+		else
+			music_compat_name[0] = 0; // becomes empty string
+		music_compat_name[6] = 0;
+		music_name = (const char *)&music_compat_name;
+		music_flags = 0;
+	}
+	else
+	{
+		music_num = 0;
+		music_name = luaL_checkstring(L, 1);
+	}
+
+	looping = (boolean)lua_opttrueboolean(L, 2);
+
+#else
 	const char *music_name = luaL_checkstring(L, 1);
 	boolean looping = (boolean)lua_opttrueboolean(L, 2);
 	player_t *player = NULL;
 	UINT16 music_flags = 0;
+	//NOHUD
 
+#endif
 	if (!lua_isnone(L, 3) && lua_isuserdata(L, 3))
 	{
 		player = *((player_t **)luaL_checkudata(L, 3, META_PLAYER));
@@ -3360,7 +3393,13 @@ static int lib_sChangeMusic(lua_State *L)
 			return LUA_ErrInvalid(L, "player_t");
 	}
 
+#ifdef MUSICSLOT_COMPATIBILITY
+	if (music_num)
+		music_flags = (UINT16)((music_num & 0x7FFF0000) >> 16);
+	else
+#endif
 	music_flags = (UINT16)luaL_optinteger(L, 4, 0);
+
 	position = (UINT32)luaL_optinteger(L, 5, 0);
 	prefadems = (UINT32)luaL_optinteger(L, 6, 0);
 	fadeinms = (UINT32)luaL_optinteger(L, 7, 0);
@@ -3657,7 +3696,33 @@ static int lib_sMusicExists(lua_State *L)
 {
 	boolean checkMIDI = lua_opttrueboolean(L, 2);
 	boolean checkDigi = lua_opttrueboolean(L, 3);
+#ifdef MUSICSLOT_COMPATIBILITY
+	const char *music_name;
+	UINT32 music_num;
+	char music_compat_name[7];
+	UINT16 music_flags = 0;
+	NOHUD
+	if (lua_isnumber(L, 1))
+	{
+		music_num = (UINT32)luaL_checkinteger(L, 1);
+		music_flags = (UINT16)(music_num & 0x0000FFFF);
+		if (music_flags && music_flags <= 1035)
+			snprintf(music_compat_name, 7, "%sM", G_BuildMapName((INT32)music_flags));
+		else if (music_flags && music_flags <= 1050)
+			strncpy(music_compat_name, compat_special_music_slots[music_flags - 1036], 7);
+		else
+			music_compat_name[0] = 0; // becomes empty string
+		music_compat_name[6] = 0;
+		music_name = (const char *)&music_compat_name;
+	}
+	else
+	{
+		music_num = 0;
+		music_name = luaL_checkstring(L, 1);
+	}
+#else
 	const char *music_name = luaL_checkstring(L, 1);
+#endif
 	NOHUD
 	lua_pushboolean(L, S_MusicExists(music_name, checkMIDI, checkDigi));
 	return 1;
diff --git a/src/s_sound.c b/src/s_sound.c
index 0329c289ee104e56cf1c156683690d65455aeed5..5fb7fa40b569e7a66bb171dedc900606aef6ccc5 100644
--- a/src/s_sound.c
+++ b/src/s_sound.c
@@ -1352,6 +1352,28 @@ void S_InitSfxChannels(INT32 sfxVolume)
 /// Music
 /// ------------------------
 
+#ifdef MUSICSLOT_COMPATIBILITY
+const char *compat_special_music_slots[16] =
+{
+	"_title", // 1036  title screen
+	"_intro", // 1037  intro
+	"_clear", // 1038  level clear
+	"_inv", // 1039  invincibility
+	"_shoes",  // 1040  super sneakers
+	"_minv", // 1041  Mario invincibility
+	"_drown",  // 1042  drowning
+	"_gover", // 1043  game over
+	"_1up", // 1044  extra life
+	"_conti", // 1045  continue screen
+	"_super", // 1046  Super Sonic
+	"_chsel", // 1047  character select
+	"_creds", // 1048  credits
+	"_inter", // 1049  Race Results
+	"_stjr",   // 1050  Sonic Team Jr. Presents
+	""
+};
+#endif
+
 static char      music_name[7]; // up to 6-character name
 static void      *music_data;
 static UINT16    music_flags;
@@ -2452,7 +2474,7 @@ void S_StartEx(boolean reset)
 static void Command_Tunes_f(void)
 {
 	const char *tunearg;
-	UINT16 track = 0;
+	UINT16 tunenum, track = 0;
 	UINT32 position = 0;
 	const size_t argc = COM_Argc();
 
@@ -2468,6 +2490,7 @@ static void Command_Tunes_f(void)
 	}
 
 	tunearg = COM_Argv(1);
+	tunenum = (UINT16)atoi(tunearg);
 	track = 0;
 
 	if (!strcasecmp(tunearg, "-show"))
@@ -2486,14 +2509,24 @@ static void Command_Tunes_f(void)
 		tunearg = mapheaderinfo[gamemap-1]->musname;
 		track = mapheaderinfo[gamemap-1]->mustrack;
 	}
+	else if (!tunearg[2] && toupper(tunearg[0]) >= 'A' && toupper(tunearg[0]) <= 'Z')
+		tunenum = (UINT16)M_MapNumber(tunearg[0], tunearg[1]);
 
-	if (strlen(tunearg) > 6) // This is automatic -- just show the error just in case
+	if (tunenum && tunenum >= 1036)
+	{
+		CONS_Alert(CONS_NOTICE, M_GetText("Valid music slots are 1 to 1035.\n"));
+		return;
+	}
+	if (!tunenum && strlen(tunearg) > 6) // This is automatic -- just show the error just in case
 		CONS_Alert(CONS_NOTICE, M_GetText("Music name too long - truncated to six characters.\n"));
 
 	if (argc > 2)
 		track = (UINT16)atoi(COM_Argv(2))-1;
 
-	strncpy(mapmusname, tunearg, 7);
+	if (tunenum)
+		snprintf(mapmusname, 7, "%sM", G_BuildMapName(tunenum));
+	else
+		strncpy(mapmusname, tunearg, 7);
 	mapmusname[6] = 0;
 
 	if (argc > 4)
diff --git a/src/s_sound.h b/src/s_sound.h
index 589060c8c2a45ce25deeee80db521a4673f39dc2..5d2626b4100631e1b461b536fa1eb08d0b9f4fa1 100644
--- a/src/s_sound.h
+++ b/src/s_sound.h
@@ -329,4 +329,10 @@ void S_StopSoundByNum(sfxenum_t sfxnum);
 #define S_StartScreamSound S_StartSound
 #endif
 
+#ifdef MUSICSLOT_COMPATIBILITY
+// For compatibility with code/scripts relying on older versions
+// This is a list of all the "special" slot names and their associated numbers
+extern const char *compat_special_music_slots[16];
+#endif
+
 #endif