diff --git a/src/d_netcmd.c b/src/d_netcmd.c
index 02bc464e61e882c2bc36ab0e4fb8afa72a3a4e5c..5eb35283414b7f807249df101c14d4048bb1251e 100644
--- a/src/d_netcmd.c
+++ b/src/d_netcmd.c
@@ -1854,10 +1854,10 @@ static void Got_Pause(UINT8 **cp, INT32 playernum)
 		if (paused)
 		{
 			if (!menuactive || netgame)
-				S_PauseSound();
+				S_PauseAudio();
 		}
 		else
-			S_ResumeSound();
+			S_ResumeAudio();
 	}
 }
 
@@ -3761,50 +3761,66 @@ static void Command_Displayplayer_f(void)
 static void Command_Tunes_f(void)
 {
 	const char *tunearg;
-	UINT16 tune, track = 0;
+	UINT16 tunenum, track = 0;
 	const size_t argc = COM_Argc();
 
 	if (argc < 2) //tunes slot ...
 	{
-		CONS_Printf("tunes <slot #/map name/\"default\"> <speed> <track>:\n");
-		CONS_Printf(M_GetText("Play a music slot at a set speed (\"1\" being normal speed).\n"));
-		CONS_Printf(M_GetText("If the format supports multiple songs, you can specify which one to play.\n"));
-		CONS_Printf(M_GetText("The current tune is: %d\nThe current track is: %d\n"),
-			(mapmusic & MUSIC_SONGMASK), ((mapmusic & MUSIC_TRACKMASK) >> MUSIC_TRACKSHIFT));
+		CONS_Printf("tunes <name/num> [track] [speed] / <-show> / <-default> / <-none>:\n");
+		CONS_Printf(M_GetText("Play an arbitrary music lump. If a map number is used, 'MAP##M' is played.\n"));
+		CONS_Printf(M_GetText("If the format supports multiple songs, you can specify which one to play.\n\n"));
+		CONS_Printf(M_GetText("* With \"-show\", shows the currently playing tune and track.\n"));
+		CONS_Printf(M_GetText("* With \"-default\", returns to the default music for the map.\n"));
+		CONS_Printf(M_GetText("* With \"-none\", any music playing will be stopped.\n"));
 		return;
 	}
 
 	tunearg = COM_Argv(1);
-	tune = (UINT16)atoi(tunearg);
+	tunenum = (UINT16)atoi(tunearg);
 	track = 0;
 
-	if (!strcasecmp(tunearg, "default"))
+	if (!strcasecmp(tunearg, "-show"))
 	{
-		tune = mapheaderinfo[gamemap-1]->musicslot;
-		track = mapheaderinfo[gamemap-1]->musicslottrack;
+		CONS_Printf(M_GetText("The current tune is: %s [track %d]\n"),
+			mapmusname, (mapmusflags & MUSIC_TRACKMASK));
+		return;
 	}
-	else if (toupper(tunearg[0]) >= 'A' && toupper(tunearg[0]) <= 'Z')
-		tune = (UINT16)M_MapNumber(tunearg[0], tunearg[1]);
-
-	if (tune >= NUMMUSIC)
+	if (!strcasecmp(tunearg, "-none"))
 	{
-		CONS_Alert(CONS_NOTICE, M_GetText("Valid slots are 1 to %d, or 0 to stop music\n"), NUMMUSIC - 1);
+		S_StopMusic();
 		return;
 	}
+	else if (!strcasecmp(tunearg, "-default"))
+	{
+		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 (argc > 3)
-		track = (UINT16)atoi(COM_Argv(3))-1;
+	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"));
 
-	mapmusic = tune | (track << MUSIC_TRACKSHIFT);
+	if (argc > 2)
+		track = (UINT16)atoi(COM_Argv(2))-1;
 
-	if (tune == mus_None)
-		S_StopMusic();
+	if (tunenum)
+		snprintf(mapmusname, 7, "%sM", G_BuildMapName(tunenum));
 	else
-		S_ChangeMusic(mapmusic, true);
+		strncpy(mapmusname, tunearg, 7);
+	mapmusname[6] = 0;
+	mapmusflags = (track & MUSIC_TRACKMASK);
 
-	if (argc > 2)
+	S_ChangeMusic(mapmusname, mapmusflags, true);
+
+	if (argc > 3)
 	{
-		float speed = (float)atof(COM_Argv(2));
+		float speed = (float)atof(COM_Argv(3));
 		if (speed > 0.0f)
 			S_SpeedMusic(speed);
 	}
diff --git a/src/dehacked.c b/src/dehacked.c
index 44ef998ac58d011a6911b2ac87ee42306173c946..c21e8fb99316648163d34e7a82e7a3cf6e600996 100644
--- a/src/dehacked.c
+++ b/src/dehacked.c
@@ -65,7 +65,9 @@ static mobjtype_t get_mobjtype(const char *word);
 static statenum_t get_state(const char *word);
 static spritenum_t get_sprite(const char *word);
 static sfxenum_t get_sfx(const char *word);
-static UINT16 get_mus(const char *word);
+#ifdef MUSICSLOT_COMPATIBILITY
+static UINT16 get_mus(const char *word, UINT8 dehacked_mode);
+#endif
 static hudnum_t get_huditem(const char *word);
 #ifndef HAVE_BLUA
 static powertype_t get_power(const char *word);
@@ -1164,19 +1166,31 @@ static void readlevelheader(MYFILE *f, INT32 num)
 					mapheaderinfo[num-1]->typeoflevel = tol;
 				}
 			}
+			else if (fastcmp(word, "MUSIC"))
+			{
+				if (fastcmp(word2, "NONE"))
+					mapheaderinfo[num-1]->musname[0] = 0; // becomes empty string
+				else
+				{
+					deh_strlcpy(mapheaderinfo[num-1]->musname, word2,
+						sizeof(mapheaderinfo[num-1]->musname), va("Level header %d: music", num));
+				}
+			}
+#ifdef MUSICSLOT_COMPATIBILITY
 			else if (fastcmp(word, "MUSICSLOT"))
 			{
-				// Convert to map number
-				if (word2[0] >= 'A' && word2[0] <= 'Z' && word2[2] == '\0')
-					i = M_MapNumber(word2[0], word2[1]);
-
-				if (i) // it's just a number
-					mapheaderinfo[num-1]->musicslot = (UINT16)i;
-				else // No? Okay, now we'll get technical.
-					mapheaderinfo[num-1]->musicslot = get_mus(word2); // accepts all of O_CHRSEL, mus_chrsel, or just plain ChrSel
+				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;
 			}
-			else if (fastcmp(word, "MUSICSLOTTRACK"))
-				mapheaderinfo[num-1]->musicslottrack = ((UINT16)i - 1);
+#endif
+			else if (fastcmp(word, "MUSICTRACK"))
+				mapheaderinfo[num-1]->mustrack = ((UINT16)i - 1);
 			else if (fastcmp(word, "FORCECHARACTER"))
 			{
 				strlcpy(mapheaderinfo[num-1]->forcecharacter, word2, SKINNAMESIZE+1);
@@ -1443,10 +1457,30 @@ static void readcutscenescene(MYFILE *f, INT32 num, INT32 scenenum)
 				else
 					deh_warning("CutSceneScene %d: unknown word '%s'", num, word);
 			}
+			else if (fastcmp(word, "MUSIC"))
+			{
+				DEH_WriteUndoline(word, cutscenes[num]->scene[scenenum].musswitch, UNDO_NONE);
+				strncpy(cutscenes[num]->scene[scenenum].musswitch, word2, 7);
+				cutscenes[num]->scene[scenenum].musswitch[6] = 0;
+			}
+#ifdef MUSICSLOT_COMPATIBILITY
 			else if (fastcmp(word, "MUSICSLOT"))
 			{
-				DEH_WriteUndoline(word, va("%u", cutscenes[num]->scene[scenenum].musicslot), UNDO_NONE);
-				cutscenes[num]->scene[scenenum].musicslot = get_mus(word2); // accepts all of O_MAP01M, mus_map01m, or just plain MAP01M
+				DEH_WriteUndoline(word, cutscenes[num]->scene[scenenum].musswitch, UNDO_NONE);
+				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"))
+			{
+				DEH_WriteUndoline(word, va("%u", cutscenes[num]->scene[scenenum].musswitchflags), UNDO_NONE);
+				cutscenes[num]->scene[scenenum].musswitchflags = ((UINT16)i) & MUSIC_TRACKMASK;
 			}
 			else if (fastcmp(word, "MUSICLOOP"))
 			{
@@ -3187,6 +3221,12 @@ static void readwipes(MYFILE *f)
 				else if (fastcmp(pword, "FINAL"))
 					wipeoffset = wipe_gameend_final;
 			}
+			else if (fastncmp(word, "SPECLEVEL_", 10))
+			{
+				pword = word + 10;
+				if (fastcmp(pword, "TOWHITE"))
+					wipeoffset = wipe_speclevel_towhite;
+			}
 
 			if (wipeoffset < 0)
 			{
@@ -3194,9 +3234,11 @@ static void readwipes(MYFILE *f)
 				continue;
 			}
 
-			if (value == UINT8_MAX // Cannot disable non-toblack wipes (or the level toblack wipe)
-			 && (wipeoffset <= wipe_level_toblack || wipeoffset >= wipe_level_final))
+			if (value == UINT8_MAX
+			 && (wipeoffset <= wipe_level_toblack || wipeoffset >= wipe_speclevel_towhite))
 			{
+				 // Cannot disable non-toblack wipes
+				 // (or the level toblack wipe, or the special towhite wipe)
 				deh_warning("Wipes: can't disable wipe of type '%s'", word);
 				continue;
 			}
@@ -4588,30 +4630,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
 	"S_MSSHIELD_F12",
 
 	// Ring
-	"S_RING1",
-	"S_RING2",
-	"S_RING3",
-	"S_RING4",
-	"S_RING5",
-	"S_RING6",
-	"S_RING7",
-	"S_RING8",
-	"S_RING9",
-	"S_RING10",
-	"S_RING11",
-	"S_RING12",
-	"S_RING13",
-	"S_RING14",
-	"S_RING15",
-	"S_RING16",
-	"S_RING17",
-	"S_RING18",
-	"S_RING19",
-	"S_RING20",
-	"S_RING21",
-	"S_RING22",
-	"S_RING23",
-	"S_RING24",
+	"S_RING",
 
 	// Blue Sphere for special stages
 	"S_BLUEBALL",
@@ -4627,39 +4646,10 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
 	"S_GRAVWELLRED3",
 
 	// Individual Team Rings
-	"S_TEAMRING1",
-	"S_TEAMRING2",
-	"S_TEAMRING3",
-	"S_TEAMRING4",
-	"S_TEAMRING5",
-	"S_TEAMRING6",
-	"S_TEAMRING7",
-	"S_TEAMRING8",
-	"S_TEAMRING9",
-	"S_TEAMRING10",
-	"S_TEAMRING11",
-	"S_TEAMRING12",
-	"S_TEAMRING13",
-	"S_TEAMRING14",
-	"S_TEAMRING15",
-	"S_TEAMRING16",
-	"S_TEAMRING17",
-	"S_TEAMRING18",
-	"S_TEAMRING19",
-	"S_TEAMRING20",
-	"S_TEAMRING21",
-	"S_TEAMRING22",
-	"S_TEAMRING23",
-	"S_TEAMRING24",
+	"S_TEAMRING",
 
 	// Special Stage Token
-	"S_EMMY1",
-	"S_EMMY2",
-	"S_EMMY3",
-	"S_EMMY4",
-	"S_EMMY5",
-	"S_EMMY6",
-	"S_EMMY7",
+	"S_EMMY",
 
 	// Special Stage Token
 	"S_TOKEN",
@@ -4813,40 +4803,9 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
 	"S_SPIKED2",
 
 	// Starpost
-	"S_STARPOST1",
-	"S_STARPOST2",
-	"S_STARPOST3",
-	"S_STARPOST4",
-	"S_STARPOST5",
-	"S_STARPOST6",
-	"S_STARPOST7",
-	"S_STARPOST8",
-	"S_STARPOST9",
-	"S_STARPOST10",
-	"S_STARPOST11",
-	"S_STARPOST12",
-	"S_STARPOST13",
-	"S_STARPOST14",
-	"S_STARPOST15",
-	"S_STARPOST16",
-	"S_STARPOST17",
-	"S_STARPOST18",
-	"S_STARPOST19",
-	"S_STARPOST20",
-	"S_STARPOST21",
-	"S_STARPOST22",
-	"S_STARPOST23",
-	"S_STARPOST24",
-	"S_STARPOST25",
-	"S_STARPOST26",
-	"S_STARPOST27",
-	"S_STARPOST28",
-	"S_STARPOST29",
-	"S_STARPOST30",
-	"S_STARPOST31",
-	"S_STARPOST32",
-	"S_STARPOST33",
-	"S_STARPOST34",
+	"S_STARPOST_IDLE",
+	"S_STARPOST_FLASH",
+	"S_STARPOST_SPIN",
 
 	// Big floating mine
 	"S_BIGMINE1",
@@ -5454,38 +5413,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
 	"S_PITY10",
 
 	// Invincibility Sparkles
-	"S_IVSP1",
-	"S_IVSP2",
-	"S_IVSP3",
-	"S_IVSP4",
-	"S_IVSP5",
-	"S_IVSP6",
-	"S_IVSP7",
-	"S_IVSP8",
-	"S_IVSP9",
-	"S_IVSP10",
-	"S_IVSP11",
-	"S_IVSP12",
-	"S_IVSP13",
-	"S_IVSP14",
-	"S_IVSP15",
-	"S_IVSP16",
-	"S_IVSP17",
-	"S_IVSP18",
-	"S_IVSP19",
-	"S_IVSP20",
-	"S_IVSP21",
-	"S_IVSP22",
-	"S_IVSP23",
-	"S_IVSP24",
-	"S_IVSP25",
-	"S_IVSP26",
-	"S_IVSP27",
-	"S_IVSP28",
-	"S_IVSP29",
-	"S_IVSP30",
-	"S_IVSP31",
-	"S_IVSP32",
+	"S_IVSP",
 
 	// Super Sonic Spark
 	"S_SSPK1",
@@ -5672,283 +5600,17 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
 	"S_RRNG6",
 	"S_RRNG7",
 
-	// Bounce Ring
-	"S_BOUNCERING1",
-	"S_BOUNCERING2",
-	"S_BOUNCERING3",
-	"S_BOUNCERING4",
-	"S_BOUNCERING5",
-	"S_BOUNCERING6",
-	"S_BOUNCERING7",
-	"S_BOUNCERING8",
-	"S_BOUNCERING9",
-	"S_BOUNCERING10",
-	"S_BOUNCERING11",
-	"S_BOUNCERING12",
-	"S_BOUNCERING13",
-	"S_BOUNCERING14",
-	"S_BOUNCERING15",
-	"S_BOUNCERING16",
-	"S_BOUNCERING17",
-	"S_BOUNCERING18",
-	"S_BOUNCERING19",
-	"S_BOUNCERING20",
-	"S_BOUNCERING21",
-	"S_BOUNCERING22",
-	"S_BOUNCERING23",
-	"S_BOUNCERING24",
-	"S_BOUNCERING25",
-	"S_BOUNCERING26",
-	"S_BOUNCERING27",
-	"S_BOUNCERING28",
-	"S_BOUNCERING29",
-	"S_BOUNCERING30",
-	"S_BOUNCERING31",
-	"S_BOUNCERING32",
-	"S_BOUNCERING33",
-	"S_BOUNCERING34",
-	"S_BOUNCERING35",
-
-	// Rail Ring
-	"S_RAILRING1",
-	"S_RAILRING2",
-	"S_RAILRING3",
-	"S_RAILRING4",
-	"S_RAILRING5",
-	"S_RAILRING6",
-	"S_RAILRING7",
-	"S_RAILRING8",
-	"S_RAILRING9",
-	"S_RAILRING10",
-	"S_RAILRING11",
-	"S_RAILRING12",
-	"S_RAILRING13",
-	"S_RAILRING14",
-	"S_RAILRING15",
-	"S_RAILRING16",
-	"S_RAILRING17",
-	"S_RAILRING18",
-	"S_RAILRING19",
-	"S_RAILRING20",
-	"S_RAILRING21",
-	"S_RAILRING22",
-	"S_RAILRING23",
-	"S_RAILRING24",
-	"S_RAILRING25",
-	"S_RAILRING26",
-	"S_RAILRING27",
-	"S_RAILRING28",
-	"S_RAILRING29",
-	"S_RAILRING30",
-	"S_RAILRING31",
-	"S_RAILRING32",
-	"S_RAILRING33",
-	"S_RAILRING34",
-	"S_RAILRING35",
-
-	// Infinity ring
-	"S_INFINITYRING1",
-	"S_INFINITYRING2",
-	"S_INFINITYRING3",
-	"S_INFINITYRING4",
-	"S_INFINITYRING5",
-	"S_INFINITYRING6",
-	"S_INFINITYRING7",
-	"S_INFINITYRING8",
-	"S_INFINITYRING9",
-	"S_INFINITYRING10",
-	"S_INFINITYRING11",
-	"S_INFINITYRING12",
-	"S_INFINITYRING13",
-	"S_INFINITYRING14",
-	"S_INFINITYRING15",
-	"S_INFINITYRING16",
-	"S_INFINITYRING17",
-	"S_INFINITYRING18",
-	"S_INFINITYRING19",
-	"S_INFINITYRING20",
-	"S_INFINITYRING21",
-	"S_INFINITYRING22",
-	"S_INFINITYRING23",
-	"S_INFINITYRING24",
-	"S_INFINITYRING25",
-	"S_INFINITYRING26",
-	"S_INFINITYRING27",
-	"S_INFINITYRING28",
-	"S_INFINITYRING29",
-	"S_INFINITYRING30",
-	"S_INFINITYRING31",
-	"S_INFINITYRING32",
-	"S_INFINITYRING33",
-	"S_INFINITYRING34",
-	"S_INFINITYRING35",
-
-	// Automatic Ring
-	"S_AUTOMATICRING1",
-	"S_AUTOMATICRING2",
-	"S_AUTOMATICRING3",
-	"S_AUTOMATICRING4",
-	"S_AUTOMATICRING5",
-	"S_AUTOMATICRING6",
-	"S_AUTOMATICRING7",
-	"S_AUTOMATICRING8",
-	"S_AUTOMATICRING9",
-	"S_AUTOMATICRING10",
-	"S_AUTOMATICRING11",
-	"S_AUTOMATICRING12",
-	"S_AUTOMATICRING13",
-	"S_AUTOMATICRING14",
-	"S_AUTOMATICRING15",
-	"S_AUTOMATICRING16",
-	"S_AUTOMATICRING17",
-	"S_AUTOMATICRING18",
-	"S_AUTOMATICRING19",
-	"S_AUTOMATICRING20",
-	"S_AUTOMATICRING21",
-	"S_AUTOMATICRING22",
-	"S_AUTOMATICRING23",
-	"S_AUTOMATICRING24",
-	"S_AUTOMATICRING25",
-	"S_AUTOMATICRING26",
-	"S_AUTOMATICRING27",
-	"S_AUTOMATICRING28",
-	"S_AUTOMATICRING29",
-	"S_AUTOMATICRING30",
-	"S_AUTOMATICRING31",
-	"S_AUTOMATICRING32",
-	"S_AUTOMATICRING33",
-	"S_AUTOMATICRING34",
-	"S_AUTOMATICRING35",
-
-	// Explosion Ring
-	"S_EXPLOSIONRING1",
-	"S_EXPLOSIONRING2",
-	"S_EXPLOSIONRING3",
-	"S_EXPLOSIONRING4",
-	"S_EXPLOSIONRING5",
-	"S_EXPLOSIONRING6",
-	"S_EXPLOSIONRING7",
-	"S_EXPLOSIONRING8",
-	"S_EXPLOSIONRING9",
-	"S_EXPLOSIONRING10",
-	"S_EXPLOSIONRING11",
-	"S_EXPLOSIONRING12",
-	"S_EXPLOSIONRING13",
-	"S_EXPLOSIONRING14",
-	"S_EXPLOSIONRING15",
-	"S_EXPLOSIONRING16",
-	"S_EXPLOSIONRING17",
-	"S_EXPLOSIONRING18",
-	"S_EXPLOSIONRING19",
-	"S_EXPLOSIONRING20",
-	"S_EXPLOSIONRING21",
-	"S_EXPLOSIONRING22",
-	"S_EXPLOSIONRING23",
-	"S_EXPLOSIONRING24",
-	"S_EXPLOSIONRING25",
-	"S_EXPLOSIONRING26",
-	"S_EXPLOSIONRING27",
-	"S_EXPLOSIONRING28",
-	"S_EXPLOSIONRING29",
-	"S_EXPLOSIONRING30",
-	"S_EXPLOSIONRING31",
-	"S_EXPLOSIONRING32",
-	"S_EXPLOSIONRING33",
-	"S_EXPLOSIONRING34",
-	"S_EXPLOSIONRING35",
-
-	// Scatter Ring
-	"S_SCATTERRING1",
-	"S_SCATTERRING2",
-	"S_SCATTERRING3",
-	"S_SCATTERRING4",
-	"S_SCATTERRING5",
-	"S_SCATTERRING6",
-	"S_SCATTERRING7",
-	"S_SCATTERRING8",
-	"S_SCATTERRING9",
-	"S_SCATTERRING10",
-	"S_SCATTERRING11",
-	"S_SCATTERRING12",
-	"S_SCATTERRING13",
-	"S_SCATTERRING14",
-	"S_SCATTERRING15",
-	"S_SCATTERRING16",
-	"S_SCATTERRING17",
-	"S_SCATTERRING18",
-	"S_SCATTERRING19",
-	"S_SCATTERRING20",
-	"S_SCATTERRING21",
-	"S_SCATTERRING22",
-	"S_SCATTERRING23",
-	"S_SCATTERRING24",
-	"S_SCATTERRING25",
-	"S_SCATTERRING26",
-	"S_SCATTERRING27",
-	"S_SCATTERRING28",
-	"S_SCATTERRING29",
-	"S_SCATTERRING30",
-	"S_SCATTERRING31",
-	"S_SCATTERRING32",
-	"S_SCATTERRING33",
-	"S_SCATTERRING34",
-	"S_SCATTERRING35",
-
-	// Grenade Ring
-	"S_GRENADERING1",
-	"S_GRENADERING2",
-	"S_GRENADERING3",
-	"S_GRENADERING4",
-	"S_GRENADERING5",
-	"S_GRENADERING6",
-	"S_GRENADERING7",
-	"S_GRENADERING8",
-	"S_GRENADERING9",
-	"S_GRENADERING10",
-	"S_GRENADERING11",
-	"S_GRENADERING12",
-	"S_GRENADERING13",
-	"S_GRENADERING14",
-	"S_GRENADERING15",
-	"S_GRENADERING16",
-	"S_GRENADERING17",
-	"S_GRENADERING18",
-	"S_GRENADERING19",
-	"S_GRENADERING20",
-	"S_GRENADERING21",
-	"S_GRENADERING22",
-	"S_GRENADERING23",
-	"S_GRENADERING24",
-	"S_GRENADERING25",
-	"S_GRENADERING26",
-	"S_GRENADERING27",
-	"S_GRENADERING28",
-	"S_GRENADERING29",
-	"S_GRENADERING30",
-	"S_GRENADERING31",
-	"S_GRENADERING32",
-	"S_GRENADERING33",
-	"S_GRENADERING34",
-	"S_GRENADERING35",
+	// Weapon Ring Ammo
+	"S_BOUNCERINGAMMO",
+	"S_RAILRINGAMMO",
+	"S_INFINITYRINGAMMO",
+	"S_AUTOMATICRINGAMMO",
+	"S_EXPLOSIONRINGAMMO",
+	"S_SCATTERRINGAMMO",
+	"S_GRENADERINGAMMO",
 
 	// Weapon pickup
-	"S_BOUNCEPICKUP1",
-	"S_BOUNCEPICKUP2",
-	"S_BOUNCEPICKUP3",
-	"S_BOUNCEPICKUP4",
-	"S_BOUNCEPICKUP5",
-	"S_BOUNCEPICKUP6",
-	"S_BOUNCEPICKUP7",
-	"S_BOUNCEPICKUP8",
-	"S_BOUNCEPICKUP9",
-	"S_BOUNCEPICKUP10",
-	"S_BOUNCEPICKUP11",
-	"S_BOUNCEPICKUP12",
-	"S_BOUNCEPICKUP13",
-	"S_BOUNCEPICKUP14",
-	"S_BOUNCEPICKUP15",
-	"S_BOUNCEPICKUP16",
-
+	"S_BOUNCEPICKUP",
 	"S_BOUNCEPICKUPFADE1",
 	"S_BOUNCEPICKUPFADE2",
 	"S_BOUNCEPICKUPFADE3",
@@ -5958,23 +5620,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
 	"S_BOUNCEPICKUPFADE7",
 	"S_BOUNCEPICKUPFADE8",
 
-	"S_RAILPICKUP1",
-	"S_RAILPICKUP2",
-	"S_RAILPICKUP3",
-	"S_RAILPICKUP4",
-	"S_RAILPICKUP5",
-	"S_RAILPICKUP6",
-	"S_RAILPICKUP7",
-	"S_RAILPICKUP8",
-	"S_RAILPICKUP9",
-	"S_RAILPICKUP10",
-	"S_RAILPICKUP11",
-	"S_RAILPICKUP12",
-	"S_RAILPICKUP13",
-	"S_RAILPICKUP14",
-	"S_RAILPICKUP15",
-	"S_RAILPICKUP16",
-
+	"S_RAILPICKUP",
 	"S_RAILPICKUPFADE1",
 	"S_RAILPICKUPFADE2",
 	"S_RAILPICKUPFADE3",
@@ -5984,23 +5630,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
 	"S_RAILPICKUPFADE7",
 	"S_RAILPICKUPFADE8",
 
-	"S_AUTOPICKUP1",
-	"S_AUTOPICKUP2",
-	"S_AUTOPICKUP3",
-	"S_AUTOPICKUP4",
-	"S_AUTOPICKUP5",
-	"S_AUTOPICKUP6",
-	"S_AUTOPICKUP7",
-	"S_AUTOPICKUP8",
-	"S_AUTOPICKUP9",
-	"S_AUTOPICKUP10",
-	"S_AUTOPICKUP11",
-	"S_AUTOPICKUP12",
-	"S_AUTOPICKUP13",
-	"S_AUTOPICKUP14",
-	"S_AUTOPICKUP15",
-	"S_AUTOPICKUP16",
-
+	"S_AUTOPICKUP",
 	"S_AUTOPICKUPFADE1",
 	"S_AUTOPICKUPFADE2",
 	"S_AUTOPICKUPFADE3",
@@ -6010,23 +5640,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
 	"S_AUTOPICKUPFADE7",
 	"S_AUTOPICKUPFADE8",
 
-	"S_EXPLODEPICKUP1",
-	"S_EXPLODEPICKUP2",
-	"S_EXPLODEPICKUP3",
-	"S_EXPLODEPICKUP4",
-	"S_EXPLODEPICKUP5",
-	"S_EXPLODEPICKUP6",
-	"S_EXPLODEPICKUP7",
-	"S_EXPLODEPICKUP8",
-	"S_EXPLODEPICKUP9",
-	"S_EXPLODEPICKUP10",
-	"S_EXPLODEPICKUP11",
-	"S_EXPLODEPICKUP12",
-	"S_EXPLODEPICKUP13",
-	"S_EXPLODEPICKUP14",
-	"S_EXPLODEPICKUP15",
-	"S_EXPLODEPICKUP16",
-
+	"S_EXPLODEPICKUP",
 	"S_EXPLODEPICKUPFADE1",
 	"S_EXPLODEPICKUPFADE2",
 	"S_EXPLODEPICKUPFADE3",
@@ -6036,23 +5650,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
 	"S_EXPLODEPICKUPFADE7",
 	"S_EXPLODEPICKUPFADE8",
 
-	"S_SCATTERPICKUP1",
-	"S_SCATTERPICKUP2",
-	"S_SCATTERPICKUP3",
-	"S_SCATTERPICKUP4",
-	"S_SCATTERPICKUP5",
-	"S_SCATTERPICKUP6",
-	"S_SCATTERPICKUP7",
-	"S_SCATTERPICKUP8",
-	"S_SCATTERPICKUP9",
-	"S_SCATTERPICKUP10",
-	"S_SCATTERPICKUP11",
-	"S_SCATTERPICKUP12",
-	"S_SCATTERPICKUP13",
-	"S_SCATTERPICKUP14",
-	"S_SCATTERPICKUP15",
-	"S_SCATTERPICKUP16",
-
+	"S_SCATTERPICKUP",
 	"S_SCATTERPICKUPFADE1",
 	"S_SCATTERPICKUPFADE2",
 	"S_SCATTERPICKUPFADE3",
@@ -6062,23 +5660,7 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
 	"S_SCATTERPICKUPFADE7",
 	"S_SCATTERPICKUPFADE8",
 
-	"S_GRENADEPICKUP1",
-	"S_GRENADEPICKUP2",
-	"S_GRENADEPICKUP3",
-	"S_GRENADEPICKUP4",
-	"S_GRENADEPICKUP5",
-	"S_GRENADEPICKUP6",
-	"S_GRENADEPICKUP7",
-	"S_GRENADEPICKUP8",
-	"S_GRENADEPICKUP9",
-	"S_GRENADEPICKUP10",
-	"S_GRENADEPICKUP11",
-	"S_GRENADEPICKUP12",
-	"S_GRENADEPICKUP13",
-	"S_GRENADEPICKUP14",
-	"S_GRENADEPICKUP15",
-	"S_GRENADEPICKUP16",
-
+	"S_GRENADEPICKUP",
 	"S_GRENADEPICKUPFADE1",
 	"S_GRENADEPICKUPFADE2",
 	"S_GRENADEPICKUPFADE3",
@@ -6459,101 +6041,22 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit
 
 	"S_ROCKSPAWN",
 
-	"S_ROCKCRUMBLEA1",
-	"S_ROCKCRUMBLEA2",
-	"S_ROCKCRUMBLEA3",
-	"S_ROCKCRUMBLEA4",
-	"S_ROCKCRUMBLEA5",
-
-	"S_ROCKCRUMBLEB1",
-	"S_ROCKCRUMBLEB2",
-	"S_ROCKCRUMBLEB3",
-	"S_ROCKCRUMBLEB4",
-	"S_ROCKCRUMBLEB5",
-
-	"S_ROCKCRUMBLEC1",
-	"S_ROCKCRUMBLEC2",
-	"S_ROCKCRUMBLEC3",
-	"S_ROCKCRUMBLEC4",
-	"S_ROCKCRUMBLEC5",
-
-	"S_ROCKCRUMBLED1",
-	"S_ROCKCRUMBLED2",
-	"S_ROCKCRUMBLED3",
-	"S_ROCKCRUMBLED4",
-	"S_ROCKCRUMBLED5",
-
-	"S_ROCKCRUMBLEE1",
-	"S_ROCKCRUMBLEE2",
-	"S_ROCKCRUMBLEE3",
-	"S_ROCKCRUMBLEE4",
-	"S_ROCKCRUMBLEE5",
-
-	"S_ROCKCRUMBLEF1",
-	"S_ROCKCRUMBLEF2",
-	"S_ROCKCRUMBLEF3",
-	"S_ROCKCRUMBLEF4",
-	"S_ROCKCRUMBLEF5",
-
-	"S_ROCKCRUMBLEG1",
-	"S_ROCKCRUMBLEG2",
-	"S_ROCKCRUMBLEG3",
-	"S_ROCKCRUMBLEG4",
-	"S_ROCKCRUMBLEG5",
-
-	"S_ROCKCRUMBLEH1",
-	"S_ROCKCRUMBLEH2",
-	"S_ROCKCRUMBLEH3",
-	"S_ROCKCRUMBLEH4",
-	"S_ROCKCRUMBLEH5",
-
-	"S_ROCKCRUMBLEI1",
-	"S_ROCKCRUMBLEI2",
-	"S_ROCKCRUMBLEI3",
-	"S_ROCKCRUMBLEI4",
-	"S_ROCKCRUMBLEI5",
-
-	"S_ROCKCRUMBLEJ1",
-	"S_ROCKCRUMBLEJ2",
-	"S_ROCKCRUMBLEJ3",
-	"S_ROCKCRUMBLEJ4",
-	"S_ROCKCRUMBLEJ5",
-
-	"S_ROCKCRUMBLEK1",
-	"S_ROCKCRUMBLEK2",
-	"S_ROCKCRUMBLEK3",
-	"S_ROCKCRUMBLEK4",
-	"S_ROCKCRUMBLEK5",
-
-	"S_ROCKCRUMBLEL1",
-	"S_ROCKCRUMBLEL2",
-	"S_ROCKCRUMBLEL3",
-	"S_ROCKCRUMBLEL4",
-	"S_ROCKCRUMBLEL5",
-
-	"S_ROCKCRUMBLEM1",
-	"S_ROCKCRUMBLEM2",
-	"S_ROCKCRUMBLEM3",
-	"S_ROCKCRUMBLEM4",
-	"S_ROCKCRUMBLEM5",
-
-	"S_ROCKCRUMBLEN1",
-	"S_ROCKCRUMBLEN2",
-	"S_ROCKCRUMBLEN3",
-	"S_ROCKCRUMBLEN4",
-	"S_ROCKCRUMBLEN5",
-
-	"S_ROCKCRUMBLEO1",
-	"S_ROCKCRUMBLEO2",
-	"S_ROCKCRUMBLEO3",
-	"S_ROCKCRUMBLEO4",
-	"S_ROCKCRUMBLEO5",
-
-	"S_ROCKCRUMBLEP1",
-	"S_ROCKCRUMBLEP2",
-	"S_ROCKCRUMBLEP3",
-	"S_ROCKCRUMBLEP4",
-	"S_ROCKCRUMBLEP5",
+	"S_ROCKCRUMBLEA",
+	"S_ROCKCRUMBLEB",
+	"S_ROCKCRUMBLEC",
+	"S_ROCKCRUMBLED",
+	"S_ROCKCRUMBLEE",
+	"S_ROCKCRUMBLEF",
+	"S_ROCKCRUMBLEG",
+	"S_ROCKCRUMBLEH",
+	"S_ROCKCRUMBLEI",
+	"S_ROCKCRUMBLEJ",
+	"S_ROCKCRUMBLEK",
+	"S_ROCKCRUMBLEL",
+	"S_ROCKCRUMBLEM",
+	"S_ROCKCRUMBLEN",
+	"S_ROCKCRUMBLEO",
+	"S_ROCKCRUMBLEP",
 
 	"S_SRB1_CRAWLA1",
 	"S_SRB1_CRAWLA2",
@@ -7472,6 +6975,8 @@ struct {
 	{"PUSHACCEL",PUSHACCEL},
 	{"MODID",MODID}, // I don't know, I just thought it would be cool for a wad to potentially know what mod it was loaded into.
 	{"CODEBASE",CODEBASE}, // or what release of SRB2 this is.
+	{"VERSION",VERSION}, // Grab the game's version!
+	{"SUBVERSION",SUBVERSION}, // more precise version number
 
 	// Special linedef executor tag numbers!
 	{"LE_PINCHPHASE",LE_PINCHPHASE}, // A boss entered pinch phase (and, in most cases, is preparing their pinch phase attack!)
@@ -7484,6 +6989,7 @@ struct {
 
 	// Frame settings
 	{"FF_FRAMEMASK",FF_FRAMEMASK},
+	{"FF_ANIMATE",FF_ANIMATE},
 	{"FF_FULLBRIGHT",FF_FULLBRIGHT},
 	{"FF_TRANSMASK",FF_TRANSMASK},
 	{"FF_TRANSSHIFT",FF_TRANSSHIFT},
@@ -7958,21 +7464,45 @@ static sfxenum_t get_sfx(const char *word)
 	return sfx_None;
 }
 
-static UINT16 get_mus(const char *word)
-{ // Returns the value of SFX_ enumerations
+#ifdef MUSICSLOT_COMPATIBILITY
+static 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_
-	for (i = 0; i < NUMMUSIC; i++)
-		if (S_music[i].name && fasticmp(word, S_music[i].name))
+
+	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;
-	deh_warning("Couldn't find music named 'MUS_%s'",word);
-	return mus_None;
+
+		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
 
 static hudnum_t get_huditem(const char *word)
 { // Returns the value of HUD_ enumerations
@@ -8172,11 +7702,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);
+		r = get_mus(word, true);
 		free(word);
 		return r;
 	}
+#endif
 	else if (fastncmp("PW_",word,3)) {
 		r = get_power(word);
 		free(word);
@@ -8546,33 +8078,29 @@ static inline int lib_getenum(lua_State *L)
 		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;
-		for (i = 0; i < NUMMUSIC; i++)
-			if (S_music[i].name && fastcmp(p, S_music[i].name)) {
-				lua_pushinteger(L, i);
-				return 1;
-			}
-		return 0;
+		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;
-		for (i = 0; i < NUMMUSIC; i++)
-			if (S_music[i].name && fasticmp(p, S_music[i].name)) {
-				lua_pushinteger(L, i);
-				return 1;
-			}
-		return luaL_error(L, "music '%s' could not be found.\n", word);
+		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;
-		for (i = 0; i < NUMMUSIC; i++)
-			if (S_music[i].name && fasticmp(p, S_music[i].name)) {
-				lua_pushinteger(L, i);
-				return 1;
-			}
-		return luaL_error(L, "music '%s' could not be found.\n", word);
+		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++)
@@ -8724,8 +8252,11 @@ static inline int lib_getenum(lua_State *L)
 	} else if (fastcmp(word,"globallevelskynum")) {
 		lua_pushinteger(L, globallevelskynum);
 		return 1;
-	} else if (fastcmp(word,"mapmusic")) {
-		lua_pushinteger(L, mapmusic);
+	} else if (fastcmp(word,"mapmusname")) {
+		lua_pushstring(L, mapmusname);
+		return 1;
+	} else if (fastcmp(word,"mapmusflags")) {
+		lua_pushinteger(L, mapmusflags);
 		return 1;
 	} else if (fastcmp(word,"server")) {
 		if ((!multiplayer || !netgame) && !playeringame[serverplayer])
@@ -8743,6 +8274,9 @@ static inline int lib_getenum(lua_State *L)
 	} else if (fastcmp(word,"gravity")) {
 		lua_pushinteger(L, gravity);
 		return 1;
+	} else if (fastcmp(word,"VERSIONSTRING")) {
+		lua_pushstring(L, VERSIONSTRING);
+		return 1;
 	}
 
 	return 0;
diff --git a/src/doomdef.h b/src/doomdef.h
index 8935eb1179b866b1e105007feb44c3e261203442..0fc4a1fea7c43ee695719ed586637da082a83c41 100644
--- a/src/doomdef.h
+++ b/src/doomdef.h
@@ -490,4 +490,8 @@ extern const char *compdate, *comptime, *comprevision, *compbranch;
 /// 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
+
 #endif // __DOOMDEF__
diff --git a/src/doomstat.h b/src/doomstat.h
index 44cf6feaabc586a449c1b55ea729a5c0ec401ef2..ffdbcaecd51d9a96f72c91180218b2f91bb41dba 100644
--- a/src/doomstat.h
+++ b/src/doomstat.h
@@ -31,15 +31,11 @@
 
 // Selected by user.
 extern INT16 gamemap;
-
-// ----------------xxxxxxxxxxxxxxxx = music slot
-// -xxxxxxxxxxxxxxx---------------- = track slot
-// x------------------------------- = reset music bit
-extern UINT32 mapmusic;
-#define MUSIC_TRACKSHIFT  16
-#define MUSIC_SONGMASK    0x0000FFFF
-#define MUSIC_TRACKMASK   0x7FFF0000
-#define MUSIC_RELOADRESET 0x80000000
+extern char mapmusname[7];
+extern UINT16 mapmusflags;
+#define MUSIC_TRACKMASK   0x0FFF // ----************
+#define MUSIC_RELOADRESET 0x8000 // *---------------
+// Use other bits if necessary.
 
 extern INT16 maptol;
 extern UINT8 globalweather;
@@ -146,11 +142,13 @@ typedef struct
 	UINT16 xcoord[8];
 	UINT16 ycoord[8];
 	UINT16 picduration[8];
-	UINT16 musicslot;
 	UINT8 musicloop;
 	UINT16 textxpos;
 	UINT16 textypos;
 
+	char   musswitch[7];
+	UINT16 musswitchflags;
+
 	UINT8 fadecolor; // Color number for fade, 0 means don't do the first fade
 	UINT8 fadeinid;  // ID of the first fade, to a color -- ignored if fadecolor is 0
 	UINT8 fadeoutid; // ID of the second fade, to the new screen
@@ -218,8 +216,8 @@ typedef struct
 	UINT8 actnum;          ///< Act number or 0 for none.
 	UINT16 typeoflevel;    ///< Combination of typeoflevel flags.
 	INT16 nextlevel;       ///< Map number of next level, or 1100-1102 to end.
-	UINT16 musicslot;      ///< Music slot number to play. 0 for no music.
-	UINT16 musicslottrack; ///< Subsong to play. Only really relevant for music modules and specific formats supported by GME. 0 to ignore.
+	char musname[7];       ///< Music track to play. "" for no music.
+	UINT16 mustrack;       ///< Subsong to play. Only really relevant for music modules and specific formats supported by GME. 0 to ignore.
 	char forcecharacter[17];  ///< (SKINNAMESIZE+1) Skin to switch to or "" to disable.
 	UINT8 weather;         ///< 0 = sunny day, 1 = storm, 2 = snow, 3 = rain, 4 = blank, 5 = thunder w/o rain, 6 = rain w/o lightning, 7 = heat wave.
 	INT16 skynum;          ///< Sky number to use.
diff --git a/src/f_finale.c b/src/f_finale.c
index 44cc18ee77a812835e2473a3894d9fd0c68dbb4a..cb85cb196bdb3a1705b61b4e711d835280c6ef44 100644
--- a/src/f_finale.c
+++ b/src/f_finale.c
@@ -559,7 +559,7 @@ static void F_IntroDrawScene(void)
 				if (finalecount < 4)
 					S_StopMusic();
 				if (finalecount == 4)
-					S_ChangeMusic(mus_stjr, false);
+					S_ChangeMusicInternal("stjr", false);
 				x = (BASEVIDWIDTH<<FRACBITS)/2 - FixedMul(334<<FRACBITS, aspect)/2;
 				y = (BASEVIDHEIGHT<<FRACBITS)/2 - FixedMul(358<<FRACBITS, aspect)/2;
 				V_DrawSciencePatch(x, y, 0, (patch = W_CachePatchName("WAHH1", PU_CACHE)), aspect);
@@ -771,7 +771,7 @@ void F_IntroDrawer(void)
 				F_RunWipe(99,true);
 			}
 
-			S_ChangeMusic(mus_read_m, false);
+			S_ChangeMusicInternal("read_m", false);
 		}
 		else if (intro_scenenum == 3)
 			roidtics = BASEVIDWIDTH - 64;
@@ -977,6 +977,7 @@ static const char *credits[] = {
 	"\"Monster\" Iestyn Jealous",
 	"Ronald \"Furyhunter\" Kinard", // The SDL2 port
 	"John \"JTE\" Muniz",
+	"Ehab \"Wolfy\" Saeed",
 	"\"SSNTails\"",
 	"Matthew \"Inuyasha\" Walsh",
 	"",
@@ -1020,7 +1021,7 @@ static const char *credits[] = {
 	"\"Monster\" Iestyn Jealous",
 	"Jarel \"Arrow\" Jones",
 	"Stefan \"Stuf\" Rimalia",
-	"Shane Strife",
+	"Shane Mychal Sexton",
 	"\"Spazzo\"",
 	"David \"Big Wave Dave\" Spencer Sr.",
 	"David \"Instant Sonic\" Spencer Jr.",
@@ -1125,7 +1126,7 @@ void F_StartCredits(void)
 	CON_ClearHUD();
 	S_StopMusic();
 
-	S_ChangeMusic(mus_credit, false);
+	S_ChangeMusicInternal("credit", false);
 
 	finalecount = 0;
 	animtimer = 0;
@@ -1422,7 +1423,7 @@ void F_StartTitleScreen(void)
 
 	// IWAD dependent stuff.
 
-	S_ChangeMusic(mus_titles, looptitle);
+	S_ChangeMusicInternal("titles", looptitle);
 
 	animtimer = 0;
 
@@ -1588,7 +1589,7 @@ void F_StartContinue(void)
 	// In case menus are still up?!!
 	M_ClearMenus(true);
 
-	S_ChangeMusic(mus_contsc, false);
+	S_ChangeMusicInternal("contsc", false);
 	S_StopSounds();
 
 	timetonext = TICRATE*11;
@@ -1702,8 +1703,10 @@ static void F_AdvanceToNextScene(void)
 	picxpos = cutscenes[cutnum]->scene[scenenum].xcoord[picnum];
 	picypos = cutscenes[cutnum]->scene[scenenum].ycoord[picnum];
 
-	if (cutscenes[cutnum]->scene[scenenum].musicslot != 0)
-		S_ChangeMusic(cutscenes[cutnum]->scene[scenenum].musicslot, cutscenes[cutnum]->scene[scenenum].musicloop);
+	if (cutscenes[cutnum]->scene[scenenum].musswitch[0])
+		S_ChangeMusic(cutscenes[cutnum]->scene[scenenum].musswitch,
+			cutscenes[cutnum]->scene[scenenum].musswitchflags,
+			cutscenes[cutnum]->scene[scenenum].musicloop);
 
 	// Fade to the next
 	dofadenow = true;
@@ -1774,8 +1777,10 @@ void F_StartCustomCutscene(INT32 cutscenenum, boolean precutscene, boolean reset
 	animtimer = cutscenes[cutnum]->scene[0].picduration[0]; // Picture duration
 	stoptimer = 0;
 
-	if (cutscenes[cutnum]->scene[scenenum].musicslot != 0)
-		S_ChangeMusic(cutscenes[cutnum]->scene[scenenum].musicslot, cutscenes[cutnum]->scene[scenenum].musicloop);
+	if (cutscenes[cutnum]->scene[0].musswitch[0])
+		S_ChangeMusic(cutscenes[cutnum]->scene[0].musswitch,
+			cutscenes[cutnum]->scene[0].musswitchflags,
+			cutscenes[cutnum]->scene[0].musicloop);
 	else
 		S_StopMusic();
 }
diff --git a/src/f_finale.h b/src/f_finale.h
index 97a26f4c411776a135ca228a0d8d6bf2463960bf..e263a37973178c8fceedcd26a1807cefd07d6c11 100644
--- a/src/f_finale.h
+++ b/src/f_finale.h
@@ -90,6 +90,7 @@ enum
 	// custom intermissions
 	wipe_specinter_toblack,
 	wipe_multinter_toblack,
+	wipe_speclevel_towhite,
 
 	wipe_level_final,
 	wipe_intermission_final,
@@ -108,7 +109,7 @@ enum
 
 	NUMWIPEDEFS
 };
-#define WIPEFINALSHIFT 12
+#define WIPEFINALSHIFT 13
 extern UINT8 wipedefs[NUMWIPEDEFS];
 
 #endif
diff --git a/src/f_wipe.c b/src/f_wipe.c
index 6f14e577aa13133806b0919293a3a18121240392..e0578949e341a05178167b2e3996fff04c2ce43a 100644
--- a/src/f_wipe.c
+++ b/src/f_wipe.c
@@ -58,6 +58,7 @@ UINT8 wipedefs[NUMWIPEDEFS] = {
 
 	0,  // wipe_specinter_toblack
 	0,  // wipe_multinter_toblack
+	0,  // wipe_speclevel_towhite
 
 	0,  // wipe_level_final
 	0,  // wipe_intermission_final
diff --git a/src/g_game.c b/src/g_game.c
index 72cfe4a57727dcc3adb9e086dff0a49b3b0657d1..3b7ef158f3748eec3b3ceff6985f2a84cf786ce5 100644
--- a/src/g_game.c
+++ b/src/g_game.c
@@ -69,8 +69,10 @@ static void G_DoStartContinue(void);
 static void G_DoContinued(void);
 static void G_DoWorldDone(void);
 
+char   mapmusname[7]; // Music name
+UINT16 mapmusflags; // Track and reset bit
+
 INT16 gamemap = 1;
-UINT32 mapmusic; // music, track, and reset bit
 INT16 maptol;
 UINT8 globalweather = 0;
 INT32 curWeather = PRECIP_NONE;
@@ -2182,12 +2184,13 @@ void G_PlayerReborn(INT32 player)
 
 	if (p-players == consoleplayer)
 	{
-		if (mapmusic & MUSIC_RELOADRESET) // TODO: Might not need this here
+		if (mapmusflags & MUSIC_RELOADRESET)
 		{
-			mapmusic = mapheaderinfo[gamemap-1]->musicslot
-				| (mapheaderinfo[gamemap-1]->musicslottrack << MUSIC_TRACKSHIFT);
+			strncpy(mapmusname, mapheaderinfo[gamemap-1]->musname, 7);
+			mapmusname[6] = 0;
+			mapmusflags = mapheaderinfo[gamemap-1]->mustrack & MUSIC_TRACKMASK;
 		}
-		S_ChangeMusic(mapmusic, true);
+		S_ChangeMusic(mapmusname, mapmusflags, true);
 	}
 
 	if (gametype == GT_COOP)
@@ -2328,6 +2331,11 @@ void G_SpawnPlayer(INT32 playernum, boolean starpost)
 		}
 	}
 	P_MovePlayerToSpawn(playernum, spawnpoint);
+	
+#ifdef HAVE_BLUA 
+	LUAh_PlayerSpawn(&players[playernum]); // Lua hook for player spawning :)
+#endif
+
 }
 
 mapthing_t *G_FindCTFStart(INT32 playernum)
@@ -2871,7 +2879,8 @@ static void G_DoCompleted(void)
 
 	// We are committed to this map now.
 	// We may as well allocate its header if it doesn't exist
-	if(!mapheaderinfo[nextmap])
+	// (That is, if it's a real map)
+	if (nextmap < NUMMAPS && !mapheaderinfo[nextmap])
 		P_AllocMapHeader(nextmap);
 
 	if (skipstats)
@@ -3521,7 +3530,7 @@ void G_InitNew(UINT8 pultmode, const char *mapname, boolean resetplayer, boolean
 	if (paused)
 	{
 		paused = false;
-		S_ResumeSound();
+		S_ResumeAudio();
 	}
 
 	if (netgame || multiplayer) // Nice try, haxor.
@@ -3595,7 +3604,7 @@ void G_InitNew(UINT8 pultmode, const char *mapname, boolean resetplayer, boolean
 	globalweather = mapheaderinfo[gamemap-1]->weather;
 
 	// Don't carry over custom music change to another map.
-	mapmusic |= MUSIC_RELOADRESET;
+	mapmusflags |= MUSIC_RELOADRESET;
 
 	ultimatemode = pultmode;
 	playerdeadview = false;
@@ -4326,10 +4335,8 @@ void G_GhostTicker(void)
 		switch(g->color)
 		{
 		case GHC_SUPER: // Super Sonic (P_DoSuperStuff)
-			if (leveltime % 9 < 5)
-				g->mo->color = SKINCOLOR_SUPER1 + leveltime % 9;
-			else
-				g->mo->color = SKINCOLOR_SUPER1 + 9 - leveltime % 9;
+			g->mo->color = SKINCOLOR_SUPER1;
+			g->mo->color += abs( ( ( leveltime >> 1 ) % 9) - 4);
 			break;
 		case GHC_INVINCIBLE: // Mario invincibility (P_CheckInvincibilityTimer)
 			g->mo->color = (UINT8)(leveltime % MAXSKINCOLORS);
diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c
index 6a315d88171b61b50371c89731a6d3a2d6b2879e..0754ef0b38f20de91cf4e4faf21422ba79115ddb 100644
--- a/src/hardware/hw_md2.c
+++ b/src/hardware/hw_md2.c
@@ -1503,16 +1503,37 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
 			HWR_GetMappedPatch(gpatch, spr->colormap);
 		}
 
+		if (spr->mobj->frame & FF_ANIMATE)
+		{
+			// set duration and tics to be the correct values for FF_ANIMATE states
+			durs = spr->mobj->state->var2;
+			tics = spr->mobj->anim_duration;
+		}
+
 		//FIXME: this is not yet correct
 		frame = (spr->mobj->frame & FF_FRAMEMASK) % md2->model->header.numFrames;
 		buff = md2->model->glCommandBuffer;
 		curr = &md2->model->frames[frame];
-		if (cv_grmd2.value == 1
-		    && spr->mobj->state->nextstate != S_NULL && states[spr->mobj->state->nextstate].sprite != SPR_NULL
-		    && !(spr->mobj->player && (spr->mobj->state->nextstate == S_PLAY_TAP1 || spr->mobj->state->nextstate == S_PLAY_TAP2) && spr->mobj->state == &states[S_PLAY_STND]))
+		if (cv_grmd2.value == 1)
 		{
-			const INT32 nextframe = (states[spr->mobj->state->nextstate].frame & FF_FRAMEMASK) % md2->model->header.numFrames;
-			next = &md2->model->frames[nextframe];
+			// frames are handled differently for states with FF_ANIMATE, so get the next frame differently for the interpolation
+			if (spr->mobj->frame & FF_ANIMATE)
+			{
+				UINT32 nextframe = (spr->mobj->frame & FF_FRAMEMASK) + 1;
+				if (nextframe >= (UINT32)spr->mobj->state->var1)
+					nextframe = (spr->mobj->state->frame & FF_FRAMEMASK);
+				nextframe %= md2->model->header.numFrames;
+				next = &md2->model->frames[nextframe];
+			}
+			else
+			{
+				if (spr->mobj->state->nextstate != S_NULL && states[spr->mobj->state->nextstate].sprite != SPR_NULL
+					&& !(spr->mobj->player && (spr->mobj->state->nextstate == S_PLAY_TAP1 || spr->mobj->state->nextstate == S_PLAY_TAP2) && spr->mobj->state == &states[S_PLAY_STND]))
+				{
+					const UINT32 nextframe = (states[spr->mobj->state->nextstate].frame & FF_FRAMEMASK) % md2->model->header.numFrames;
+					next = &md2->model->frames[nextframe];
+				}
+			}
 		}
 
 		//Hurdler: it seems there is still a small problem with mobj angle
diff --git a/src/info.c b/src/info.c
index cc07ae3f29f8dbf3baf67c8108fae29e84207d83..fb19fa2b43113e5f5e5747e654c38b205ef1a5d9 100644
--- a/src/info.c
+++ b/src/info.c
@@ -60,6 +60,7 @@ char sprnames[NUMSPRITES + 1][5] =
 state_t states[NUMSTATES] =
 {
 	// frame is masked through FF_FRAMEMASK
+	// FF_ANIMATE (0x4000) makes simple state animations (var1 #frames, var2 tic delay)
 	// FF_FULLBRIGHT (0x8000) activates the fullbright colormap
 	// use FF_TRANS10 - FF_TRANS90 for easy translucency
 	// (or tr_trans10<<FF_TRANSSHIFT if you want to make it hard on yourself)
@@ -924,30 +925,7 @@ state_t states[NUMSTATES] =
 	{SPR_MSCF, FF_FULLBRIGHT|FF_TRANS30|11, 1, {NULL}, 0, 0, S_MSSHIELD_F1},  // S_MSSHIELD_F12
 
 	// Ring
-	{SPR_RING,  0, 1, {NULL}, 0, 0, S_RING2},  // S_RING1
-	{SPR_RING,  1, 1, {NULL}, 0, 0, S_RING3},  // S_RING2
-	{SPR_RING,  2, 1, {NULL}, 0, 0, S_RING4},  // S_RING3
-	{SPR_RING,  3, 1, {NULL}, 0, 0, S_RING5},  // S_RING4
-	{SPR_RING,  4, 1, {NULL}, 0, 0, S_RING6},  // S_RING5
-	{SPR_RING,  5, 1, {NULL}, 0, 0, S_RING7},  // S_RING6
-	{SPR_RING,  6, 1, {NULL}, 0, 0, S_RING8},  // S_RING7
-	{SPR_RING,  7, 1, {NULL}, 0, 0, S_RING9},  // S_RING8
-	{SPR_RING,  8, 1, {NULL}, 0, 0, S_RING10}, // S_RING9
-	{SPR_RING,  9, 1, {NULL}, 0, 0, S_RING11}, // S_RING10
-	{SPR_RING, 10, 1, {NULL}, 0, 0, S_RING12}, // S_RING11
-	{SPR_RING, 11, 1, {NULL}, 0, 0, S_RING13}, // S_RING12
-	{SPR_RING, 12, 1, {NULL}, 0, 0, S_RING14}, // S_RING13
-	{SPR_RING, 13, 1, {NULL}, 0, 0, S_RING15}, // S_RING14
-	{SPR_RING, 14, 1, {NULL}, 0, 0, S_RING16}, // S_RING15
-	{SPR_RING, 15, 1, {NULL}, 0, 0, S_RING17}, // S_RING16
-	{SPR_RING, 16, 1, {NULL}, 0, 0, S_RING18}, // S_RING17
-	{SPR_RING, 17, 1, {NULL}, 0, 0, S_RING19}, // S_RING18
-	{SPR_RING, 18, 1, {NULL}, 0, 0, S_RING20}, // S_RING19
-	{SPR_RING, 19, 1, {NULL}, 0, 0, S_RING21}, // S_RING20
-	{SPR_RING, 20, 1, {NULL}, 0, 0, S_RING22}, // S_RING21
-	{SPR_RING, 21, 1, {NULL}, 0, 0, S_RING23}, // S_RING22
-	{SPR_RING, 22, 1, {NULL}, 0, 0, S_RING24}, // S_RING23
-	{SPR_RING, 23, 1, {NULL}, 0, 0, S_RING1},  // S_RING24
+	{SPR_RING, FF_ANIMATE, -1, {NULL}, 23, 1, S_RING}, // S_RING
 
 	// Blue Sphere Replacement for special stages
 	{SPR_BBAL, 0, -1, {NULL}, 0, 0, S_NULL}, // S_BLUEBALL
@@ -963,39 +941,10 @@ state_t states[NUMSTATES] =
 	{SPR_GWLR, 2, 1, {NULL}, 0, 0, S_GRAVWELLRED},    // S_GRAVWELLRED3
 
 	// Individual Team Rings (now with shield attracting action! =P)
-	{SPR_TRNG,  0, 1, {NULL}, 0, 0, S_TEAMRING2},  // S_TEAMRING1
-	{SPR_TRNG,  1, 1, {NULL}, 0, 0, S_TEAMRING3},  // S_TEAMRING2
-	{SPR_TRNG,  2, 1, {NULL}, 0, 0, S_TEAMRING4},  // S_TEAMRING3
-	{SPR_TRNG,  3, 1, {NULL}, 0, 0, S_TEAMRING5},  // S_TEAMRING4
-	{SPR_TRNG,  4, 1, {NULL}, 0, 0, S_TEAMRING6},  // S_TEAMRING5
-	{SPR_TRNG,  5, 1, {NULL}, 0, 0, S_TEAMRING7},  // S_TEAMRING6
-	{SPR_TRNG,  6, 1, {NULL}, 0, 0, S_TEAMRING8},  // S_TEAMRING7
-	{SPR_TRNG,  7, 1, {NULL}, 0, 0, S_TEAMRING9},  // S_TEAMRING8
-	{SPR_TRNG,  8, 1, {NULL}, 0, 0, S_TEAMRING10}, // S_TEAMRING9
-	{SPR_TRNG,  9, 1, {NULL}, 0, 0, S_TEAMRING11}, // S_TEAMRING10
-	{SPR_TRNG, 10, 1, {NULL}, 0, 0, S_TEAMRING12}, // S_TEAMRING11
-	{SPR_TRNG, 11, 1, {NULL}, 0, 0, S_TEAMRING13}, // S_TEAMRING12
-	{SPR_TRNG, 12, 1, {NULL}, 0, 0, S_TEAMRING14}, // S_TEAMRING13
-	{SPR_TRNG, 13, 1, {NULL}, 0, 0, S_TEAMRING15}, // S_TEAMRING14
-	{SPR_TRNG, 14, 1, {NULL}, 0, 0, S_TEAMRING16}, // S_TEAMRING15
-	{SPR_TRNG, 15, 1, {NULL}, 0, 0, S_TEAMRING17}, // S_TEAMRING16
-	{SPR_TRNG, 16, 1, {NULL}, 0, 0, S_TEAMRING18}, // S_TEAMRING17
-	{SPR_TRNG, 17, 1, {NULL}, 0, 0, S_TEAMRING19}, // S_TEAMRING18
-	{SPR_TRNG, 18, 1, {NULL}, 0, 0, S_TEAMRING20}, // S_TEAMRING19
-	{SPR_TRNG, 19, 1, {NULL}, 0, 0, S_TEAMRING21}, // S_TEAMRING20
-	{SPR_TRNG, 20, 1, {NULL}, 0, 0, S_TEAMRING22}, // S_TEAMRING21
-	{SPR_TRNG, 21, 1, {NULL}, 0, 0, S_TEAMRING23}, // S_TEAMRING22
-	{SPR_TRNG, 22, 1, {NULL}, 0, 0, S_TEAMRING24}, // S_TEAMRING23
-	{SPR_TRNG, 23, 1, {NULL}, 0, 0, S_TEAMRING1},  // S_TEAMRING24
+	{SPR_TRNG, FF_ANIMATE, -1, {NULL}, 23, 1, S_TEAMRING},  // S_TEAMRING1
 
 	// Special Stage Token
-	{SPR_EMMY, FF_FULLBRIGHT,   2, {NULL}, 0, 0, S_EMMY2}, // S_EMMY1
-	{SPR_EMMY, FF_FULLBRIGHT|1, 2, {NULL}, 0, 0, S_EMMY3}, // S_EMMY2
-	{SPR_EMMY, FF_FULLBRIGHT|2, 2, {NULL}, 0, 0, S_EMMY4}, // S_EMMY3
-	{SPR_EMMY, FF_FULLBRIGHT|3, 2, {NULL}, 0, 0, S_EMMY5}, // S_EMMY4
-	{SPR_EMMY, FF_FULLBRIGHT|4, 2, {NULL}, 0, 0, S_EMMY6}, // S_EMMY5
-	{SPR_EMMY, FF_FULLBRIGHT|5, 2, {NULL}, 0, 0, S_EMMY7}, // S_EMMY6
-	{SPR_EMMY, FF_FULLBRIGHT|6, 2, {NULL}, 0, 0, S_EMMY1}, // S_EMMY7
+	{SPR_EMMY, FF_ANIMATE|FF_FULLBRIGHT, -1, {NULL}, 6, 2, S_EMMY}, // S_EMMY
 
 	// Special Stage Token
 	{SPR_TOKE, FF_TRANS50|FF_FULLBRIGHT, -1, {NULL}, 0, 0, S_NULL}, // S_TOKEN
@@ -1150,40 +1099,9 @@ state_t states[NUMSTATES] =
 	{SPR_USPK, 2,-1, {NULL}, 0, 0, S_NULL}, // S_SPIKED2
 
 	// Starpost
-	{SPR_STPT, 0, -1, {NULL}, 0, 0, S_NULL},       // S_STARPOST1
-	{SPR_STPT, 0, 2, {NULL}, 0, 0, S_STARPOST3},   // S_STARPOST2
-	{SPR_STPT, 1, 2, {NULL}, 0, 0, S_STARPOST2},   // S_STARPOST3
-	{SPR_STPT, 2, 1, {NULL}, 0, 0, S_STARPOST5},   // S_STARPOST4
-	{SPR_STPT, 3, 1, {NULL}, 0, 0, S_STARPOST6},   // S_STARPOST5
-	{SPR_STPT, 4, 1, {NULL}, 0, 0, S_STARPOST7},   // S_STARPOST6
-	{SPR_STPT, 5, 1, {NULL}, 0, 0, S_STARPOST8},   // S_STARPOST7
-	{SPR_STPT, 6, 1, {NULL}, 0, 0, S_STARPOST9},   // S_STARPOST8
-	{SPR_STPT, 7, 1, {NULL}, 0, 0, S_STARPOST10},  // S_STARPOST9
-	{SPR_STPT, 8, 1, {NULL}, 0, 0, S_STARPOST11},  // S_STARPOST10
-	{SPR_STPT, 9, 1, {NULL}, 0, 0, S_STARPOST12},  // S_STARPOST11
-	{SPR_STPT, 10, 1, {NULL}, 0, 0, S_STARPOST13}, // S_STARPOST12
-	{SPR_STPT, 11, 1, {NULL}, 0, 0, S_STARPOST14}, // S_STARPOST13
-	{SPR_STPT, 12, 1, {NULL}, 0, 0, S_STARPOST15}, // S_STARPOST14
-	{SPR_STPT, 13, 1, {NULL}, 0, 0, S_STARPOST16}, // S_STARPOST15
-	{SPR_STPT, 14, 1, {NULL}, 0, 0, S_STARPOST17}, // S_STARPOST16
-	{SPR_STPT, 15, 1, {NULL}, 0, 0, S_STARPOST18}, // S_STARPOST17
-	{SPR_STPT, 16, 1, {NULL}, 0, 0, S_STARPOST19}, // S_STARPOST18
-	{SPR_STPT, 0, 1, {NULL}, 0, 0, S_STARPOST20},  // S_STARPOST19
-	{SPR_STPT, 2, 1, {NULL}, 0, 0, S_STARPOST21},  // S_STARPOST20
-	{SPR_STPT, 3, 1, {NULL}, 0, 0, S_STARPOST22},  // S_STARPOST21
-	{SPR_STPT, 4, 1, {NULL}, 0, 0, S_STARPOST23},  // S_STARPOST22
-	{SPR_STPT, 5, 1, {NULL}, 0, 0, S_STARPOST24},  // S_STARPOST23
-	{SPR_STPT, 6, 1, {NULL}, 0, 0, S_STARPOST25},  // S_STARPOST24
-	{SPR_STPT, 7, 1, {NULL}, 0, 0, S_STARPOST26},  // S_STARPOST25
-	{SPR_STPT, 8, 1, {NULL}, 0, 0, S_STARPOST27},  // S_STARPOST26
-	{SPR_STPT, 9, 1, {NULL}, 0, 0, S_STARPOST28},  // S_STARPOST27
-	{SPR_STPT, 10, 1, {NULL}, 0, 0, S_STARPOST29}, // S_STARPOST28
-	{SPR_STPT, 11, 1, {NULL}, 0, 0, S_STARPOST30}, // S_STARPOST29
-	{SPR_STPT, 12, 1, {NULL}, 0, 0, S_STARPOST31}, // S_STARPOST30
-	{SPR_STPT, 13, 1, {NULL}, 0, 0, S_STARPOST32}, // S_STARPOST31
-	{SPR_STPT, 14, 1, {NULL}, 0, 0, S_STARPOST33}, // S_STARPOST32
-	{SPR_STPT, 15, 1, {NULL}, 0, 0, S_STARPOST34}, // S_STARPOST33
-	{SPR_STPT, 16, 1, {NULL}, 0, 0, S_STARPOST2},  // S_STARPOST34
+	{SPR_STPT, 0           , -1, {NULL},  0, 0, S_NULL},           // S_STARPOST_IDLE
+	{SPR_STPT, FF_ANIMATE  , -1, {NULL},  1, 2, S_NULL},           // S_STARPOST_FLASH
+	{SPR_STPT, FF_ANIMATE|2, 31, {NULL}, 15, 1, S_STARPOST_FLASH}, // S_STARPOST_SPIN
 
 	// Big floating mine
 	{SPR_BMNE, 0, 5, {NULL}, 0, 0, S_BIGMINE2},    // S_BIGMINE1
@@ -1801,38 +1719,7 @@ state_t states[NUMSTATES] =
 	{SPR_PITY, FF_TRANS20|5, 1, {NULL}, 0, 0, S_PITY1 }, // S_PITY10
 
 	// Invincibility Sparkles
-	{SPR_IVSP, 0, 1, {NULL}, 0, 0, S_IVSP2},   // S_IVSP1
-	{SPR_IVSP, 1, 1, {NULL}, 0, 0, S_IVSP3},   // S_IVSP2
-	{SPR_IVSP, 2, 1, {NULL}, 0, 0, S_IVSP4},   // S_IVSP3
-	{SPR_IVSP, 3, 1, {NULL}, 0, 0, S_IVSP5},   // S_IVSP4
-	{SPR_IVSP, 4, 1, {NULL}, 0, 0, S_IVSP6},   // S_IVSP5
-	{SPR_IVSP, 5, 1, {NULL}, 0, 0, S_IVSP7},   // S_IVSP6
-	{SPR_IVSP, 6, 1, {NULL}, 0, 0, S_IVSP8},   // S_IVSP7
-	{SPR_IVSP, 7, 1, {NULL}, 0, 0, S_IVSP9},   // S_IVSP8
-	{SPR_IVSP, 8, 1, {NULL}, 0, 0, S_IVSP10},  // S_IVSP9
-	{SPR_IVSP, 9, 1, {NULL}, 0, 0, S_IVSP11},  // S_IVSP10
-	{SPR_IVSP, 10, 1, {NULL}, 0, 0, S_IVSP12}, // S_IVSP11
-	{SPR_IVSP, 11, 1, {NULL}, 0, 0, S_IVSP13}, // S_IVSP12
-	{SPR_IVSP, 12, 1, {NULL}, 0, 0, S_IVSP14}, // S_IVSP13
-	{SPR_IVSP, 13, 1, {NULL}, 0, 0, S_IVSP15}, // S_IVSP14
-	{SPR_IVSP, 14, 1, {NULL}, 0, 0, S_IVSP16}, // S_IVSP15
-	{SPR_IVSP, 15, 1, {NULL}, 0, 0, S_IVSP17}, // S_IVSP16
-	{SPR_IVSP, 16, 1, {NULL}, 0, 0, S_IVSP18}, // S_IVSP17
-	{SPR_IVSP, 17, 1, {NULL}, 0, 0, S_IVSP19}, // S_IVSP18
-	{SPR_IVSP, 18, 1, {NULL}, 0, 0, S_IVSP20}, // S_IVSP19
-	{SPR_IVSP, 19, 1, {NULL}, 0, 0, S_IVSP21}, // S_IVSP20
-	{SPR_IVSP, 20, 1, {NULL}, 0, 0, S_IVSP22}, // S_IVSP21
-	{SPR_IVSP, 21, 1, {NULL}, 0, 0, S_IVSP23}, // S_IVSP22
-	{SPR_IVSP, 22, 1, {NULL}, 0, 0, S_IVSP24}, // S_IVSP23
-	{SPR_IVSP, 23, 1, {NULL}, 0, 0, S_IVSP25}, // S_IVSP24
-	{SPR_IVSP, 24, 1, {NULL}, 0, 0, S_IVSP26}, // S_IVSP25
-	{SPR_IVSP, 25, 1, {NULL}, 0, 0, S_IVSP27}, // S_IVSP26
-	{SPR_IVSP, 26, 1, {NULL}, 0, 0, S_IVSP28}, // S_IVSP27
-	{SPR_IVSP, 27, 1, {NULL}, 0, 0, S_IVSP29}, // S_IVSP28
-	{SPR_IVSP, 28, 1, {NULL}, 0, 0, S_IVSP30}, // S_IVSP29
-	{SPR_IVSP, 29, 1, {NULL}, 0, 0, S_IVSP31}, // S_IVSP30
-	{SPR_IVSP, 30, 1, {NULL}, 0, 0, S_IVSP32}, // S_IVSP31
-	{SPR_IVSP, 31, 1, {NULL}, 0, 0, S_NULL},   // S_IVSP32
+	{SPR_IVSP, FF_ANIMATE, 32, {NULL}, 31, 1, S_NULL},   // S_IVSP
 
 	// Super Sonic Spark
 	{SPR_SSPK, 0, 2, {NULL}, 0, 0, S_SSPK2}, // S_SSPK1
@@ -2024,284 +1911,18 @@ state_t states[NUMSTATES] =
 	{SPR_RRNG, FF_FULLBRIGHT|5, 1, {A_ThrownRing}, 0, 0, S_RRNG7}, // S_RRNG6
 	{SPR_RRNG, FF_FULLBRIGHT|6, 1, {A_ThrownRing}, 0, 0, S_RRNG1}, // S_RRNG7
 
-	// Bounce Ring
-	{SPR_RNGB, 0, 1, {NULL}, 0, 0, S_BOUNCERING2},   // S_BOUNCERING1
-	{SPR_RNGB, 1, 1, {NULL}, 0, 0, S_BOUNCERING3},   // S_BOUNCERING2
-	{SPR_RNGB, 2, 1, {NULL}, 0, 0, S_BOUNCERING4},   // S_BOUNCERING3
-	{SPR_RNGB, 3, 1, {NULL}, 0, 0, S_BOUNCERING5},   // S_BOUNCERING4
-	{SPR_RNGB, 4, 1, {NULL}, 0, 0, S_BOUNCERING6},   // S_BOUNCERING5
-	{SPR_RNGB, 5, 1, {NULL}, 0, 0, S_BOUNCERING7},   // S_BOUNCERING6
-	{SPR_RNGB, 6, 1, {NULL}, 0, 0, S_BOUNCERING8},   // S_BOUNCERING7
-	{SPR_RNGB, 7, 1, {NULL}, 0, 0, S_BOUNCERING9},   // S_BOUNCERING8
-	{SPR_RNGB, 8, 1, {NULL}, 0, 0, S_BOUNCERING10},  // S_BOUNCERING9
-	{SPR_RNGB, 9, 1, {NULL}, 0, 0, S_BOUNCERING11},  // S_BOUNCERING10
-	{SPR_RNGB, 10, 1, {NULL}, 0, 0, S_BOUNCERING12}, // S_BOUNCERING11
-	{SPR_RNGB, 11, 1, {NULL}, 0, 0, S_BOUNCERING13}, // S_BOUNCERING12
-	{SPR_RNGB, 12, 1, {NULL}, 0, 0, S_BOUNCERING14}, // S_BOUNCERING13
-	{SPR_RNGB, 13, 1, {NULL}, 0, 0, S_BOUNCERING15}, // S_BOUNCERING14
-	{SPR_RNGB, 14, 1, {NULL}, 0, 0, S_BOUNCERING16}, // S_BOUNCERING15
-	{SPR_RNGB, 15, 1, {NULL}, 0, 0, S_BOUNCERING17}, // S_BOUNCERING16
-	{SPR_RNGB, 16, 1, {NULL}, 0, 0, S_BOUNCERING18}, // S_BOUNCERING17
-	{SPR_RNGB, 17, 1, {NULL}, 0, 0, S_BOUNCERING19}, // S_BOUNCERING18
-	{SPR_RNGB, 18, 1, {NULL}, 0, 0, S_BOUNCERING20}, // S_BOUNCERING19
-	{SPR_RNGB, 19, 1, {NULL}, 0, 0, S_BOUNCERING21}, // S_BOUNCERING20
-	{SPR_RNGB, 20, 1, {NULL}, 0, 0, S_BOUNCERING22}, // S_BOUNCERING21
-	{SPR_RNGB, 21, 1, {NULL}, 0, 0, S_BOUNCERING23}, // S_BOUNCERING22
-	{SPR_RNGB, 22, 1, {NULL}, 0, 0, S_BOUNCERING24}, // S_BOUNCERING23
-	{SPR_RNGB, 23, 1, {NULL}, 0, 0, S_BOUNCERING25}, // S_BOUNCERING24
-	{SPR_RNGB, 24, 1, {NULL}, 0, 0, S_BOUNCERING26}, // S_BOUNCERING25
-	{SPR_RNGB, 25, 1, {NULL}, 0, 0, S_BOUNCERING27}, // S_BOUNCERING26
-	{SPR_RNGB, 26, 1, {NULL}, 0, 0, S_BOUNCERING28}, // S_BOUNCERING27
-	{SPR_RNGB, 27, 1, {NULL}, 0, 0, S_BOUNCERING29}, // S_BOUNCERING28
-	{SPR_RNGB, 28, 1, {NULL}, 0, 0, S_BOUNCERING30}, // S_BOUNCERING29
-	{SPR_RNGB, 29, 1, {NULL}, 0, 0, S_BOUNCERING31}, // S_BOUNCERING30
-	{SPR_RNGB, 30, 1, {NULL}, 0, 0, S_BOUNCERING32}, // S_BOUNCERING31
-	{SPR_RNGB, 31, 1, {NULL}, 0, 0, S_BOUNCERING33}, // S_BOUNCERING32
-	{SPR_RNGB, 32, 1, {NULL}, 0, 0, S_BOUNCERING34}, // S_BOUNCERING33
-	{SPR_RNGB, 33, 1, {NULL}, 0, 0, S_BOUNCERING35}, // S_BOUNCERING34
-	{SPR_RNGB, 34, 1, {NULL}, 0, 0, S_BOUNCERING1},  // S_BOUNCERING35
-
-	// Rail Ring
-	{SPR_RNGR, 0, 1, {NULL}, 0, 0, S_RAILRING2},   // S_RAILRING1
-	{SPR_RNGR, 1, 1, {NULL}, 0, 0, S_RAILRING3},   // S_RAILRING2
-	{SPR_RNGR, 2, 1, {NULL}, 0, 0, S_RAILRING4},   // S_RAILRING3
-	{SPR_RNGR, 3, 1, {NULL}, 0, 0, S_RAILRING5},   // S_RAILRING4
-	{SPR_RNGR, 4, 1, {NULL}, 0, 0, S_RAILRING6},   // S_RAILRING5
-	{SPR_RNGR, 5, 1, {NULL}, 0, 0, S_RAILRING7},   // S_RAILRING6
-	{SPR_RNGR, 6, 1, {NULL}, 0, 0, S_RAILRING8},   // S_RAILRING7
-	{SPR_RNGR, 7, 1, {NULL}, 0, 0, S_RAILRING9},   // S_RAILRING8
-	{SPR_RNGR, 8, 1, {NULL}, 0, 0, S_RAILRING10},  // S_RAILRING9
-	{SPR_RNGR, 9, 1, {NULL}, 0, 0, S_RAILRING11},  // S_RAILRING10
-	{SPR_RNGR, 10, 1, {NULL}, 0, 0, S_RAILRING12}, // S_RAILRING11
-	{SPR_RNGR, 11, 1, {NULL}, 0, 0, S_RAILRING13}, // S_RAILRING12
-	{SPR_RNGR, 12, 1, {NULL}, 0, 0, S_RAILRING14}, // S_RAILRING13
-	{SPR_RNGR, 13, 1, {NULL}, 0, 0, S_RAILRING15}, // S_RAILRING14
-	{SPR_RNGR, 14, 1, {NULL}, 0, 0, S_RAILRING16}, // S_RAILRING15
-	{SPR_RNGR, 15, 1, {NULL}, 0, 0, S_RAILRING17}, // S_RAILRING16
-	{SPR_RNGR, 16, 1, {NULL}, 0, 0, S_RAILRING18}, // S_RAILRING17
-	{SPR_RNGR, 17, 1, {NULL}, 0, 0, S_RAILRING19}, // S_RAILRING18
-	{SPR_RNGR, 18, 1, {NULL}, 0, 0, S_RAILRING20}, // S_RAILRING19
-	{SPR_RNGR, 19, 1, {NULL}, 0, 0, S_RAILRING21}, // S_RAILRING20
-	{SPR_RNGR, 20, 1, {NULL}, 0, 0, S_RAILRING22}, // S_RAILRING21
-	{SPR_RNGR, 21, 1, {NULL}, 0, 0, S_RAILRING23}, // S_RAILRING22
-	{SPR_RNGR, 22, 1, {NULL}, 0, 0, S_RAILRING24}, // S_RAILRING23
-	{SPR_RNGR, 23, 1, {NULL}, 0, 0, S_RAILRING25}, // S_RAILRING24
-	{SPR_RNGR, 24, 1, {NULL}, 0, 0, S_RAILRING26}, // S_RAILRING25
-	{SPR_RNGR, 25, 1, {NULL}, 0, 0, S_RAILRING27}, // S_RAILRING26
-	{SPR_RNGR, 26, 1, {NULL}, 0, 0, S_RAILRING28}, // S_RAILRING27
-	{SPR_RNGR, 27, 1, {NULL}, 0, 0, S_RAILRING29}, // S_RAILRING28
-	{SPR_RNGR, 28, 1, {NULL}, 0, 0, S_RAILRING30}, // S_RAILRING29
-	{SPR_RNGR, 29, 1, {NULL}, 0, 0, S_RAILRING31}, // S_RAILRING30
-	{SPR_RNGR, 30, 1, {NULL}, 0, 0, S_RAILRING32}, // S_RAILRING31
-	{SPR_RNGR, 31, 1, {NULL}, 0, 0, S_RAILRING33}, // S_RAILRING32
-	{SPR_RNGR, 32, 1, {NULL}, 0, 0, S_RAILRING34}, // S_RAILRING33
-	{SPR_RNGR, 33, 1, {NULL}, 0, 0, S_RAILRING35}, // S_RAILRING34
-	{SPR_RNGR, 34, 1, {NULL}, 0, 0, S_RAILRING1},  // S_RAILRING35
-
-	// Infinity Ring
-	{SPR_RNGI, 0, 1, {NULL}, 0, 0, S_INFINITYRING2},   // S_INFINITYRING1
-	{SPR_RNGI, 1, 1, {NULL}, 0, 0, S_INFINITYRING3},   // S_INFINITYRING2
-	{SPR_RNGI, 2, 1, {NULL}, 0, 0, S_INFINITYRING4},   // S_INFINITYRING3
-	{SPR_RNGI, 3, 1, {NULL}, 0, 0, S_INFINITYRING5},   // S_INFINITYRING4
-	{SPR_RNGI, 4, 1, {NULL}, 0, 0, S_INFINITYRING6},   // S_INFINITYRING5
-	{SPR_RNGI, 5, 1, {NULL}, 0, 0, S_INFINITYRING7},   // S_INFINITYRING6
-	{SPR_RNGI, 6, 1, {NULL}, 0, 0, S_INFINITYRING8},   // S_INFINITYRING7
-	{SPR_RNGI, 7, 1, {NULL}, 0, 0, S_INFINITYRING9},   // S_INFINITYRING8
-	{SPR_RNGI, 8, 1, {NULL}, 0, 0, S_INFINITYRING10},  // S_INFINITYRING9
-	{SPR_RNGI, 9, 1, {NULL}, 0, 0, S_INFINITYRING11},  // S_INFINITYRING10
-	{SPR_RNGI, 10, 1, {NULL}, 0, 0, S_INFINITYRING12}, // S_INFINITYRING11
-	{SPR_RNGI, 11, 1, {NULL}, 0, 0, S_INFINITYRING13}, // S_INFINITYRING12
-	{SPR_RNGI, 12, 1, {NULL}, 0, 0, S_INFINITYRING14}, // S_INFINITYRING13
-	{SPR_RNGI, 13, 1, {NULL}, 0, 0, S_INFINITYRING15}, // S_INFINITYRING14
-	{SPR_RNGI, 14, 1, {NULL}, 0, 0, S_INFINITYRING16}, // S_INFINITYRING15
-	{SPR_RNGI, 15, 1, {NULL}, 0, 0, S_INFINITYRING17}, // S_INFINITYRING16
-	{SPR_RNGI, 16, 1, {NULL}, 0, 0, S_INFINITYRING18}, // S_INFINITYRING17
-	{SPR_RNGI, 17, 1, {NULL}, 0, 0, S_INFINITYRING19}, // S_INFINITYRING18
-	{SPR_RNGI, 18, 1, {NULL}, 0, 0, S_INFINITYRING20}, // S_INFINITYRING19
-	{SPR_RNGI, 19, 1, {NULL}, 0, 0, S_INFINITYRING21}, // S_INFINITYRING20
-	{SPR_RNGI, 20, 1, {NULL}, 0, 0, S_INFINITYRING22}, // S_INFINITYRING21
-	{SPR_RNGI, 21, 1, {NULL}, 0, 0, S_INFINITYRING23}, // S_INFINITYRING22
-	{SPR_RNGI, 22, 1, {NULL}, 0, 0, S_INFINITYRING24}, // S_INFINITYRING23
-	{SPR_RNGI, 23, 1, {NULL}, 0, 0, S_INFINITYRING25}, // S_INFINITYRING24
-	{SPR_RNGI, 24, 1, {NULL}, 0, 0, S_INFINITYRING26}, // S_INFINITYRING25
-	{SPR_RNGI, 25, 1, {NULL}, 0, 0, S_INFINITYRING27}, // S_INFINITYRING26
-	{SPR_RNGI, 26, 1, {NULL}, 0, 0, S_INFINITYRING28}, // S_INFINITYRING27
-	{SPR_RNGI, 27, 1, {NULL}, 0, 0, S_INFINITYRING29}, // S_INFINITYRING28
-	{SPR_RNGI, 28, 1, {NULL}, 0, 0, S_INFINITYRING30}, // S_INFINITYRING29
-	{SPR_RNGI, 29, 1, {NULL}, 0, 0, S_INFINITYRING31}, // S_INFINITYRING30
-	{SPR_RNGI, 30, 1, {NULL}, 0, 0, S_INFINITYRING32}, // S_INFINITYRING31
-	{SPR_RNGI, 31, 1, {NULL}, 0, 0, S_INFINITYRING33}, // S_INFINITYRING32
-	{SPR_RNGI, 32, 1, {NULL}, 0, 0, S_INFINITYRING34}, // S_INFINITYRING33
-	{SPR_RNGI, 33, 1, {NULL}, 0, 0, S_INFINITYRING35}, // S_INFINITYRING34
-	{SPR_RNGI, 34, 1, {NULL}, 0, 0, S_INFINITYRING1},  // S_INFINITYRING35
-
-	// Automatic Ring
-	{SPR_RNGA, 0, 1, {NULL}, 0, 0, S_AUTOMATICRING2},   // S_AUTOMATICRING1
-	{SPR_RNGA, 1, 1, {NULL}, 0, 0, S_AUTOMATICRING3},   // S_AUTOMATICRING2
-	{SPR_RNGA, 2, 1, {NULL}, 0, 0, S_AUTOMATICRING4},   // S_AUTOMATICRING3
-	{SPR_RNGA, 3, 1, {NULL}, 0, 0, S_AUTOMATICRING5},   // S_AUTOMATICRING4
-	{SPR_RNGA, 4, 1, {NULL}, 0, 0, S_AUTOMATICRING6},   // S_AUTOMATICRING5
-	{SPR_RNGA, 5, 1, {NULL}, 0, 0, S_AUTOMATICRING7},   // S_AUTOMATICRING6
-	{SPR_RNGA, 6, 1, {NULL}, 0, 0, S_AUTOMATICRING8},   // S_AUTOMATICRING7
-	{SPR_RNGA, 7, 1, {NULL}, 0, 0, S_AUTOMATICRING9},   // S_AUTOMATICRING8
-	{SPR_RNGA, 8, 1, {NULL}, 0, 0, S_AUTOMATICRING10},  // S_AUTOMATICRING9
-	{SPR_RNGA, 9, 1, {NULL}, 0, 0, S_AUTOMATICRING11},  // S_AUTOMATICRING10
-	{SPR_RNGA, 10, 1, {NULL}, 0, 0, S_AUTOMATICRING12}, // S_AUTOMATICRING11
-	{SPR_RNGA, 11, 1, {NULL}, 0, 0, S_AUTOMATICRING13}, // S_AUTOMATICRING12
-	{SPR_RNGA, 12, 1, {NULL}, 0, 0, S_AUTOMATICRING14}, // S_AUTOMATICRING13
-	{SPR_RNGA, 13, 1, {NULL}, 0, 0, S_AUTOMATICRING15}, // S_AUTOMATICRING14
-	{SPR_RNGA, 14, 1, {NULL}, 0, 0, S_AUTOMATICRING16}, // S_AUTOMATICRING15
-	{SPR_RNGA, 15, 1, {NULL}, 0, 0, S_AUTOMATICRING17}, // S_AUTOMATICRING16
-	{SPR_RNGA, 16, 1, {NULL}, 0, 0, S_AUTOMATICRING18}, // S_AUTOMATICRING17
-	{SPR_RNGA, 17, 1, {NULL}, 0, 0, S_AUTOMATICRING19}, // S_AUTOMATICRING18
-	{SPR_RNGA, 18, 1, {NULL}, 0, 0, S_AUTOMATICRING20}, // S_AUTOMATICRING19
-	{SPR_RNGA, 19, 1, {NULL}, 0, 0, S_AUTOMATICRING21}, // S_AUTOMATICRING20
-	{SPR_RNGA, 20, 1, {NULL}, 0, 0, S_AUTOMATICRING22}, // S_AUTOMATICRING21
-	{SPR_RNGA, 21, 1, {NULL}, 0, 0, S_AUTOMATICRING23}, // S_AUTOMATICRING22
-	{SPR_RNGA, 22, 1, {NULL}, 0, 0, S_AUTOMATICRING24}, // S_AUTOMATICRING23
-	{SPR_RNGA, 23, 1, {NULL}, 0, 0, S_AUTOMATICRING25}, // S_AUTOMATICRING24
-	{SPR_RNGA, 24, 1, {NULL}, 0, 0, S_AUTOMATICRING26}, // S_AUTOMATICRING25
-	{SPR_RNGA, 25, 1, {NULL}, 0, 0, S_AUTOMATICRING27}, // S_AUTOMATICRING26
-	{SPR_RNGA, 26, 1, {NULL}, 0, 0, S_AUTOMATICRING28}, // S_AUTOMATICRING27
-	{SPR_RNGA, 27, 1, {NULL}, 0, 0, S_AUTOMATICRING29}, // S_AUTOMATICRING28
-	{SPR_RNGA, 28, 1, {NULL}, 0, 0, S_AUTOMATICRING30}, // S_AUTOMATICRING29
-	{SPR_RNGA, 29, 1, {NULL}, 0, 0, S_AUTOMATICRING31}, // S_AUTOMATICRING30
-	{SPR_RNGA, 30, 1, {NULL}, 0, 0, S_AUTOMATICRING32}, // S_AUTOMATICRING31
-	{SPR_RNGA, 31, 1, {NULL}, 0, 0, S_AUTOMATICRING33}, // S_AUTOMATICRING32
-	{SPR_RNGA, 32, 1, {NULL}, 0, 0, S_AUTOMATICRING34}, // S_AUTOMATICRING33
-	{SPR_RNGA, 33, 1, {NULL}, 0, 0, S_AUTOMATICRING35}, // S_AUTOMATICRING34
-	{SPR_RNGA, 34, 1, {NULL}, 0, 0, S_AUTOMATICRING1},  // S_AUTOMATICRING35
-
-	// Explosion Ring
-	{SPR_RNGE, 0, 1, {NULL}, 0, 0, S_EXPLOSIONRING2},   // S_EXPLOSIONRING1
-	{SPR_RNGE, 1, 1, {NULL}, 0, 0, S_EXPLOSIONRING3},   // S_EXPLOSIONRING2
-	{SPR_RNGE, 2, 1, {NULL}, 0, 0, S_EXPLOSIONRING4},   // S_EXPLOSIONRING3
-	{SPR_RNGE, 3, 1, {NULL}, 0, 0, S_EXPLOSIONRING5},   // S_EXPLOSIONRING4
-	{SPR_RNGE, 4, 1, {NULL}, 0, 0, S_EXPLOSIONRING6},   // S_EXPLOSIONRING5
-	{SPR_RNGE, 5, 1, {NULL}, 0, 0, S_EXPLOSIONRING7},   // S_EXPLOSIONRING6
-	{SPR_RNGE, 6, 1, {NULL}, 0, 0, S_EXPLOSIONRING8},   // S_EXPLOSIONRING7
-	{SPR_RNGE, 7, 1, {NULL}, 0, 0, S_EXPLOSIONRING9},   // S_EXPLOSIONRING8
-	{SPR_RNGE, 8, 1, {NULL}, 0, 0, S_EXPLOSIONRING10},  // S_EXPLOSIONRING9
-	{SPR_RNGE, 9, 1, {NULL}, 0, 0, S_EXPLOSIONRING11},  // S_EXPLOSIONRING10
-	{SPR_RNGE, 10, 1, {NULL}, 0, 0, S_EXPLOSIONRING12}, // S_EXPLOSIONRING11
-	{SPR_RNGE, 11, 1, {NULL}, 0, 0, S_EXPLOSIONRING13}, // S_EXPLOSIONRING12
-	{SPR_RNGE, 12, 1, {NULL}, 0, 0, S_EXPLOSIONRING14}, // S_EXPLOSIONRING13
-	{SPR_RNGE, 13, 1, {NULL}, 0, 0, S_EXPLOSIONRING15}, // S_EXPLOSIONRING14
-	{SPR_RNGE, 14, 1, {NULL}, 0, 0, S_EXPLOSIONRING16}, // S_EXPLOSIONRING15
-	{SPR_RNGE, 15, 1, {NULL}, 0, 0, S_EXPLOSIONRING17}, // S_EXPLOSIONRING16
-	{SPR_RNGE, 16, 1, {NULL}, 0, 0, S_EXPLOSIONRING18}, // S_EXPLOSIONRING17
-	{SPR_RNGE, 17, 1, {NULL}, 0, 0, S_EXPLOSIONRING19}, // S_EXPLOSIONRING18
-	{SPR_RNGE, 18, 1, {NULL}, 0, 0, S_EXPLOSIONRING20}, // S_EXPLOSIONRING19
-	{SPR_RNGE, 19, 1, {NULL}, 0, 0, S_EXPLOSIONRING21}, // S_EXPLOSIONRING20
-	{SPR_RNGE, 20, 1, {NULL}, 0, 0, S_EXPLOSIONRING22}, // S_EXPLOSIONRING21
-	{SPR_RNGE, 21, 1, {NULL}, 0, 0, S_EXPLOSIONRING23}, // S_EXPLOSIONRING22
-	{SPR_RNGE, 22, 1, {NULL}, 0, 0, S_EXPLOSIONRING24}, // S_EXPLOSIONRING23
-	{SPR_RNGE, 23, 1, {NULL}, 0, 0, S_EXPLOSIONRING25}, // S_EXPLOSIONRING24
-	{SPR_RNGE, 24, 1, {NULL}, 0, 0, S_EXPLOSIONRING26}, // S_EXPLOSIONRING25
-	{SPR_RNGE, 25, 1, {NULL}, 0, 0, S_EXPLOSIONRING27}, // S_EXPLOSIONRING26
-	{SPR_RNGE, 26, 1, {NULL}, 0, 0, S_EXPLOSIONRING28}, // S_EXPLOSIONRING27
-	{SPR_RNGE, 27, 1, {NULL}, 0, 0, S_EXPLOSIONRING29}, // S_EXPLOSIONRING28
-	{SPR_RNGE, 28, 1, {NULL}, 0, 0, S_EXPLOSIONRING30}, // S_EXPLOSIONRING29
-	{SPR_RNGE, 29, 1, {NULL}, 0, 0, S_EXPLOSIONRING31}, // S_EXPLOSIONRING30
-	{SPR_RNGE, 30, 1, {NULL}, 0, 0, S_EXPLOSIONRING32}, // S_EXPLOSIONRING31
-	{SPR_RNGE, 31, 1, {NULL}, 0, 0, S_EXPLOSIONRING33}, // S_EXPLOSIONRING32
-	{SPR_RNGE, 32, 1, {NULL}, 0, 0, S_EXPLOSIONRING34}, // S_EXPLOSIONRING33
-	{SPR_RNGE, 33, 1, {NULL}, 0, 0, S_EXPLOSIONRING35}, // S_EXPLOSIONRING34
-	{SPR_RNGE, 34, 1, {NULL}, 0, 0, S_EXPLOSIONRING1},  // S_EXPLOSIONRING35
-
-	// Scatter Ring
-	{SPR_RNGS, 0, 1, {NULL}, 0, 0, S_SCATTERRING2},   // S_SCATTERRING1
-	{SPR_RNGS, 1, 1, {NULL}, 0, 0, S_SCATTERRING3},   // S_SCATTERRING2
-	{SPR_RNGS, 2, 1, {NULL}, 0, 0, S_SCATTERRING4},   // S_SCATTERRING3
-	{SPR_RNGS, 3, 1, {NULL}, 0, 0, S_SCATTERRING5},   // S_SCATTERRING4
-	{SPR_RNGS, 4, 1, {NULL}, 0, 0, S_SCATTERRING6},   // S_SCATTERRING5
-	{SPR_RNGS, 5, 1, {NULL}, 0, 0, S_SCATTERRING7},   // S_SCATTERRING6
-	{SPR_RNGS, 6, 1, {NULL}, 0, 0, S_SCATTERRING8},   // S_SCATTERRING7
-	{SPR_RNGS, 7, 1, {NULL}, 0, 0, S_SCATTERRING9},   // S_SCATTERRING8
-	{SPR_RNGS, 8, 1, {NULL}, 0, 0, S_SCATTERRING10},  // S_SCATTERRING9
-	{SPR_RNGS, 9, 1, {NULL}, 0, 0, S_SCATTERRING11},  // S_SCATTERRING10
-	{SPR_RNGS, 10, 1, {NULL}, 0, 0, S_SCATTERRING12}, // S_SCATTERRING11
-	{SPR_RNGS, 11, 1, {NULL}, 0, 0, S_SCATTERRING13}, // S_SCATTERRING12
-	{SPR_RNGS, 12, 1, {NULL}, 0, 0, S_SCATTERRING14}, // S_SCATTERRING13
-	{SPR_RNGS, 13, 1, {NULL}, 0, 0, S_SCATTERRING15}, // S_SCATTERRING14
-	{SPR_RNGS, 14, 1, {NULL}, 0, 0, S_SCATTERRING16}, // S_SCATTERRING15
-	{SPR_RNGS, 15, 1, {NULL}, 0, 0, S_SCATTERRING17}, // S_SCATTERRING16
-	{SPR_RNGS, 16, 1, {NULL}, 0, 0, S_SCATTERRING18}, // S_SCATTERRING17
-	{SPR_RNGS, 17, 1, {NULL}, 0, 0, S_SCATTERRING19}, // S_SCATTERRING18
-	{SPR_RNGS, 18, 1, {NULL}, 0, 0, S_SCATTERRING20}, // S_SCATTERRING19
-	{SPR_RNGS, 19, 1, {NULL}, 0, 0, S_SCATTERRING21}, // S_SCATTERRING20
-	{SPR_RNGS, 20, 1, {NULL}, 0, 0, S_SCATTERRING22}, // S_SCATTERRING21
-	{SPR_RNGS, 21, 1, {NULL}, 0, 0, S_SCATTERRING23}, // S_SCATTERRING22
-	{SPR_RNGS, 22, 1, {NULL}, 0, 0, S_SCATTERRING24}, // S_SCATTERRING23
-	{SPR_RNGS, 23, 1, {NULL}, 0, 0, S_SCATTERRING25}, // S_SCATTERRING24
-	{SPR_RNGS, 24, 1, {NULL}, 0, 0, S_SCATTERRING26}, // S_SCATTERRING25
-	{SPR_RNGS, 25, 1, {NULL}, 0, 0, S_SCATTERRING27}, // S_SCATTERRING26
-	{SPR_RNGS, 26, 1, {NULL}, 0, 0, S_SCATTERRING28}, // S_SCATTERRING27
-	{SPR_RNGS, 27, 1, {NULL}, 0, 0, S_SCATTERRING29}, // S_SCATTERRING28
-	{SPR_RNGS, 28, 1, {NULL}, 0, 0, S_SCATTERRING30}, // S_SCATTERRING29
-	{SPR_RNGS, 29, 1, {NULL}, 0, 0, S_SCATTERRING31}, // S_SCATTERRING30
-	{SPR_RNGS, 30, 1, {NULL}, 0, 0, S_SCATTERRING32}, // S_SCATTERRING31
-	{SPR_RNGS, 31, 1, {NULL}, 0, 0, S_SCATTERRING33}, // S_SCATTERRING32
-	{SPR_RNGS, 32, 1, {NULL}, 0, 0, S_SCATTERRING34}, // S_SCATTERRING33
-	{SPR_RNGS, 33, 1, {NULL}, 0, 0, S_SCATTERRING35}, // S_SCATTERRING34
-	{SPR_RNGS, 34, 1, {NULL}, 0, 0, S_SCATTERRING1},  // S_SCATTERRING35
-
-	// Grenade Ring
-	{SPR_RNGG, 0, 1, {NULL}, 0, 0, S_GRENADERING2},   // S_GRENADERING1
-	{SPR_RNGG, 1, 1, {NULL}, 0, 0, S_GRENADERING3},   // S_GRENADERING2
-	{SPR_RNGG, 2, 1, {NULL}, 0, 0, S_GRENADERING4},   // S_GRENADERING3
-	{SPR_RNGG, 3, 1, {NULL}, 0, 0, S_GRENADERING5},   // S_GRENADERING4
-	{SPR_RNGG, 4, 1, {NULL}, 0, 0, S_GRENADERING6},   // S_GRENADERING5
-	{SPR_RNGG, 5, 1, {NULL}, 0, 0, S_GRENADERING7},   // S_GRENADERING6
-	{SPR_RNGG, 6, 1, {NULL}, 0, 0, S_GRENADERING8},   // S_GRENADERING7
-	{SPR_RNGG, 7, 1, {NULL}, 0, 0, S_GRENADERING9},   // S_GRENADERING8
-	{SPR_RNGG, 8, 1, {NULL}, 0, 0, S_GRENADERING10},  // S_GRENADERING9
-	{SPR_RNGG, 9, 1, {NULL}, 0, 0, S_GRENADERING11},  // S_GRENADERING10
-	{SPR_RNGG, 10, 1, {NULL}, 0, 0, S_GRENADERING12}, // S_GRENADERING11
-	{SPR_RNGG, 11, 1, {NULL}, 0, 0, S_GRENADERING13}, // S_GRENADERING12
-	{SPR_RNGG, 12, 1, {NULL}, 0, 0, S_GRENADERING14}, // S_GRENADERING13
-	{SPR_RNGG, 13, 1, {NULL}, 0, 0, S_GRENADERING15}, // S_GRENADERING14
-	{SPR_RNGG, 14, 1, {NULL}, 0, 0, S_GRENADERING16}, // S_GRENADERING15
-	{SPR_RNGG, 15, 1, {NULL}, 0, 0, S_GRENADERING17}, // S_GRENADERING16
-	{SPR_RNGG, 16, 1, {NULL}, 0, 0, S_GRENADERING18}, // S_GRENADERING17
-	{SPR_RNGG, 17, 1, {NULL}, 0, 0, S_GRENADERING19}, // S_GRENADERING18
-	{SPR_RNGG, 18, 1, {NULL}, 0, 0, S_GRENADERING20}, // S_GRENADERING19
-	{SPR_RNGG, 19, 1, {NULL}, 0, 0, S_GRENADERING21}, // S_GRENADERING20
-	{SPR_RNGG, 20, 1, {NULL}, 0, 0, S_GRENADERING22}, // S_GRENADERING21
-	{SPR_RNGG, 21, 1, {NULL}, 0, 0, S_GRENADERING23}, // S_GRENADERING22
-	{SPR_RNGG, 22, 1, {NULL}, 0, 0, S_GRENADERING24}, // S_GRENADERING23
-	{SPR_RNGG, 23, 1, {NULL}, 0, 0, S_GRENADERING25}, // S_GRENADERING24
-	{SPR_RNGG, 24, 1, {NULL}, 0, 0, S_GRENADERING26}, // S_GRENADERING25
-	{SPR_RNGG, 25, 1, {NULL}, 0, 0, S_GRENADERING27}, // S_GRENADERING26
-	{SPR_RNGG, 26, 1, {NULL}, 0, 0, S_GRENADERING28}, // S_GRENADERING27
-	{SPR_RNGG, 27, 1, {NULL}, 0, 0, S_GRENADERING29}, // S_GRENADERING28
-	{SPR_RNGG, 28, 1, {NULL}, 0, 0, S_GRENADERING30}, // S_GRENADERING29
-	{SPR_RNGG, 29, 1, {NULL}, 0, 0, S_GRENADERING31}, // S_GRENADERING30
-	{SPR_RNGG, 30, 1, {NULL}, 0, 0, S_GRENADERING32}, // S_GRENADERING31
-	{SPR_RNGG, 31, 1, {NULL}, 0, 0, S_GRENADERING33}, // S_GRENADERING32
-	{SPR_RNGG, 32, 1, {NULL}, 0, 0, S_GRENADERING34}, // S_GRENADERING33
-	{SPR_RNGG, 33, 1, {NULL}, 0, 0, S_GRENADERING35}, // S_GRENADERING34
-	{SPR_RNGG, 34, 1, {NULL}, 0, 0, S_GRENADERING1},  // S_GRENADERING35
+	// Weapon Ring Ammo
+	{SPR_RNGB, FF_ANIMATE, -1, {NULL}, 34, 1, S_BOUNCERINGAMMO},    // S_BOUNCERINGAMMO
+	{SPR_RNGR, FF_ANIMATE, -1, {NULL}, 34, 1, S_RAILRINGAMMO},      // S_RAILRINGAMMO
+	{SPR_RNGI, FF_ANIMATE, -1, {NULL}, 34, 1, S_INFINITYRINGAMMO},  // S_INFINITYRINGAMMO
+	{SPR_RNGA, FF_ANIMATE, -1, {NULL}, 34, 1, S_AUTOMATICRINGAMMO}, // S_AUTOMATICRINGAMMO
+	{SPR_RNGE, FF_ANIMATE, -1, {NULL}, 34, 1, S_EXPLOSIONRINGAMMO}, // S_EXPLOSIONRINGAMMO
+	{SPR_RNGS, FF_ANIMATE, -1, {NULL}, 34, 1, S_SCATTERRINGAMMO},   // S_SCATTERRINGAMMO
+	{SPR_RNGG, FF_ANIMATE, -1, {NULL}, 34, 1, S_GRENADERINGAMMO},   // S_GRENADERINGAMMO
 
 	// Bounce Ring Pickup
-	{SPR_PIKB,  0, 1, {NULL}, 0, 0, S_BOUNCEPICKUP2},  // S_BOUNCEPICKUP1
-	{SPR_PIKB,  1, 1, {NULL}, 0, 0, S_BOUNCEPICKUP3},  // S_BOUNCEPICKUP2
-	{SPR_PIKB,  2, 1, {NULL}, 0, 0, S_BOUNCEPICKUP4},  // S_BOUNCEPICKUP3
-	{SPR_PIKB,  3, 1, {NULL}, 0, 0, S_BOUNCEPICKUP5},  // S_BOUNCEPICKUP4
-	{SPR_PIKB,  4, 1, {NULL}, 0, 0, S_BOUNCEPICKUP6},  // S_BOUNCEPICKUP5
-	{SPR_PIKB,  5, 1, {NULL}, 0, 0, S_BOUNCEPICKUP7},  // S_BOUNCEPICKUP6
-	{SPR_PIKB,  6, 1, {NULL}, 0, 0, S_BOUNCEPICKUP8},  // S_BOUNCEPICKUP7
-	{SPR_PIKB,  7, 1, {NULL}, 0, 0, S_BOUNCEPICKUP9},  // S_BOUNCEPICKUP8
-	{SPR_PIKB,  8, 1, {NULL}, 0, 0, S_BOUNCEPICKUP10}, // S_BOUNCEPICKUP9
-	{SPR_PIKB,  9, 1, {NULL}, 0, 0, S_BOUNCEPICKUP11}, // S_BOUNCEPICKUP10
-	{SPR_PIKB, 10, 1, {NULL}, 0, 0, S_BOUNCEPICKUP12}, // S_BOUNCEPICKUP11
-	{SPR_PIKB, 11, 1, {NULL}, 0, 0, S_BOUNCEPICKUP13}, // S_BOUNCEPICKUP12
-	{SPR_PIKB, 12, 1, {NULL}, 0, 0, S_BOUNCEPICKUP14}, // S_BOUNCEPICKUP13
-	{SPR_PIKB, 13, 1, {NULL}, 0, 0, S_BOUNCEPICKUP15}, // S_BOUNCEPICKUP14
-	{SPR_PIKB, 14, 1, {NULL}, 0, 0, S_BOUNCEPICKUP16}, // S_BOUNCEPICKUP15
-	{SPR_PIKB, 15, 1, {NULL}, 0, 0, S_BOUNCEPICKUP1},  // S_BOUNCEPICKUP16
-
-	// Bounce Ring Pickup Fade
+	{SPR_PIKB, FF_ANIMATE, -1, {NULL}, 15, 1, S_BOUNCEPICKUP},  // S_BOUNCEPICKUP
+
 	{SPR_PIKB,  0, 1, {NULL}, 0, 0, S_BOUNCEPICKUPFADE2}, // S_BOUNCEPICKUPFADE1
 	{SPR_PIKB,  2, 1, {NULL}, 0, 0, S_BOUNCEPICKUPFADE3}, // S_BOUNCEPICKUPFADE2
 	{SPR_PIKB,  4, 1, {NULL}, 0, 0, S_BOUNCEPICKUPFADE4}, // S_BOUNCEPICKUPFADE3
@@ -2312,24 +1933,8 @@ state_t states[NUMSTATES] =
 	{SPR_PIKB, 14, 1, {NULL}, 0, 0, S_BOUNCEPICKUPFADE1}, // S_BOUNCEPICKUPFADE8
 
 	// Rail Ring Pickup
-	{SPR_PIKR,  0, 1, {NULL}, 0, 0, S_RAILPICKUP2},  // S_RAILPICKUP1
-	{SPR_PIKR,  1, 1, {NULL}, 0, 0, S_RAILPICKUP3},  // S_RAILPICKUP2
-	{SPR_PIKR,  2, 1, {NULL}, 0, 0, S_RAILPICKUP4},  // S_RAILPICKUP3
-	{SPR_PIKR,  3, 1, {NULL}, 0, 0, S_RAILPICKUP5},  // S_RAILPICKUP4
-	{SPR_PIKR,  4, 1, {NULL}, 0, 0, S_RAILPICKUP6},  // S_RAILPICKUP5
-	{SPR_PIKR,  5, 1, {NULL}, 0, 0, S_RAILPICKUP7},  // S_RAILPICKUP6
-	{SPR_PIKR,  6, 1, {NULL}, 0, 0, S_RAILPICKUP8},  // S_RAILPICKUP7
-	{SPR_PIKR,  7, 1, {NULL}, 0, 0, S_RAILPICKUP9},  // S_RAILPICKUP8
-	{SPR_PIKR,  8, 1, {NULL}, 0, 0, S_RAILPICKUP10}, // S_RAILPICKUP9
-	{SPR_PIKR,  9, 1, {NULL}, 0, 0, S_RAILPICKUP11}, // S_RAILPICKUP10
-	{SPR_PIKR, 10, 1, {NULL}, 0, 0, S_RAILPICKUP12}, // S_RAILPICKUP11
-	{SPR_PIKR, 11, 1, {NULL}, 0, 0, S_RAILPICKUP13}, // S_RAILPICKUP12
-	{SPR_PIKR, 12, 1, {NULL}, 0, 0, S_RAILPICKUP14}, // S_RAILPICKUP13
-	{SPR_PIKR, 13, 1, {NULL}, 0, 0, S_RAILPICKUP15}, // S_RAILPICKUP14
-	{SPR_PIKR, 14, 1, {NULL}, 0, 0, S_RAILPICKUP16}, // S_RAILPICKUP15
-	{SPR_PIKR, 15, 1, {NULL}, 0, 0, S_RAILPICKUP1},  // S_RAILPICKUP16
-
-	// Rail Ring Pickup Fade
+	{SPR_PIKR, FF_ANIMATE, -1, {NULL}, 15, 1, S_RAILPICKUP},  // S_RAILPICKUP
+
 	{SPR_PIKR,  0, 1, {NULL}, 0, 0, S_RAILPICKUPFADE2}, // S_RAILPICKUPFADE1
 	{SPR_PIKR,  2, 1, {NULL}, 0, 0, S_RAILPICKUPFADE3}, // S_RAILPICKUPFADE2
 	{SPR_PIKR,  4, 1, {NULL}, 0, 0, S_RAILPICKUPFADE4}, // S_RAILPICKUPFADE3
@@ -2340,22 +1945,7 @@ state_t states[NUMSTATES] =
 	{SPR_PIKR, 14, 1, {NULL}, 0, 0, S_RAILPICKUPFADE1}, // S_RAILPICKUPFADE8
 
 	// Auto Ring Pickup
-	{SPR_PIKA,  0, 1, {NULL}, 0, 0, S_AUTOPICKUP2},  // S_AUTOPICKUP1
-	{SPR_PIKA,  1, 1, {NULL}, 0, 0, S_AUTOPICKUP3},  // S_AUTOPICKUP2
-	{SPR_PIKA,  2, 1, {NULL}, 0, 0, S_AUTOPICKUP4},  // S_AUTOPICKUP3
-	{SPR_PIKA,  3, 1, {NULL}, 0, 0, S_AUTOPICKUP5},  // S_AUTOPICKUP4
-	{SPR_PIKA,  4, 1, {NULL}, 0, 0, S_AUTOPICKUP6},  // S_AUTOPICKUP5
-	{SPR_PIKA,  5, 1, {NULL}, 0, 0, S_AUTOPICKUP7},  // S_AUTOPICKUP6
-	{SPR_PIKA,  6, 1, {NULL}, 0, 0, S_AUTOPICKUP8},  // S_AUTOPICKUP7
-	{SPR_PIKA,  7, 1, {NULL}, 0, 0, S_AUTOPICKUP9},  // S_AUTOPICKUP8
-	{SPR_PIKA,  8, 1, {NULL}, 0, 0, S_AUTOPICKUP10}, // S_AUTOPICKUP9
-	{SPR_PIKA,  9, 1, {NULL}, 0, 0, S_AUTOPICKUP11}, // S_AUTOPICKUP10
-	{SPR_PIKA, 10, 1, {NULL}, 0, 0, S_AUTOPICKUP12}, // S_AUTOPICKUP11
-	{SPR_PIKA, 11, 1, {NULL}, 0, 0, S_AUTOPICKUP13}, // S_AUTOPICKUP12
-	{SPR_PIKA, 12, 1, {NULL}, 0, 0, S_AUTOPICKUP14}, // S_AUTOPICKUP13
-	{SPR_PIKA, 13, 1, {NULL}, 0, 0, S_AUTOPICKUP15}, // S_AUTOPICKUP14
-	{SPR_PIKA, 14, 1, {NULL}, 0, 0, S_AUTOPICKUP16}, // S_AUTOPICKUP15
-	{SPR_PIKA, 15, 1, {NULL}, 0, 0, S_AUTOPICKUP1},  // S_AUTOPICKUP16
+	{SPR_PIKA, FF_ANIMATE, -1, {NULL}, 15, 1, S_AUTOPICKUP},  // S_AUTOPICKUP
 
 	{SPR_PIKA,  0, 1, {NULL}, 0, 0, S_AUTOPICKUPFADE2}, // S_AUTOPICKUPFADE1
 	{SPR_PIKA,  2, 1, {NULL}, 0, 0, S_AUTOPICKUPFADE3}, // S_AUTOPICKUPFADE2
@@ -2367,22 +1957,7 @@ state_t states[NUMSTATES] =
 	{SPR_PIKA, 14, 1, {NULL}, 0, 0, S_AUTOPICKUPFADE1}, // S_AUTOPICKUPFADE8
 
 	// Explode Ring Pickup
-	{SPR_PIKE,  0, 1, {NULL}, 0, 0, S_EXPLODEPICKUP2},  // S_EXPLODEPICKUP1
-	{SPR_PIKE,  1, 1, {NULL}, 0, 0, S_EXPLODEPICKUP3},  // S_EXPLODEPICKUP2
-	{SPR_PIKE,  2, 1, {NULL}, 0, 0, S_EXPLODEPICKUP4},  // S_EXPLODEPICKUP3
-	{SPR_PIKE,  3, 1, {NULL}, 0, 0, S_EXPLODEPICKUP5},  // S_EXPLODEPICKUP4
-	{SPR_PIKE,  4, 1, {NULL}, 0, 0, S_EXPLODEPICKUP6},  // S_EXPLODEPICKUP5
-	{SPR_PIKE,  5, 1, {NULL}, 0, 0, S_EXPLODEPICKUP7},  // S_EXPLODEPICKUP6
-	{SPR_PIKE,  6, 1, {NULL}, 0, 0, S_EXPLODEPICKUP8},  // S_EXPLODEPICKUP7
-	{SPR_PIKE,  7, 1, {NULL}, 0, 0, S_EXPLODEPICKUP9},  // S_EXPLODEPICKUP8
-	{SPR_PIKE,  8, 1, {NULL}, 0, 0, S_EXPLODEPICKUP10}, // S_EXPLODEPICKUP9
-	{SPR_PIKE,  9, 1, {NULL}, 0, 0, S_EXPLODEPICKUP11}, // S_EXPLODEPICKUP10
-	{SPR_PIKE, 10, 1, {NULL}, 0, 0, S_EXPLODEPICKUP12}, // S_EXPLODEPICKUP11
-	{SPR_PIKE, 11, 1, {NULL}, 0, 0, S_EXPLODEPICKUP13}, // S_EXPLODEPICKUP12
-	{SPR_PIKE, 12, 1, {NULL}, 0, 0, S_EXPLODEPICKUP14}, // S_EXPLODEPICKUP13
-	{SPR_PIKE, 13, 1, {NULL}, 0, 0, S_EXPLODEPICKUP15}, // S_EXPLODEPICKUP14
-	{SPR_PIKE, 14, 1, {NULL}, 0, 0, S_EXPLODEPICKUP16}, // S_EXPLODEPICKUP15
-	{SPR_PIKE, 15, 1, {NULL}, 0, 0, S_EXPLODEPICKUP1},  // S_EXPLODEPICKUP16
+	{SPR_PIKE, FF_ANIMATE, -1, {NULL}, 15, 1, S_EXPLODEPICKUP},  // S_EXPLODEPICKUP
 
 	{SPR_PIKE,  0, 1, {NULL}, 0, 0, S_EXPLODEPICKUPFADE2}, // S_EXPLODEPICKUPFADE1
 	{SPR_PIKE,  2, 1, {NULL}, 0, 0, S_EXPLODEPICKUPFADE3}, // S_EXPLODEPICKUPFADE2
@@ -2394,22 +1969,7 @@ state_t states[NUMSTATES] =
 	{SPR_PIKE, 14, 1, {NULL}, 0, 0, S_EXPLODEPICKUPFADE1}, // S_EXPLODEPICKUPFADE8
 
 	// Scatter Ring Pickup
-	{SPR_PIKS,  0, 1, {NULL}, 0, 0, S_SCATTERPICKUP2},  // S_SCATTERPICKUP1
-	{SPR_PIKS,  1, 1, {NULL}, 0, 0, S_SCATTERPICKUP3},  // S_SCATTERPICKUP2
-	{SPR_PIKS,  2, 1, {NULL}, 0, 0, S_SCATTERPICKUP4},  // S_SCATTERPICKUP3
-	{SPR_PIKS,  3, 1, {NULL}, 0, 0, S_SCATTERPICKUP5},  // S_SCATTERPICKUP4
-	{SPR_PIKS,  4, 1, {NULL}, 0, 0, S_SCATTERPICKUP6},  // S_SCATTERPICKUP5
-	{SPR_PIKS,  5, 1, {NULL}, 0, 0, S_SCATTERPICKUP7},  // S_SCATTERPICKUP6
-	{SPR_PIKS,  6, 1, {NULL}, 0, 0, S_SCATTERPICKUP8},  // S_SCATTERPICKUP7
-	{SPR_PIKS,  7, 1, {NULL}, 0, 0, S_SCATTERPICKUP9},  // S_SCATTERPICKUP8
-	{SPR_PIKS,  8, 1, {NULL}, 0, 0, S_SCATTERPICKUP10}, // S_SCATTERPICKUP9
-	{SPR_PIKS,  9, 1, {NULL}, 0, 0, S_SCATTERPICKUP11}, // S_SCATTERPICKUP10
-	{SPR_PIKS, 10, 1, {NULL}, 0, 0, S_SCATTERPICKUP12}, // S_SCATTERPICKUP11
-	{SPR_PIKS, 11, 1, {NULL}, 0, 0, S_SCATTERPICKUP13}, // S_SCATTERPICKUP12
-	{SPR_PIKS, 12, 1, {NULL}, 0, 0, S_SCATTERPICKUP14}, // S_SCATTERPICKUP13
-	{SPR_PIKS, 13, 1, {NULL}, 0, 0, S_SCATTERPICKUP15}, // S_SCATTERPICKUP14
-	{SPR_PIKS, 14, 1, {NULL}, 0, 0, S_SCATTERPICKUP16}, // S_SCATTERPICKUP15
-	{SPR_PIKS, 15, 1, {NULL}, 0, 0, S_SCATTERPICKUP1},  // S_SCATTERPICKUP16
+	{SPR_PIKS,  FF_ANIMATE, -1, {NULL}, 15, 1, S_SCATTERPICKUP},  // S_SCATTERPICKUP
 
 	{SPR_PIKS,  0, 1, {NULL}, 0, 0, S_SCATTERPICKUPFADE2}, // S_SCATTERPICKUPFADE1
 	{SPR_PIKS,  2, 1, {NULL}, 0, 0, S_SCATTERPICKUPFADE3}, // S_SCATTERPICKUPFADE2
@@ -2421,22 +1981,7 @@ state_t states[NUMSTATES] =
 	{SPR_PIKS, 14, 1, {NULL}, 0, 0, S_SCATTERPICKUPFADE1}, // S_SCATTERPICKUPFADE8
 
 	// Grenade Ring Pickup
-	{SPR_PIKG,  0, 1, {NULL}, 0, 0, S_GRENADEPICKUP2},  // S_GRENADEPICKUP1
-	{SPR_PIKG,  1, 1, {NULL}, 0, 0, S_GRENADEPICKUP3},  // S_GRENADEPICKUP2
-	{SPR_PIKG,  2, 1, {NULL}, 0, 0, S_GRENADEPICKUP4},  // S_GRENADEPICKUP3
-	{SPR_PIKG,  3, 1, {NULL}, 0, 0, S_GRENADEPICKUP5},  // S_GRENADEPICKUP4
-	{SPR_PIKG,  4, 1, {NULL}, 0, 0, S_GRENADEPICKUP6},  // S_GRENADEPICKUP5
-	{SPR_PIKG,  5, 1, {NULL}, 0, 0, S_GRENADEPICKUP7},  // S_GRENADEPICKUP6
-	{SPR_PIKG,  6, 1, {NULL}, 0, 0, S_GRENADEPICKUP8},  // S_GRENADEPICKUP7
-	{SPR_PIKG,  7, 1, {NULL}, 0, 0, S_GRENADEPICKUP9},  // S_GRENADEPICKUP8
-	{SPR_PIKG,  8, 1, {NULL}, 0, 0, S_GRENADEPICKUP10}, // S_GRENADEPICKUP9
-	{SPR_PIKG,  9, 1, {NULL}, 0, 0, S_GRENADEPICKUP11}, // S_GRENADEPICKUP10
-	{SPR_PIKG, 10, 1, {NULL}, 0, 0, S_GRENADEPICKUP12}, // S_GRENADEPICKUP11
-	{SPR_PIKG, 11, 1, {NULL}, 0, 0, S_GRENADEPICKUP13}, // S_GRENADEPICKUP12
-	{SPR_PIKG, 12, 1, {NULL}, 0, 0, S_GRENADEPICKUP14}, // S_GRENADEPICKUP13
-	{SPR_PIKG, 13, 1, {NULL}, 0, 0, S_GRENADEPICKUP15}, // S_GRENADEPICKUP14
-	{SPR_PIKG, 14, 1, {NULL}, 0, 0, S_GRENADEPICKUP16}, // S_GRENADEPICKUP15
-	{SPR_PIKG, 15, 1, {NULL}, 0, 0, S_GRENADEPICKUP1},  // S_GRENADEPICKUP16
+	{SPR_PIKG,  FF_ANIMATE, -1, {NULL}, 15, 1, S_GRENADEPICKUP},  // S_GRENADEPICKUP
 
 	{SPR_PIKG,  0, 1, {NULL}, 0, 0, S_GRENADEPICKUPFADE2}, // S_GRENADEPICKUPFADE1
 	{SPR_PIKG,  2, 1, {NULL}, 0, 0, S_GRENADEPICKUPFADE3}, // S_GRENADEPICKUPFADE2
@@ -2448,58 +1993,58 @@ state_t states[NUMSTATES] =
 	{SPR_PIKG, 14, 1, {NULL}, 0, 0, S_GRENADEPICKUPFADE1}, // S_GRENADEPICKUPFADE8
 
 	// Thrown Weapon Rings
-	{SPR_RNGB, 32768, 1, {A_ThrownRing}, 0, 0, S_THROWNBOUNCE2}, // S_THROWNBOUNCE1
-	{SPR_RNGB, 32773, 1, {A_ThrownRing}, 0, 0, S_THROWNBOUNCE3}, // S_THROWNBOUNCE2
-	{SPR_RNGB, 32778, 1, {A_ThrownRing}, 0, 0, S_THROWNBOUNCE4}, // S_THROWNBOUNCE3
-	{SPR_RNGB, 32783, 1, {A_ThrownRing}, 0, 0, S_THROWNBOUNCE5}, // S_THROWNBOUNCE4
-	{SPR_RNGB, 32788, 1, {A_ThrownRing}, 0, 0, S_THROWNBOUNCE6}, // S_THROWNBOUNCE5
-	{SPR_RNGB, 32793, 1, {A_ThrownRing}, 0, 0, S_THROWNBOUNCE7}, // S_THROWNBOUNCE6
-	{SPR_RNGB, 32798, 1, {A_ThrownRing}, 0, 0, S_THROWNBOUNCE1}, // S_THROWNBOUNCE7
-
-	{SPR_RNGI, 32768, 1, {A_ThrownRing}, 0, 0, S_THROWNINFINITY2}, // S_THROWNINFINITY1
-	{SPR_RNGI, 32773, 1, {A_ThrownRing}, 0, 0, S_THROWNINFINITY3}, // S_THROWNINFINITY2
-	{SPR_RNGI, 32778, 1, {A_ThrownRing}, 0, 0, S_THROWNINFINITY4}, // S_THROWNINFINITY3
-	{SPR_RNGI, 32783, 1, {A_ThrownRing}, 0, 0, S_THROWNINFINITY5}, // S_THROWNINFINITY4
-	{SPR_RNGI, 32788, 1, {A_ThrownRing}, 0, 0, S_THROWNINFINITY6}, // S_THROWNINFINITY5
-	{SPR_RNGI, 32793, 1, {A_ThrownRing}, 0, 0, S_THROWNINFINITY7}, // S_THROWNINFINITY6
-	{SPR_RNGI, 32798, 1, {A_ThrownRing}, 0, 0, S_THROWNINFINITY1}, // S_THROWNINFINITY7
-
-	{SPR_TAUT, 32768, 1, {A_ThrownRing}, 0, 0, S_THROWNAUTOMATIC2}, // S_THROWNAUTOMATIC1
-	{SPR_TAUT, 32769, 1, {A_ThrownRing}, 0, 0, S_THROWNAUTOMATIC3}, // S_THROWNAUTOMATIC2
-	{SPR_TAUT, 32770, 1, {A_ThrownRing}, 0, 0, S_THROWNAUTOMATIC4}, // S_THROWNAUTOMATIC3
-	{SPR_TAUT, 32771, 1, {A_ThrownRing}, 0, 0, S_THROWNAUTOMATIC5}, // S_THROWNAUTOMATIC4
-	{SPR_TAUT, 32772, 1, {A_ThrownRing}, 0, 0, S_THROWNAUTOMATIC6}, // S_THROWNAUTOMATIC5
-	{SPR_TAUT, 32773, 1, {A_ThrownRing}, 0, 0, S_THROWNAUTOMATIC7}, // S_THROWNAUTOMATIC6
-	{SPR_TAUT, 32774, 1, {A_ThrownRing}, 0, 0, S_THROWNAUTOMATIC1}, // S_THROWNAUTOMATIC7
-
-	{SPR_RNGE, 32768, 1, {A_ThrownRing}, 0, 0, S_THROWNEXPLOSION2}, // S_THROWNEXPLOSION1
-	{SPR_RNGE, 32773, 1, {A_ThrownRing}, 0, 0, S_THROWNEXPLOSION3}, // S_THROWNEXPLOSION2
-	{SPR_RNGE, 32778, 1, {A_ThrownRing}, 0, 0, S_THROWNEXPLOSION4}, // S_THROWNEXPLOSION3
-	{SPR_RNGE, 32783, 1, {A_ThrownRing}, 0, 0, S_THROWNEXPLOSION5}, // S_THROWNEXPLOSION4
-	{SPR_RNGE, 32788, 1, {A_ThrownRing}, 0, 0, S_THROWNEXPLOSION6}, // S_THROWNEXPLOSION5
-	{SPR_RNGE, 32793, 1, {A_ThrownRing}, 0, 0, S_THROWNEXPLOSION7}, // S_THROWNEXPLOSION6
-	{SPR_RNGE, 32798, 1, {A_ThrownRing}, 0, 0, S_THROWNEXPLOSION1}, // S_THROWNEXPLOSION7
-
-	{SPR_TGRE, 32768, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE2},  // S_THROWNGRENADE1
-	{SPR_TGRE, 32769, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE3},  // S_THROWNGRENADE2
-	{SPR_TGRE, 32770, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE4},  // S_THROWNGRENADE3
-	{SPR_TGRE, 32771, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE5},  // S_THROWNGRENADE4
-	{SPR_TGRE, 32772, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE6},  // S_THROWNGRENADE5
-	{SPR_TGRE, 32773, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE7},  // S_THROWNGRENADE6
-	{SPR_TGRE, 32774, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE8},  // S_THROWNGRENADE7
-	{SPR_TGRE, 32775, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE9},  // S_THROWNGRENADE8
-	{SPR_TGRE, 32776, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE10}, // S_THROWNGRENADE9
-	{SPR_TGRE, 32777, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE11}, // S_THROWNGRENADE10
-	{SPR_TGRE, 32778, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE12}, // S_THROWNGRENADE11
-	{SPR_TGRE, 32779, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE13}, // S_THROWNGRENADE12
-	{SPR_TGRE, 32780, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE14}, // S_THROWNGRENADE13
-	{SPR_TGRE, 32781, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE15}, // S_THROWNGRENADE14
-	{SPR_TGRE, 32782, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE16}, // S_THROWNGRENADE15
-	{SPR_TGRE, 32783, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE17}, // S_THROWNGRENADE16
-	{SPR_TGRE, 32784, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE18}, // S_THROWNGRENADE17
-	{SPR_TGRE, 32785, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE1},  // S_THROWNGRENADE18
-
-	{SPR_TSCR, 0, 1, {A_ThrownRing}, 0, 0, S_THROWNSCATTER}, // S_THROWNSCATTER
+	{SPR_RNGB, FF_FULLBRIGHT   , 1, {A_ThrownRing}, 0, 0, S_THROWNBOUNCE2}, // S_THROWNBOUNCE1
+	{SPR_RNGB, FF_FULLBRIGHT| 5, 1, {A_ThrownRing}, 0, 0, S_THROWNBOUNCE3}, // S_THROWNBOUNCE2
+	{SPR_RNGB, FF_FULLBRIGHT|10, 1, {A_ThrownRing}, 0, 0, S_THROWNBOUNCE4}, // S_THROWNBOUNCE3
+	{SPR_RNGB, FF_FULLBRIGHT|15, 1, {A_ThrownRing}, 0, 0, S_THROWNBOUNCE5}, // S_THROWNBOUNCE4
+	{SPR_RNGB, FF_FULLBRIGHT|20, 1, {A_ThrownRing}, 0, 0, S_THROWNBOUNCE6}, // S_THROWNBOUNCE5
+	{SPR_RNGB, FF_FULLBRIGHT|25, 1, {A_ThrownRing}, 0, 0, S_THROWNBOUNCE7}, // S_THROWNBOUNCE6
+	{SPR_RNGB, FF_FULLBRIGHT|30, 1, {A_ThrownRing}, 0, 0, S_THROWNBOUNCE1}, // S_THROWNBOUNCE7
+
+	{SPR_RNGI, FF_FULLBRIGHT   , 1, {A_ThrownRing}, 0, 0, S_THROWNINFINITY2}, // S_THROWNINFINITY1
+	{SPR_RNGI, FF_FULLBRIGHT| 5, 1, {A_ThrownRing}, 0, 0, S_THROWNINFINITY3}, // S_THROWNINFINITY2
+	{SPR_RNGI, FF_FULLBRIGHT|10, 1, {A_ThrownRing}, 0, 0, S_THROWNINFINITY4}, // S_THROWNINFINITY3
+	{SPR_RNGI, FF_FULLBRIGHT|15, 1, {A_ThrownRing}, 0, 0, S_THROWNINFINITY5}, // S_THROWNINFINITY4
+	{SPR_RNGI, FF_FULLBRIGHT|20, 1, {A_ThrownRing}, 0, 0, S_THROWNINFINITY6}, // S_THROWNINFINITY5
+	{SPR_RNGI, FF_FULLBRIGHT|25, 1, {A_ThrownRing}, 0, 0, S_THROWNINFINITY7}, // S_THROWNINFINITY6
+	{SPR_RNGI, FF_FULLBRIGHT|30, 1, {A_ThrownRing}, 0, 0, S_THROWNINFINITY1}, // S_THROWNINFINITY7
+
+	{SPR_TAUT, FF_FULLBRIGHT  , 1, {A_ThrownRing}, 0, 0, S_THROWNAUTOMATIC2}, // S_THROWNAUTOMATIC1
+	{SPR_TAUT, FF_FULLBRIGHT|1, 1, {A_ThrownRing}, 0, 0, S_THROWNAUTOMATIC3}, // S_THROWNAUTOMATIC2
+	{SPR_TAUT, FF_FULLBRIGHT|2, 1, {A_ThrownRing}, 0, 0, S_THROWNAUTOMATIC4}, // S_THROWNAUTOMATIC3
+	{SPR_TAUT, FF_FULLBRIGHT|3, 1, {A_ThrownRing}, 0, 0, S_THROWNAUTOMATIC5}, // S_THROWNAUTOMATIC4
+	{SPR_TAUT, FF_FULLBRIGHT|4, 1, {A_ThrownRing}, 0, 0, S_THROWNAUTOMATIC6}, // S_THROWNAUTOMATIC5
+	{SPR_TAUT, FF_FULLBRIGHT|5, 1, {A_ThrownRing}, 0, 0, S_THROWNAUTOMATIC7}, // S_THROWNAUTOMATIC6
+	{SPR_TAUT, FF_FULLBRIGHT|6, 1, {A_ThrownRing}, 0, 0, S_THROWNAUTOMATIC1}, // S_THROWNAUTOMATIC7
+
+	{SPR_RNGE, FF_FULLBRIGHT   , 1, {A_ThrownRing}, 0, 0, S_THROWNEXPLOSION2}, // S_THROWNEXPLOSION1
+	{SPR_RNGE, FF_FULLBRIGHT| 5, 1, {A_ThrownRing}, 0, 0, S_THROWNEXPLOSION3}, // S_THROWNEXPLOSION2
+	{SPR_RNGE, FF_FULLBRIGHT|10, 1, {A_ThrownRing}, 0, 0, S_THROWNEXPLOSION4}, // S_THROWNEXPLOSION3
+	{SPR_RNGE, FF_FULLBRIGHT|15, 1, {A_ThrownRing}, 0, 0, S_THROWNEXPLOSION5}, // S_THROWNEXPLOSION4
+	{SPR_RNGE, FF_FULLBRIGHT|20, 1, {A_ThrownRing}, 0, 0, S_THROWNEXPLOSION6}, // S_THROWNEXPLOSION5
+	{SPR_RNGE, FF_FULLBRIGHT|25, 1, {A_ThrownRing}, 0, 0, S_THROWNEXPLOSION7}, // S_THROWNEXPLOSION6
+	{SPR_RNGE, FF_FULLBRIGHT|30, 1, {A_ThrownRing}, 0, 0, S_THROWNEXPLOSION1}, // S_THROWNEXPLOSION7
+
+	{SPR_TGRE, FF_FULLBRIGHT   , 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE2},  // S_THROWNGRENADE1
+	{SPR_TGRE, FF_FULLBRIGHT| 1, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE3},  // S_THROWNGRENADE2
+	{SPR_TGRE, FF_FULLBRIGHT| 2, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE4},  // S_THROWNGRENADE3
+	{SPR_TGRE, FF_FULLBRIGHT| 3, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE5},  // S_THROWNGRENADE4
+	{SPR_TGRE, FF_FULLBRIGHT| 4, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE6},  // S_THROWNGRENADE5
+	{SPR_TGRE, FF_FULLBRIGHT| 5, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE7},  // S_THROWNGRENADE6
+	{SPR_TGRE, FF_FULLBRIGHT| 6, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE8},  // S_THROWNGRENADE7
+	{SPR_TGRE, FF_FULLBRIGHT| 7, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE9},  // S_THROWNGRENADE8
+	{SPR_TGRE, FF_FULLBRIGHT| 8, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE10}, // S_THROWNGRENADE9
+	{SPR_TGRE, FF_FULLBRIGHT| 9, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE11}, // S_THROWNGRENADE10
+	{SPR_TGRE, FF_FULLBRIGHT|10, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE12}, // S_THROWNGRENADE11
+	{SPR_TGRE, FF_FULLBRIGHT|11, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE13}, // S_THROWNGRENADE12
+	{SPR_TGRE, FF_FULLBRIGHT|12, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE14}, // S_THROWNGRENADE13
+	{SPR_TGRE, FF_FULLBRIGHT|13, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE15}, // S_THROWNGRENADE14
+	{SPR_TGRE, FF_FULLBRIGHT|14, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE16}, // S_THROWNGRENADE15
+	{SPR_TGRE, FF_FULLBRIGHT|15, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE17}, // S_THROWNGRENADE16
+	{SPR_TGRE, FF_FULLBRIGHT|16, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE18}, // S_THROWNGRENADE17
+	{SPR_TGRE, FF_FULLBRIGHT|17, 1, {A_ThrownRing}, 0, 0, S_THROWNGRENADE1},  // S_THROWNGRENADE18
+
+	{SPR_TSCR, FF_FULLBRIGHT, 1, {A_ThrownRing}, 0, 0, S_THROWNSCATTER}, // S_THROWNSCATTER
 
 	{SPR_NULL, 0, 1, {A_RingExplode}, 0, 0, S_XPLD1}, // S_RINGEXPLODE
 
@@ -2813,15 +2358,15 @@ state_t states[NUMSTATES] =
 	{SPR_NULL, 0, 35, {NULL}, 0, 0, S_CRUMBLE2},  // S_CRUMBLE1
 	{SPR_NULL, 0, 105, {A_Scream}, 0, 0, S_NULL}, // S_CRUMBLE2
 
-	{SPR_SUPT, 0,     4, {A_Scream}, 0, 0,  S_SUPERTRANS2}, // S_SUPERTRANS1
-	{SPR_SUPT, 1,     4, {NULL}, 0, 0,  S_SUPERTRANS3}, // S_SUPERTRANS2
-	{SPR_SUPT, 32770, 4, {NULL}, 0, 0,  S_SUPERTRANS4}, // S_SUPERTRANS3
-	{SPR_SUPT, 3,     3, {NULL}, 0, 0,  S_SUPERTRANS5}, // S_SUPERTRANS4
-	{SPR_SUPT, 4,     3, {NULL}, 0, 0,  S_SUPERTRANS6}, // S_SUPERTRANS5
-	{SPR_SUPT, 5,     3, {NULL}, 0, 0,  S_SUPERTRANS7}, // S_SUPERTRANS6
-	{SPR_SUPT, 6,     3, {NULL}, 0, 0,  S_SUPERTRANS8}, // S_SUPERTRANS7
-	{SPR_SUPT, 7,     3, {NULL}, 0, 0,  S_SUPERTRANS9}, // S_SUPERTRANS8
-	{SPR_SUPT, 8,    16, {NULL}, 0, 0, S_NIGHTSDRONE1}, // S_SUPERTRANS9
+	{SPR_SUPT,               0,  4, {A_Scream}, 0, 0,  S_SUPERTRANS2}, // S_SUPERTRANS1
+	{SPR_SUPT,               1,  4, {NULL}, 0, 0,  S_SUPERTRANS3}, // S_SUPERTRANS2
+	{SPR_SUPT, FF_FULLBRIGHT|2,  4, {NULL}, 0, 0,  S_SUPERTRANS4}, // S_SUPERTRANS3
+	{SPR_SUPT,               3,  3, {NULL}, 0, 0,  S_SUPERTRANS5}, // S_SUPERTRANS4
+	{SPR_SUPT,               4,  3, {NULL}, 0, 0,  S_SUPERTRANS6}, // S_SUPERTRANS5
+	{SPR_SUPT,               5,  3, {NULL}, 0, 0,  S_SUPERTRANS7}, // S_SUPERTRANS6
+	{SPR_SUPT,               6,  3, {NULL}, 0, 0,  S_SUPERTRANS8}, // S_SUPERTRANS7
+	{SPR_SUPT,               7,  3, {NULL}, 0, 0,  S_SUPERTRANS9}, // S_SUPERTRANS8
+	{SPR_SUPT,               8, 16, {NULL}, 0, 0, S_NIGHTSDRONE1}, // S_SUPERTRANS9
 
 	// Spark
 	{SPR_SPRK, FF_TRANS40  , 1, {NULL}, 0, 0, S_SPRK2},  // S_SPRK1
@@ -2857,101 +2402,22 @@ state_t states[NUMSTATES] =
 
 	{SPR_NULL, 0, 1, {A_RockSpawn}, 0, 0, S_ROCKSPAWN}, // S_ROCKSPAWN
 
-	{SPR_ROIA, 0, 2, {NULL}, 0, 0, S_ROCKCRUMBLEA2}, // S_ROCKCRUMBLEA1
-	{SPR_ROIA, 1, 2, {NULL}, 0, 0, S_ROCKCRUMBLEA3}, // S_ROCKCRUMBLEA2
-	{SPR_ROIA, 2, 2, {NULL}, 0, 0, S_ROCKCRUMBLEA4}, // S_ROCKCRUMBLEA3
-	{SPR_ROIA, 3, 2, {NULL}, 0, 0, S_ROCKCRUMBLEA5}, // S_ROCKCRUMBLEA4
-	{SPR_ROIA, 4, 2, {NULL}, 0, 0, S_ROCKCRUMBLEA1}, // S_ROCKCRUMBLEA5
-
-	{SPR_ROIB, 0, 2, {NULL}, 0, 0, S_ROCKCRUMBLEB2}, // S_ROCKCRUMBLEB1
-	{SPR_ROIB, 1, 2, {NULL}, 0, 0, S_ROCKCRUMBLEB3}, // S_ROCKCRUMBLEB2
-	{SPR_ROIB, 2, 2, {NULL}, 0, 0, S_ROCKCRUMBLEB4}, // S_ROCKCRUMBLEB3
-	{SPR_ROIB, 3, 2, {NULL}, 0, 0, S_ROCKCRUMBLEB5}, // S_ROCKCRUMBLEB4
-	{SPR_ROIB, 4, 2, {NULL}, 0, 0, S_ROCKCRUMBLEB1}, // S_ROCKCRUMBLEB5
-
-	{SPR_ROIC, 0, 2, {NULL}, 0, 0, S_ROCKCRUMBLEC2}, // S_ROCKCRUMBLEC1
-	{SPR_ROIC, 1, 2, {NULL}, 0, 0, S_ROCKCRUMBLEC3}, // S_ROCKCRUMBLEC2
-	{SPR_ROIC, 2, 2, {NULL}, 0, 0, S_ROCKCRUMBLEC4}, // S_ROCKCRUMBLEC3
-	{SPR_ROIC, 3, 2, {NULL}, 0, 0, S_ROCKCRUMBLEC5}, // S_ROCKCRUMBLEC4
-	{SPR_ROIC, 4, 2, {NULL}, 0, 0, S_ROCKCRUMBLEC1}, // S_ROCKCRUMBLEC5
-
-	{SPR_ROID, 0, 2, {NULL}, 0, 0, S_ROCKCRUMBLED2}, // S_ROCKCRUMBLED1
-	{SPR_ROID, 1, 2, {NULL}, 0, 0, S_ROCKCRUMBLED3}, // S_ROCKCRUMBLED2
-	{SPR_ROID, 2, 2, {NULL}, 0, 0, S_ROCKCRUMBLED4}, // S_ROCKCRUMBLED3
-	{SPR_ROID, 3, 2, {NULL}, 0, 0, S_ROCKCRUMBLED5}, // S_ROCKCRUMBLED4
-	{SPR_ROID, 4, 2, {NULL}, 0, 0, S_ROCKCRUMBLED1}, // S_ROCKCRUMBLED5
-
-	{SPR_ROIE, 0, 2, {NULL}, 0, 0, S_ROCKCRUMBLEE2}, // S_ROCKCRUMBLEE1
-	{SPR_ROIE, 1, 2, {NULL}, 0, 0, S_ROCKCRUMBLEE3}, // S_ROCKCRUMBLEE2
-	{SPR_ROIE, 2, 2, {NULL}, 0, 0, S_ROCKCRUMBLEE4}, // S_ROCKCRUMBLEE3
-	{SPR_ROIE, 3, 2, {NULL}, 0, 0, S_ROCKCRUMBLEE5}, // S_ROCKCRUMBLEE4
-	{SPR_ROIE, 4, 2, {NULL}, 0, 0, S_ROCKCRUMBLEE1}, // S_ROCKCRUMBLEE5
-
-	{SPR_ROIF, 0, 2, {NULL}, 0, 0, S_ROCKCRUMBLEF2}, // S_ROCKCRUMBLEF1
-	{SPR_ROIF, 1, 2, {NULL}, 0, 0, S_ROCKCRUMBLEF3}, // S_ROCKCRUMBLEF2
-	{SPR_ROIF, 2, 2, {NULL}, 0, 0, S_ROCKCRUMBLEF4}, // S_ROCKCRUMBLEF3
-	{SPR_ROIF, 3, 2, {NULL}, 0, 0, S_ROCKCRUMBLEF5}, // S_ROCKCRUMBLEF4
-	{SPR_ROIF, 4, 2, {NULL}, 0, 0, S_ROCKCRUMBLEF1}, // S_ROCKCRUMBLEF5
-
-	{SPR_ROIG, 0, 2, {NULL}, 0, 0, S_ROCKCRUMBLEG2}, // S_ROCKCRUMBLEG1
-	{SPR_ROIG, 1, 2, {NULL}, 0, 0, S_ROCKCRUMBLEG3}, // S_ROCKCRUMBLEG2
-	{SPR_ROIG, 2, 2, {NULL}, 0, 0, S_ROCKCRUMBLEG4}, // S_ROCKCRUMBLEG3
-	{SPR_ROIG, 3, 2, {NULL}, 0, 0, S_ROCKCRUMBLEG5}, // S_ROCKCRUMBLEG4
-	{SPR_ROIG, 4, 2, {NULL}, 0, 0, S_ROCKCRUMBLEG1}, // S_ROCKCRUMBLEG5
-
-	{SPR_ROIH, 0, 2, {NULL}, 0, 0, S_ROCKCRUMBLEH2}, // S_ROCKCRUMBLEH1
-	{SPR_ROIH, 1, 2, {NULL}, 0, 0, S_ROCKCRUMBLEH3}, // S_ROCKCRUMBLEH2
-	{SPR_ROIH, 2, 2, {NULL}, 0, 0, S_ROCKCRUMBLEH4}, // S_ROCKCRUMBLEH3
-	{SPR_ROIH, 3, 2, {NULL}, 0, 0, S_ROCKCRUMBLEH5}, // S_ROCKCRUMBLEH4
-	{SPR_ROIH, 4, 2, {NULL}, 0, 0, S_ROCKCRUMBLEH1}, // S_ROCKCRUMBLEH5
-
-	{SPR_ROII, 0, 2, {NULL}, 0, 0, S_ROCKCRUMBLEI2}, // S_ROCKCRUMBLEI1
-	{SPR_ROII, 1, 2, {NULL}, 0, 0, S_ROCKCRUMBLEI3}, // S_ROCKCRUMBLEI2
-	{SPR_ROII, 2, 2, {NULL}, 0, 0, S_ROCKCRUMBLEI4}, // S_ROCKCRUMBLEI3
-	{SPR_ROII, 3, 2, {NULL}, 0, 0, S_ROCKCRUMBLEI5}, // S_ROCKCRUMBLEI4
-	{SPR_ROII, 4, 2, {NULL}, 0, 0, S_ROCKCRUMBLEI1}, // S_ROCKCRUMBLEI5
-
-	{SPR_ROIJ, 0, 2, {NULL}, 0, 0, S_ROCKCRUMBLEJ2}, // S_ROCKCRUMBLEJ1
-	{SPR_ROIJ, 1, 2, {NULL}, 0, 0, S_ROCKCRUMBLEJ3}, // S_ROCKCRUMBLEJ2
-	{SPR_ROIJ, 2, 2, {NULL}, 0, 0, S_ROCKCRUMBLEJ4}, // S_ROCKCRUMBLEJ3
-	{SPR_ROIJ, 3, 2, {NULL}, 0, 0, S_ROCKCRUMBLEJ5}, // S_ROCKCRUMBLEJ4
-	{SPR_ROIJ, 4, 2, {NULL}, 0, 0, S_ROCKCRUMBLEJ1}, // S_ROCKCRUMBLEJ5
-
-	{SPR_ROIK, 0, 2, {NULL}, 0, 0, S_ROCKCRUMBLEK2}, // S_ROCKCRUMBLEK1
-	{SPR_ROIK, 1, 2, {NULL}, 0, 0, S_ROCKCRUMBLEK3}, // S_ROCKCRUMBLEK2
-	{SPR_ROIK, 2, 2, {NULL}, 0, 0, S_ROCKCRUMBLEK4}, // S_ROCKCRUMBLEK3
-	{SPR_ROIK, 3, 2, {NULL}, 0, 0, S_ROCKCRUMBLEK5}, // S_ROCKCRUMBLEK4
-	{SPR_ROIK, 4, 2, {NULL}, 0, 0, S_ROCKCRUMBLEK1}, // S_ROCKCRUMBLEK5
-
-	{SPR_ROIL, 0, 2, {NULL}, 0, 0, S_ROCKCRUMBLEL2}, // S_ROCKCRUMBLEL1
-	{SPR_ROIL, 1, 2, {NULL}, 0, 0, S_ROCKCRUMBLEL3}, // S_ROCKCRUMBLEL2
-	{SPR_ROIL, 2, 2, {NULL}, 0, 0, S_ROCKCRUMBLEL4}, // S_ROCKCRUMBLEL3
-	{SPR_ROIL, 3, 2, {NULL}, 0, 0, S_ROCKCRUMBLEL5}, // S_ROCKCRUMBLEL4
-	{SPR_ROIL, 4, 2, {NULL}, 0, 0, S_ROCKCRUMBLEL1}, // S_ROCKCRUMBLEL5
-
-	{SPR_ROIM, 0, 2, {NULL}, 0, 0, S_ROCKCRUMBLEM2}, // S_ROCKCRUMBLEM1
-	{SPR_ROIM, 1, 2, {NULL}, 0, 0, S_ROCKCRUMBLEM3}, // S_ROCKCRUMBLEM2
-	{SPR_ROIM, 2, 2, {NULL}, 0, 0, S_ROCKCRUMBLEM4}, // S_ROCKCRUMBLEM3
-	{SPR_ROIM, 3, 2, {NULL}, 0, 0, S_ROCKCRUMBLEM5}, // S_ROCKCRUMBLEM4
-	{SPR_ROIM, 4, 2, {NULL}, 0, 0, S_ROCKCRUMBLEM1}, // S_ROCKCRUMBLEM5
-
-	{SPR_ROIN, 0, 2, {NULL}, 0, 0, S_ROCKCRUMBLEN2}, // S_ROCKCRUMBLEN1
-	{SPR_ROIN, 1, 2, {NULL}, 0, 0, S_ROCKCRUMBLEN3}, // S_ROCKCRUMBLEN2
-	{SPR_ROIN, 2, 2, {NULL}, 0, 0, S_ROCKCRUMBLEN4}, // S_ROCKCRUMBLEN3
-	{SPR_ROIN, 3, 2, {NULL}, 0, 0, S_ROCKCRUMBLEN5}, // S_ROCKCRUMBLEN4
-	{SPR_ROIN, 4, 2, {NULL}, 0, 0, S_ROCKCRUMBLEN1}, // S_ROCKCRUMBLEN5
-
-	{SPR_ROIO, 0, 2, {NULL}, 0, 0, S_ROCKCRUMBLEO2}, // S_ROCKCRUMBLEO1
-	{SPR_ROIO, 1, 2, {NULL}, 0, 0, S_ROCKCRUMBLEO3}, // S_ROCKCRUMBLEO2
-	{SPR_ROIO, 2, 2, {NULL}, 0, 0, S_ROCKCRUMBLEO4}, // S_ROCKCRUMBLEO3
-	{SPR_ROIO, 3, 2, {NULL}, 0, 0, S_ROCKCRUMBLEO5}, // S_ROCKCRUMBLEO4
-	{SPR_ROIO, 4, 2, {NULL}, 0, 0, S_ROCKCRUMBLEO1}, // S_ROCKCRUMBLEO5
-
-	{SPR_ROIP, 0, 2, {NULL}, 0, 0, S_ROCKCRUMBLEP2}, // S_ROCKCRUMBLEP1
-	{SPR_ROIP, 1, 2, {NULL}, 0, 0, S_ROCKCRUMBLEP3}, // S_ROCKCRUMBLEP2
-	{SPR_ROIP, 2, 2, {NULL}, 0, 0, S_ROCKCRUMBLEP4}, // S_ROCKCRUMBLEP3
-	{SPR_ROIP, 3, 2, {NULL}, 0, 0, S_ROCKCRUMBLEP5}, // S_ROCKCRUMBLEP4
-	{SPR_ROIP, 4, 2, {NULL}, 0, 0, S_ROCKCRUMBLEP1}, // S_ROCKCRUMBLEP5
+	{SPR_ROIA, FF_ANIMATE, -1, {NULL}, 4, 2, S_ROCKCRUMBLEA}, // S_ROCKCRUMBLEA
+	{SPR_ROIB, FF_ANIMATE, -1, {NULL}, 4, 2, S_ROCKCRUMBLEB}, // S_ROCKCRUMBLEB
+	{SPR_ROIC, FF_ANIMATE, -1, {NULL}, 4, 2, S_ROCKCRUMBLEC}, // S_ROCKCRUMBLEC
+	{SPR_ROID, FF_ANIMATE, -1, {NULL}, 4, 2, S_ROCKCRUMBLED}, // S_ROCKCRUMBLED
+	{SPR_ROIE, FF_ANIMATE, -1, {NULL}, 4, 2, S_ROCKCRUMBLEE}, // S_ROCKCRUMBLEE
+	{SPR_ROIF, FF_ANIMATE, -1, {NULL}, 4, 2, S_ROCKCRUMBLEF}, // S_ROCKCRUMBLEF
+	{SPR_ROIG, FF_ANIMATE, -1, {NULL}, 4, 2, S_ROCKCRUMBLEG}, // S_ROCKCRUMBLEG
+	{SPR_ROIH, FF_ANIMATE, -1, {NULL}, 4, 2, S_ROCKCRUMBLEH}, // S_ROCKCRUMBLEH
+	{SPR_ROII, FF_ANIMATE, -1, {NULL}, 4, 2, S_ROCKCRUMBLEI}, // S_ROCKCRUMBLEI
+	{SPR_ROIJ, FF_ANIMATE, -1, {NULL}, 4, 2, S_ROCKCRUMBLEJ}, // S_ROCKCRUMBLEJ
+	{SPR_ROIK, FF_ANIMATE, -1, {NULL}, 4, 2, S_ROCKCRUMBLEK}, // S_ROCKCRUMBLEK
+	{SPR_ROIL, FF_ANIMATE, -1, {NULL}, 4, 2, S_ROCKCRUMBLEL}, // S_ROCKCRUMBLEL
+	{SPR_ROIM, FF_ANIMATE, -1, {NULL}, 4, 2, S_ROCKCRUMBLEM}, // S_ROCKCRUMBLEM
+	{SPR_ROIN, FF_ANIMATE, -1, {NULL}, 4, 2, S_ROCKCRUMBLEN}, // S_ROCKCRUMBLEN
+	{SPR_ROIO, FF_ANIMATE, -1, {NULL}, 4, 2, S_ROCKCRUMBLEO}, // S_ROCKCRUMBLEO
+	{SPR_ROIP, FF_ANIMATE, -1, {NULL}, 4, 2, S_ROCKCRUMBLEP}, // S_ROCKCRUMBLEP
 
 	{SPR_SRBA, 0, 5, {A_Look}, 0, 0, S_SRB1_CRAWLA1}, // S_SRB1_CRAWLA1
 	{SPR_SRBA, 0, 3, {A_Chase}, 0, 0, S_SRB1_CRAWLA3}, // S_SRB1_CRAWLA2
@@ -5051,7 +4517,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 
 	{           // MT_RING
 		300,            // doomednum
-		S_RING1,        // spawnstate
+		S_RING,         // spawnstate
 		1000,           // spawnhealth
 		S_NULL,         // seestate
 		sfx_None,       // seesound
@@ -5078,7 +4544,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 
 	{           // MT_FLINGRING
 		-1,             // doomednum
-		S_RING1,        // spawnstate
+		S_RING,         // spawnstate
 		1000,           // spawnhealth
 		S_NULL,         // seestate
 		sfx_None,       // seesound
@@ -5134,7 +4600,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 
 	{           // MT_REDTEAMRING
 		308,            // doomednum
-		S_TEAMRING1,    // spawnstate
+		S_TEAMRING,     // spawnstate
 		1000,           // spawnhealth
 		S_NULL,         // seestate
 		sfx_None,       // seesound
@@ -5161,7 +4627,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 
 	{           // MT_BLUETEAMRING
 		309,            // doomednum
-		S_TEAMRING1,    // spawnstate
+		S_TEAMRING,     // spawnstate
 		1000,           // spawnhealth
 		S_NULL,         // seestate
 		sfx_None,       // seesound
@@ -5188,7 +4654,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 
 	{           // MT_EMMY
 		312,            // doomednum
-		S_EMMY1,        // spawnstate
+		S_EMMY,         // spawnstate
 		1000,           // spawnhealth
 		S_NULL,         // seestate
 		sfx_None,       // seesound
@@ -5938,13 +5404,13 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 
 	{           // MT_STARPOST
 		502,            // doomednum
-		S_STARPOST1,    // spawnstate
+		S_STARPOST_IDLE, // spawnstate
 		1,              // spawnhealth
-		S_STARPOST2,    // seestate
+		S_STARPOST_FLASH, // seestate
 		sfx_None,       // seesound
 		8,              // reactiontime
 		sfx_None,       // attacksound
-		S_STARPOST4,    // painstate
+		S_STARPOST_SPIN, // painstate
 		0,              // painchance
 		sfx_strpst,     // painsound
 		S_NULL,         // meleestate
@@ -10481,7 +9947,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 
 	{           // MT_IVSP
 		-1,             // doomednum
-		S_IVSP1,        // spawnstate
+		S_IVSP,         // spawnstate
 		1000,           // spawnhealth
 		S_NULL,         // seestate
 		sfx_None,       // seesound
@@ -11463,7 +10929,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 // Ring ammo: Health = amount given
 	{           // MT_BOUNCERING
 		301,            // doomednum
-		S_BOUNCERING1,  // spawnstate
+		S_BOUNCERINGAMMO, // spawnstate
 		10,             // spawnhealth
 		S_NULL,         // seestate
 		sfx_None,       // seesound
@@ -11490,7 +10956,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 
 	{           // MT_RAILRING
 		302,            // doomednum
-		S_RAILRING1,    // spawnstate
+		S_RAILRINGAMMO, // spawnstate
 		5,              // spawnhealth
 		S_NULL,         // seestate
 		sfx_None,       // seesound
@@ -11517,7 +10983,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 
 	{           // MT_INFINITYRING
 		303,            // doomednum
-		S_INFINITYRING1,// spawnstate
+		S_INFINITYRINGAMMO,// spawnstate
 		80,             // spawnhealth
 		S_NULL,         // seestate
 		sfx_None,       // seesound
@@ -11544,7 +11010,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 
 	{           // MT_AUTOMATICRING
 		304,            // doomednum
-		S_AUTOMATICRING1, // spawnstate
+		S_AUTOMATICRINGAMMO, // spawnstate
 		40,             // spawnhealth
 		S_NULL,         // seestate
 		sfx_None,       // seesound
@@ -11571,7 +11037,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 
 	{           // MT_EXPLOSIONRING
 		305,            // doomednum
-		S_EXPLOSIONRING1, // spawnstate
+		S_EXPLOSIONRINGAMMO, // spawnstate
 		5,              // spawnhealth
 		S_NULL,         // seestate
 		sfx_None,       // seesound
@@ -11598,7 +11064,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 
 	{           // MT_SCATTERRING
 		306,            // doomednum
-		S_SCATTERRING1, // spawnstate
+		S_SCATTERRINGAMMO, // spawnstate
 		5,              // spawnhealth
 		S_NULL,         // seestate
 		sfx_None,       // seesound
@@ -11625,7 +11091,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 
 	{           // MT_GRENADERING
 		307,            // doomednum
-		S_GRENADERING1, // spawnstate
+		S_GRENADERINGAMMO, // spawnstate
 		10,             // spawnhealth
 		S_NULL,         // seestate
 		sfx_None,       // seesound
@@ -11653,7 +11119,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 // Ring panels: Reactiontime = amount given
 	{           // MT_BOUNCEPICKUP
 		330,            // doomednum
-		S_BOUNCEPICKUP1,// spawnstate
+		S_BOUNCEPICKUP, // spawnstate
 		1,              // spawnhealth
 		S_NULL,         // seestate
 		sfx_None,       // seesound
@@ -11680,7 +11146,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 
 	{           // MT_RAILPICKUP
 		331,            // doomednum
-		S_RAILPICKUP1,  // spawnstate
+		S_RAILPICKUP,   // spawnstate
 		1,              // spawnhealth
 		S_NULL,         // seestate
 		sfx_None,       // seesound
@@ -11707,7 +11173,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 
 	{           // MT_AUTOPICKUP
 		332,            // doomednum
-		S_AUTOPICKUP1,  // spawnstate
+		S_AUTOPICKUP,   // spawnstate
 		1,              // spawnhealth
 		S_NULL,         // seestate
 		sfx_None,       // seesound
@@ -11734,7 +11200,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 
 	{           // MT_EXPLODEPICKUP
 		333,            // doomednum
-		S_EXPLODEPICKUP1,// spawnstate
+		S_EXPLODEPICKUP,// spawnstate
 		1,              // spawnhealth
 		S_NULL,         // seestate
 		sfx_None,       // seesound
@@ -11761,7 +11227,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 
 	{           // MT_SCATTERPICKUP
 		334,            // doomednum
-		S_SCATTERPICKUP1,// spawnstate
+		S_SCATTERPICKUP,// spawnstate
 		1,              // spawnhealth
 		S_NULL,         // seestate
 		sfx_None,       // seesound
@@ -11788,7 +11254,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 
 	{           // MT_GRENADEPICKUP
 		335,            // doomednum
-		S_GRENADEPICKUP1,// spawnstate
+		S_GRENADEPICKUP,// spawnstate
 		1,              // spawnhealth
 		S_NULL,         // seestate
 		sfx_None,       // seesound
@@ -12740,7 +12206,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 		S_NULL,         // painstate
 		0,              // painchance
 		sfx_itemup,     // painsound
-		S_RING1,        // meleestate
+		S_RING,         // meleestate
 		S_NULL,         // missilestate
 		S_SPRK1,        // deathstate
 		S_NULL,         // xdeathstate
@@ -13383,7 +12849,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 
 	{           // MT_FALLINGROCK
 		-1,             // doomednum
-		S_ROCKCRUMBLEA1,// spawnstate
+		S_ROCKCRUMBLEA, // spawnstate
 		1000,           // spawnhealth
 		S_NULL,         // seestate
 		sfx_ambint,     // seesound
@@ -13410,7 +12876,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 
 	{           // MT_ROCKCRUMBLE1
 		-1,             // doomednum
-		S_ROCKCRUMBLEA1,// spawnstate
+		S_ROCKCRUMBLEA, // spawnstate
 		1000,           // spawnhealth
 		S_NULL,         // seestate
 		sfx_ambint,     // seesound
@@ -13437,7 +12903,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 
 	{           // MT_ROCKCRUMBLE2
 		-1,             // doomednum
-		S_ROCKCRUMBLEB1, // spawnstate
+		S_ROCKCRUMBLEB, // spawnstate
 		1000,           // spawnhealth
 		S_NULL,         // seestate
 		sfx_ambint,     // seesound
@@ -13464,7 +12930,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 
 	{           // MT_ROCKCRUMBLE3
 		-1,             // doomednum
-		S_ROCKCRUMBLEC1,// spawnstate
+		S_ROCKCRUMBLEC, //spawnstate
 		1000,           // spawnhealth
 		S_NULL,         // seestate
 		sfx_ambint,     // seesound
@@ -13491,7 +12957,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 
 	{           // MT_ROCKCRUMBLE4
 		-1,             // doomednum
-		S_ROCKCRUMBLED1,// spawnstate
+		S_ROCKCRUMBLED, // spawnstate
 		1000,           // spawnhealth
 		S_NULL,         // seestate
 		sfx_ambint,     // seesound
@@ -13518,7 +12984,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 
 	{           // MT_ROCKCRUMBLE5
 		-1,             // doomednum
-		S_ROCKCRUMBLEE1,// spawnstate
+		S_ROCKCRUMBLEE, // spawnstate
 		1000,           // spawnhealth
 		S_NULL,         // seestate
 		sfx_ambint,     // seesound
@@ -13545,7 +13011,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 
 	{           // MT_ROCKCRUMBLE6
 		-1,             // doomednum
-		S_ROCKCRUMBLEF1,// spawnstate
+		S_ROCKCRUMBLEF, // spawnstate
 		1000,           // spawnhealth
 		S_NULL,         // seestate
 		sfx_ambint,     // seesound
@@ -13572,7 +13038,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 
 	{           // MT_ROCKCRUMBLE7
 		-1,             // doomednum
-		S_ROCKCRUMBLEG1,// spawnstate
+		S_ROCKCRUMBLEG, // spawnstate
 		1000,           // spawnhealth
 		S_NULL,         // seestate
 		sfx_ambint,     // seesound
@@ -13599,7 +13065,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 
 	{           // MT_ROCKCRUMBLE8
 		-1,             // doomednum
-		S_ROCKCRUMBLEH1,// spawnstate
+		S_ROCKCRUMBLEH, // spawnstate
 		1000,           // spawnhealth
 		S_NULL,         // seestate
 		sfx_ambint,     // seesound
@@ -13626,7 +13092,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 
 	{           // MT_ROCKCRUMBLE9
 		-1,             // doomednum
-		S_ROCKCRUMBLEI1,// spawnstate
+		S_ROCKCRUMBLEI, // spawnstate
 		1000,           // spawnhealth
 		S_NULL,         // seestate
 		sfx_ambint,     // seesound
@@ -13653,7 +13119,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 
 	{           // MT_ROCKCRUMBLE10
 		-1,             // doomednum
-		S_ROCKCRUMBLEJ1,// spawnstate
+		S_ROCKCRUMBLEJ, // spawnstate
 		1000,           // spawnhealth
 		S_NULL,         // seestate
 		sfx_ambint,     // seesound
@@ -13680,7 +13146,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 
 	{           // MT_ROCKCRUMBLE11
 		-1,             // doomednum
-		S_ROCKCRUMBLEK1,// spawnstate
+		S_ROCKCRUMBLEK, // spawnstate
 		1000,           // spawnhealth
 		S_NULL,         // seestate
 		sfx_ambint,     // seesound
@@ -13707,7 +13173,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 
 	{           // MT_ROCKCRUMBLE12
 		-1,             // doomednum
-		S_ROCKCRUMBLEL1,// spawnstate
+		S_ROCKCRUMBLEL, // spawnstate
 		1000,           // spawnhealth
 		S_NULL,         // seestate
 		sfx_ambint,     // seesound
@@ -13734,7 +13200,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 
 	{           // MT_ROCKCRUMBLE13
 		-1,             // doomednum
-		S_ROCKCRUMBLEM1,// spawnstate
+		S_ROCKCRUMBLEM, // spawnstate
 		1000,           // spawnhealth
 		S_NULL,         // seestate
 		sfx_ambint,     // seesound
@@ -13761,7 +13227,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 
 	{           // MT_ROCKCRUMBLE14
 		-1,             // doomednum
-		S_ROCKCRUMBLEN1,// spawnstate
+		S_ROCKCRUMBLEN, // spawnstate
 		1000,           // spawnhealth
 		S_NULL,         // seestate
 		sfx_ambint,     // seesound
@@ -13788,7 +13254,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 
 	{           // MT_ROCKCRUMBLE15
 		-1,             // doomednum
-		S_ROCKCRUMBLEO1,// spawnstate
+		S_ROCKCRUMBLEO, // spawnstate
 		1000,           // spawnhealth
 		S_NULL,         // seestate
 		sfx_ambint,     // seesound
@@ -13815,7 +13281,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
 
 	{           // MT_ROCKCRUMBLE16
 		-1,             // doomednum
-		S_ROCKCRUMBLEP1,// spawnstate
+		S_ROCKCRUMBLEP, // spawnstate
 		1000,           // spawnhealth
 		S_NULL,         // seestate
 		sfx_ambint,     // seesound
diff --git a/src/info.h b/src/info.h
index 03726260b0b3261f83219951f1ae620306553598..9596f038421bd82f2b7c8b6235c63a8ce1994326 100644
--- a/src/info.h
+++ b/src/info.h
@@ -1433,30 +1433,7 @@ typedef enum state
 	S_MSSHIELD_F12,
 
 	// Ring
-	S_RING1,
-	S_RING2,
-	S_RING3,
-	S_RING4,
-	S_RING5,
-	S_RING6,
-	S_RING7,
-	S_RING8,
-	S_RING9,
-	S_RING10,
-	S_RING11,
-	S_RING12,
-	S_RING13,
-	S_RING14,
-	S_RING15,
-	S_RING16,
-	S_RING17,
-	S_RING18,
-	S_RING19,
-	S_RING20,
-	S_RING21,
-	S_RING22,
-	S_RING23,
-	S_RING24,
+	S_RING,
 
 	// Blue Sphere for special stages
 	S_BLUEBALL,
@@ -1472,39 +1449,10 @@ typedef enum state
 	S_GRAVWELLRED3,
 
 	// Individual Team Rings
-	S_TEAMRING1,
-	S_TEAMRING2,
-	S_TEAMRING3,
-	S_TEAMRING4,
-	S_TEAMRING5,
-	S_TEAMRING6,
-	S_TEAMRING7,
-	S_TEAMRING8,
-	S_TEAMRING9,
-	S_TEAMRING10,
-	S_TEAMRING11,
-	S_TEAMRING12,
-	S_TEAMRING13,
-	S_TEAMRING14,
-	S_TEAMRING15,
-	S_TEAMRING16,
-	S_TEAMRING17,
-	S_TEAMRING18,
-	S_TEAMRING19,
-	S_TEAMRING20,
-	S_TEAMRING21,
-	S_TEAMRING22,
-	S_TEAMRING23,
-	S_TEAMRING24,
+	S_TEAMRING,
 
 	// Special Stage Token
-	S_EMMY1,
-	S_EMMY2,
-	S_EMMY3,
-	S_EMMY4,
-	S_EMMY5,
-	S_EMMY6,
-	S_EMMY7,
+	S_EMMY,
 
 	// Special Stage Token
 	S_TOKEN,
@@ -1658,40 +1606,9 @@ typedef enum state
 	S_SPIKED2,
 
 	// Starpost
-	S_STARPOST1,
-	S_STARPOST2,
-	S_STARPOST3,
-	S_STARPOST4,
-	S_STARPOST5,
-	S_STARPOST6,
-	S_STARPOST7,
-	S_STARPOST8,
-	S_STARPOST9,
-	S_STARPOST10,
-	S_STARPOST11,
-	S_STARPOST12,
-	S_STARPOST13,
-	S_STARPOST14,
-	S_STARPOST15,
-	S_STARPOST16,
-	S_STARPOST17,
-	S_STARPOST18,
-	S_STARPOST19,
-	S_STARPOST20,
-	S_STARPOST21,
-	S_STARPOST22,
-	S_STARPOST23,
-	S_STARPOST24,
-	S_STARPOST25,
-	S_STARPOST26,
-	S_STARPOST27,
-	S_STARPOST28,
-	S_STARPOST29,
-	S_STARPOST30,
-	S_STARPOST31,
-	S_STARPOST32,
-	S_STARPOST33,
-	S_STARPOST34,
+	S_STARPOST_IDLE,
+	S_STARPOST_FLASH,
+	S_STARPOST_SPIN,
 
 	// Big floating mine
 	S_BIGMINE1,
@@ -2299,38 +2216,7 @@ typedef enum state
 	S_PITY10,
 
 	// Invincibility Sparkles
-	S_IVSP1,
-	S_IVSP2,
-	S_IVSP3,
-	S_IVSP4,
-	S_IVSP5,
-	S_IVSP6,
-	S_IVSP7,
-	S_IVSP8,
-	S_IVSP9,
-	S_IVSP10,
-	S_IVSP11,
-	S_IVSP12,
-	S_IVSP13,
-	S_IVSP14,
-	S_IVSP15,
-	S_IVSP16,
-	S_IVSP17,
-	S_IVSP18,
-	S_IVSP19,
-	S_IVSP20,
-	S_IVSP21,
-	S_IVSP22,
-	S_IVSP23,
-	S_IVSP24,
-	S_IVSP25,
-	S_IVSP26,
-	S_IVSP27,
-	S_IVSP28,
-	S_IVSP29,
-	S_IVSP30,
-	S_IVSP31,
-	S_IVSP32,
+	S_IVSP,
 
 	// Super Sonic Spark
 	S_SSPK1,
@@ -2517,283 +2403,17 @@ typedef enum state
 	S_RRNG6,
 	S_RRNG7,
 
-	// Bounce Ring
-	S_BOUNCERING1,
-	S_BOUNCERING2,
-	S_BOUNCERING3,
-	S_BOUNCERING4,
-	S_BOUNCERING5,
-	S_BOUNCERING6,
-	S_BOUNCERING7,
-	S_BOUNCERING8,
-	S_BOUNCERING9,
-	S_BOUNCERING10,
-	S_BOUNCERING11,
-	S_BOUNCERING12,
-	S_BOUNCERING13,
-	S_BOUNCERING14,
-	S_BOUNCERING15,
-	S_BOUNCERING16,
-	S_BOUNCERING17,
-	S_BOUNCERING18,
-	S_BOUNCERING19,
-	S_BOUNCERING20,
-	S_BOUNCERING21,
-	S_BOUNCERING22,
-	S_BOUNCERING23,
-	S_BOUNCERING24,
-	S_BOUNCERING25,
-	S_BOUNCERING26,
-	S_BOUNCERING27,
-	S_BOUNCERING28,
-	S_BOUNCERING29,
-	S_BOUNCERING30,
-	S_BOUNCERING31,
-	S_BOUNCERING32,
-	S_BOUNCERING33,
-	S_BOUNCERING34,
-	S_BOUNCERING35,
-
-	// Rail Ring
-	S_RAILRING1,
-	S_RAILRING2,
-	S_RAILRING3,
-	S_RAILRING4,
-	S_RAILRING5,
-	S_RAILRING6,
-	S_RAILRING7,
-	S_RAILRING8,
-	S_RAILRING9,
-	S_RAILRING10,
-	S_RAILRING11,
-	S_RAILRING12,
-	S_RAILRING13,
-	S_RAILRING14,
-	S_RAILRING15,
-	S_RAILRING16,
-	S_RAILRING17,
-	S_RAILRING18,
-	S_RAILRING19,
-	S_RAILRING20,
-	S_RAILRING21,
-	S_RAILRING22,
-	S_RAILRING23,
-	S_RAILRING24,
-	S_RAILRING25,
-	S_RAILRING26,
-	S_RAILRING27,
-	S_RAILRING28,
-	S_RAILRING29,
-	S_RAILRING30,
-	S_RAILRING31,
-	S_RAILRING32,
-	S_RAILRING33,
-	S_RAILRING34,
-	S_RAILRING35,
-
-	// Infinity Ring
-	S_INFINITYRING1,
-	S_INFINITYRING2,
-	S_INFINITYRING3,
-	S_INFINITYRING4,
-	S_INFINITYRING5,
-	S_INFINITYRING6,
-	S_INFINITYRING7,
-	S_INFINITYRING8,
-	S_INFINITYRING9,
-	S_INFINITYRING10,
-	S_INFINITYRING11,
-	S_INFINITYRING12,
-	S_INFINITYRING13,
-	S_INFINITYRING14,
-	S_INFINITYRING15,
-	S_INFINITYRING16,
-	S_INFINITYRING17,
-	S_INFINITYRING18,
-	S_INFINITYRING19,
-	S_INFINITYRING20,
-	S_INFINITYRING21,
-	S_INFINITYRING22,
-	S_INFINITYRING23,
-	S_INFINITYRING24,
-	S_INFINITYRING25,
-	S_INFINITYRING26,
-	S_INFINITYRING27,
-	S_INFINITYRING28,
-	S_INFINITYRING29,
-	S_INFINITYRING30,
-	S_INFINITYRING31,
-	S_INFINITYRING32,
-	S_INFINITYRING33,
-	S_INFINITYRING34,
-	S_INFINITYRING35,
-
-	// Automatic Ring
-	S_AUTOMATICRING1,
-	S_AUTOMATICRING2,
-	S_AUTOMATICRING3,
-	S_AUTOMATICRING4,
-	S_AUTOMATICRING5,
-	S_AUTOMATICRING6,
-	S_AUTOMATICRING7,
-	S_AUTOMATICRING8,
-	S_AUTOMATICRING9,
-	S_AUTOMATICRING10,
-	S_AUTOMATICRING11,
-	S_AUTOMATICRING12,
-	S_AUTOMATICRING13,
-	S_AUTOMATICRING14,
-	S_AUTOMATICRING15,
-	S_AUTOMATICRING16,
-	S_AUTOMATICRING17,
-	S_AUTOMATICRING18,
-	S_AUTOMATICRING19,
-	S_AUTOMATICRING20,
-	S_AUTOMATICRING21,
-	S_AUTOMATICRING22,
-	S_AUTOMATICRING23,
-	S_AUTOMATICRING24,
-	S_AUTOMATICRING25,
-	S_AUTOMATICRING26,
-	S_AUTOMATICRING27,
-	S_AUTOMATICRING28,
-	S_AUTOMATICRING29,
-	S_AUTOMATICRING30,
-	S_AUTOMATICRING31,
-	S_AUTOMATICRING32,
-	S_AUTOMATICRING33,
-	S_AUTOMATICRING34,
-	S_AUTOMATICRING35,
-
-	// Explosion Ring
-	S_EXPLOSIONRING1,
-	S_EXPLOSIONRING2,
-	S_EXPLOSIONRING3,
-	S_EXPLOSIONRING4,
-	S_EXPLOSIONRING5,
-	S_EXPLOSIONRING6,
-	S_EXPLOSIONRING7,
-	S_EXPLOSIONRING8,
-	S_EXPLOSIONRING9,
-	S_EXPLOSIONRING10,
-	S_EXPLOSIONRING11,
-	S_EXPLOSIONRING12,
-	S_EXPLOSIONRING13,
-	S_EXPLOSIONRING14,
-	S_EXPLOSIONRING15,
-	S_EXPLOSIONRING16,
-	S_EXPLOSIONRING17,
-	S_EXPLOSIONRING18,
-	S_EXPLOSIONRING19,
-	S_EXPLOSIONRING20,
-	S_EXPLOSIONRING21,
-	S_EXPLOSIONRING22,
-	S_EXPLOSIONRING23,
-	S_EXPLOSIONRING24,
-	S_EXPLOSIONRING25,
-	S_EXPLOSIONRING26,
-	S_EXPLOSIONRING27,
-	S_EXPLOSIONRING28,
-	S_EXPLOSIONRING29,
-	S_EXPLOSIONRING30,
-	S_EXPLOSIONRING31,
-	S_EXPLOSIONRING32,
-	S_EXPLOSIONRING33,
-	S_EXPLOSIONRING34,
-	S_EXPLOSIONRING35,
-
-	// Scatter Ring
-	S_SCATTERRING1,
-	S_SCATTERRING2,
-	S_SCATTERRING3,
-	S_SCATTERRING4,
-	S_SCATTERRING5,
-	S_SCATTERRING6,
-	S_SCATTERRING7,
-	S_SCATTERRING8,
-	S_SCATTERRING9,
-	S_SCATTERRING10,
-	S_SCATTERRING11,
-	S_SCATTERRING12,
-	S_SCATTERRING13,
-	S_SCATTERRING14,
-	S_SCATTERRING15,
-	S_SCATTERRING16,
-	S_SCATTERRING17,
-	S_SCATTERRING18,
-	S_SCATTERRING19,
-	S_SCATTERRING20,
-	S_SCATTERRING21,
-	S_SCATTERRING22,
-	S_SCATTERRING23,
-	S_SCATTERRING24,
-	S_SCATTERRING25,
-	S_SCATTERRING26,
-	S_SCATTERRING27,
-	S_SCATTERRING28,
-	S_SCATTERRING29,
-	S_SCATTERRING30,
-	S_SCATTERRING31,
-	S_SCATTERRING32,
-	S_SCATTERRING33,
-	S_SCATTERRING34,
-	S_SCATTERRING35,
-
-	// Grenade Ring
-	S_GRENADERING1,
-	S_GRENADERING2,
-	S_GRENADERING3,
-	S_GRENADERING4,
-	S_GRENADERING5,
-	S_GRENADERING6,
-	S_GRENADERING7,
-	S_GRENADERING8,
-	S_GRENADERING9,
-	S_GRENADERING10,
-	S_GRENADERING11,
-	S_GRENADERING12,
-	S_GRENADERING13,
-	S_GRENADERING14,
-	S_GRENADERING15,
-	S_GRENADERING16,
-	S_GRENADERING17,
-	S_GRENADERING18,
-	S_GRENADERING19,
-	S_GRENADERING20,
-	S_GRENADERING21,
-	S_GRENADERING22,
-	S_GRENADERING23,
-	S_GRENADERING24,
-	S_GRENADERING25,
-	S_GRENADERING26,
-	S_GRENADERING27,
-	S_GRENADERING28,
-	S_GRENADERING29,
-	S_GRENADERING30,
-	S_GRENADERING31,
-	S_GRENADERING32,
-	S_GRENADERING33,
-	S_GRENADERING34,
-	S_GRENADERING35,
+	// Weapon Ring Ammo
+	S_BOUNCERINGAMMO,
+	S_RAILRINGAMMO,
+	S_INFINITYRINGAMMO,
+	S_AUTOMATICRINGAMMO,
+	S_EXPLOSIONRINGAMMO,
+	S_SCATTERRINGAMMO,
+	S_GRENADERINGAMMO,
 
 	// Weapon pickup
-	S_BOUNCEPICKUP1,
-	S_BOUNCEPICKUP2,
-	S_BOUNCEPICKUP3,
-	S_BOUNCEPICKUP4,
-	S_BOUNCEPICKUP5,
-	S_BOUNCEPICKUP6,
-	S_BOUNCEPICKUP7,
-	S_BOUNCEPICKUP8,
-	S_BOUNCEPICKUP9,
-	S_BOUNCEPICKUP10,
-	S_BOUNCEPICKUP11,
-	S_BOUNCEPICKUP12,
-	S_BOUNCEPICKUP13,
-	S_BOUNCEPICKUP14,
-	S_BOUNCEPICKUP15,
-	S_BOUNCEPICKUP16,
-
+	S_BOUNCEPICKUP,
 	S_BOUNCEPICKUPFADE1,
 	S_BOUNCEPICKUPFADE2,
 	S_BOUNCEPICKUPFADE3,
@@ -2803,23 +2423,7 @@ typedef enum state
 	S_BOUNCEPICKUPFADE7,
 	S_BOUNCEPICKUPFADE8,
 
-	S_RAILPICKUP1,
-	S_RAILPICKUP2,
-	S_RAILPICKUP3,
-	S_RAILPICKUP4,
-	S_RAILPICKUP5,
-	S_RAILPICKUP6,
-	S_RAILPICKUP7,
-	S_RAILPICKUP8,
-	S_RAILPICKUP9,
-	S_RAILPICKUP10,
-	S_RAILPICKUP11,
-	S_RAILPICKUP12,
-	S_RAILPICKUP13,
-	S_RAILPICKUP14,
-	S_RAILPICKUP15,
-	S_RAILPICKUP16,
-
+	S_RAILPICKUP,
 	S_RAILPICKUPFADE1,
 	S_RAILPICKUPFADE2,
 	S_RAILPICKUPFADE3,
@@ -2829,23 +2433,7 @@ typedef enum state
 	S_RAILPICKUPFADE7,
 	S_RAILPICKUPFADE8,
 
-	S_AUTOPICKUP1,
-	S_AUTOPICKUP2,
-	S_AUTOPICKUP3,
-	S_AUTOPICKUP4,
-	S_AUTOPICKUP5,
-	S_AUTOPICKUP6,
-	S_AUTOPICKUP7,
-	S_AUTOPICKUP8,
-	S_AUTOPICKUP9,
-	S_AUTOPICKUP10,
-	S_AUTOPICKUP11,
-	S_AUTOPICKUP12,
-	S_AUTOPICKUP13,
-	S_AUTOPICKUP14,
-	S_AUTOPICKUP15,
-	S_AUTOPICKUP16,
-
+	S_AUTOPICKUP,
 	S_AUTOPICKUPFADE1,
 	S_AUTOPICKUPFADE2,
 	S_AUTOPICKUPFADE3,
@@ -2855,23 +2443,7 @@ typedef enum state
 	S_AUTOPICKUPFADE7,
 	S_AUTOPICKUPFADE8,
 
-	S_EXPLODEPICKUP1,
-	S_EXPLODEPICKUP2,
-	S_EXPLODEPICKUP3,
-	S_EXPLODEPICKUP4,
-	S_EXPLODEPICKUP5,
-	S_EXPLODEPICKUP6,
-	S_EXPLODEPICKUP7,
-	S_EXPLODEPICKUP8,
-	S_EXPLODEPICKUP9,
-	S_EXPLODEPICKUP10,
-	S_EXPLODEPICKUP11,
-	S_EXPLODEPICKUP12,
-	S_EXPLODEPICKUP13,
-	S_EXPLODEPICKUP14,
-	S_EXPLODEPICKUP15,
-	S_EXPLODEPICKUP16,
-
+	S_EXPLODEPICKUP,
 	S_EXPLODEPICKUPFADE1,
 	S_EXPLODEPICKUPFADE2,
 	S_EXPLODEPICKUPFADE3,
@@ -2881,23 +2453,7 @@ typedef enum state
 	S_EXPLODEPICKUPFADE7,
 	S_EXPLODEPICKUPFADE8,
 
-	S_SCATTERPICKUP1,
-	S_SCATTERPICKUP2,
-	S_SCATTERPICKUP3,
-	S_SCATTERPICKUP4,
-	S_SCATTERPICKUP5,
-	S_SCATTERPICKUP6,
-	S_SCATTERPICKUP7,
-	S_SCATTERPICKUP8,
-	S_SCATTERPICKUP9,
-	S_SCATTERPICKUP10,
-	S_SCATTERPICKUP11,
-	S_SCATTERPICKUP12,
-	S_SCATTERPICKUP13,
-	S_SCATTERPICKUP14,
-	S_SCATTERPICKUP15,
-	S_SCATTERPICKUP16,
-
+	S_SCATTERPICKUP,
 	S_SCATTERPICKUPFADE1,
 	S_SCATTERPICKUPFADE2,
 	S_SCATTERPICKUPFADE3,
@@ -2907,23 +2463,7 @@ typedef enum state
 	S_SCATTERPICKUPFADE7,
 	S_SCATTERPICKUPFADE8,
 
-	S_GRENADEPICKUP1,
-	S_GRENADEPICKUP2,
-	S_GRENADEPICKUP3,
-	S_GRENADEPICKUP4,
-	S_GRENADEPICKUP5,
-	S_GRENADEPICKUP6,
-	S_GRENADEPICKUP7,
-	S_GRENADEPICKUP8,
-	S_GRENADEPICKUP9,
-	S_GRENADEPICKUP10,
-	S_GRENADEPICKUP11,
-	S_GRENADEPICKUP12,
-	S_GRENADEPICKUP13,
-	S_GRENADEPICKUP14,
-	S_GRENADEPICKUP15,
-	S_GRENADEPICKUP16,
-
+	S_GRENADEPICKUP,
 	S_GRENADEPICKUPFADE1,
 	S_GRENADEPICKUPFADE2,
 	S_GRENADEPICKUPFADE3,
@@ -3304,101 +2844,22 @@ typedef enum state
 
 	S_ROCKSPAWN,
 
-	S_ROCKCRUMBLEA1,
-	S_ROCKCRUMBLEA2,
-	S_ROCKCRUMBLEA3,
-	S_ROCKCRUMBLEA4,
-	S_ROCKCRUMBLEA5,
-
-	S_ROCKCRUMBLEB1,
-	S_ROCKCRUMBLEB2,
-	S_ROCKCRUMBLEB3,
-	S_ROCKCRUMBLEB4,
-	S_ROCKCRUMBLEB5,
-
-	S_ROCKCRUMBLEC1,
-	S_ROCKCRUMBLEC2,
-	S_ROCKCRUMBLEC3,
-	S_ROCKCRUMBLEC4,
-	S_ROCKCRUMBLEC5,
-
-	S_ROCKCRUMBLED1,
-	S_ROCKCRUMBLED2,
-	S_ROCKCRUMBLED3,
-	S_ROCKCRUMBLED4,
-	S_ROCKCRUMBLED5,
-
-	S_ROCKCRUMBLEE1,
-	S_ROCKCRUMBLEE2,
-	S_ROCKCRUMBLEE3,
-	S_ROCKCRUMBLEE4,
-	S_ROCKCRUMBLEE5,
-
-	S_ROCKCRUMBLEF1,
-	S_ROCKCRUMBLEF2,
-	S_ROCKCRUMBLEF3,
-	S_ROCKCRUMBLEF4,
-	S_ROCKCRUMBLEF5,
-
-	S_ROCKCRUMBLEG1,
-	S_ROCKCRUMBLEG2,
-	S_ROCKCRUMBLEG3,
-	S_ROCKCRUMBLEG4,
-	S_ROCKCRUMBLEG5,
-
-	S_ROCKCRUMBLEH1,
-	S_ROCKCRUMBLEH2,
-	S_ROCKCRUMBLEH3,
-	S_ROCKCRUMBLEH4,
-	S_ROCKCRUMBLEH5,
-
-	S_ROCKCRUMBLEI1,
-	S_ROCKCRUMBLEI2,
-	S_ROCKCRUMBLEI3,
-	S_ROCKCRUMBLEI4,
-	S_ROCKCRUMBLEI5,
-
-	S_ROCKCRUMBLEJ1,
-	S_ROCKCRUMBLEJ2,
-	S_ROCKCRUMBLEJ3,
-	S_ROCKCRUMBLEJ4,
-	S_ROCKCRUMBLEJ5,
-
-	S_ROCKCRUMBLEK1,
-	S_ROCKCRUMBLEK2,
-	S_ROCKCRUMBLEK3,
-	S_ROCKCRUMBLEK4,
-	S_ROCKCRUMBLEK5,
-
-	S_ROCKCRUMBLEL1,
-	S_ROCKCRUMBLEL2,
-	S_ROCKCRUMBLEL3,
-	S_ROCKCRUMBLEL4,
-	S_ROCKCRUMBLEL5,
-
-	S_ROCKCRUMBLEM1,
-	S_ROCKCRUMBLEM2,
-	S_ROCKCRUMBLEM3,
-	S_ROCKCRUMBLEM4,
-	S_ROCKCRUMBLEM5,
-
-	S_ROCKCRUMBLEN1,
-	S_ROCKCRUMBLEN2,
-	S_ROCKCRUMBLEN3,
-	S_ROCKCRUMBLEN4,
-	S_ROCKCRUMBLEN5,
-
-	S_ROCKCRUMBLEO1,
-	S_ROCKCRUMBLEO2,
-	S_ROCKCRUMBLEO3,
-	S_ROCKCRUMBLEO4,
-	S_ROCKCRUMBLEO5,
-
-	S_ROCKCRUMBLEP1,
-	S_ROCKCRUMBLEP2,
-	S_ROCKCRUMBLEP3,
-	S_ROCKCRUMBLEP4,
-	S_ROCKCRUMBLEP5,
+	S_ROCKCRUMBLEA,
+	S_ROCKCRUMBLEB,
+	S_ROCKCRUMBLEC,
+	S_ROCKCRUMBLED,
+	S_ROCKCRUMBLEE,
+	S_ROCKCRUMBLEF,
+	S_ROCKCRUMBLEG,
+	S_ROCKCRUMBLEH,
+	S_ROCKCRUMBLEI,
+	S_ROCKCRUMBLEJ,
+	S_ROCKCRUMBLEK,
+	S_ROCKCRUMBLEL,
+	S_ROCKCRUMBLEM,
+	S_ROCKCRUMBLEN,
+	S_ROCKCRUMBLEO,
+	S_ROCKCRUMBLEP,
 
 	S_SRB1_CRAWLA1,
 	S_SRB1_CRAWLA2,
diff --git a/src/lua_baselib.c b/src/lua_baselib.c
index 5e2d31b10f13f8e49917392c1f51927127000d71..c415eecb8e10f2c2853cb5b123d6fb3126ff58de 100644
--- a/src/lua_baselib.c
+++ b/src/lua_baselib.c
@@ -1636,18 +1636,63 @@ static int lib_sStopSound(lua_State *L)
 
 static int lib_sChangeMusic(lua_State *L)
 {
-	UINT32 music_num = (UINT32)luaL_checkinteger(L, 1);
+#ifdef MUSICSLOT_COMPATIBILITY
+	const char *music_name;
+	UINT32 music_num;
+	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));
 		if (!player)
 			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);
+
 	if (!player || P_IsLocalPlayer(player))
-	S_ChangeMusic(music_num, looping);
+		S_ChangeMusic(music_name, music_flags, looping);
 	return 0;
 }
 
diff --git a/src/lua_hook.h b/src/lua_hook.h
index da2dcdc380461cefd958b9f42bfbe738a98d724b..4eb083780ea69e5d1674483e9ef83908a5dd9cba 100644
--- a/src/lua_hook.h
+++ b/src/lua_hook.h
@@ -42,6 +42,7 @@ enum hook {
 	hook_LinedefExecute,
 	hook_PlayerMsg,
 	hook_HurtMsg,
+	hook_PlayerSpawn,
 
 	hook_MAX // last hook
 };
@@ -75,5 +76,6 @@ boolean LUAh_BotAI(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd); // Hook for B_B
 boolean LUAh_LinedefExecute(line_t *line, mobj_t *mo, sector_t *sector); // Hook for linedef executors
 boolean LUAh_PlayerMsg(int source, int target, int flags, char *msg); // Hook for chat messages
 boolean LUAh_HurtMsg(player_t *player, mobj_t *inflictor, mobj_t *source); // Hook for hurt messages
+#define LUAh_PlayerSpawn(player) LUAh_PlayerHook(player, hook_PlayerSpawn) // Hook for G_SpawnPlayer 
 
 #endif
diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c
index 0415d23e61acfe98705ec8855846b06297fcdf02..2c1aa1cea97cffcaf833015ac8cacaa5f6395ce6 100644
--- a/src/lua_hooklib.c
+++ b/src/lua_hooklib.c
@@ -53,6 +53,7 @@ const char *const hookNames[hook_MAX+1] = {
 	"LinedefExecute",
 	"PlayerMsg",
 	"HurtMsg",
+	"PlayerSpawn",
 	NULL
 };
 
@@ -768,4 +769,33 @@ boolean LUAh_HurtMsg(player_t *player, mobj_t *inflictor, mobj_t *source)
 	return hooked;
 }
 
+void LUAh_NetArchiveHook(lua_CFunction archFunc)
+{
+	hook_p hookp;
+
+	if (!gL || !(hooksAvailable[hook_NetVars/8] & (1<<(hook_NetVars%8))))
+		return;
+
+	// stack: tables
+	I_Assert(lua_gettop(gL) > 0);
+	I_Assert(lua_istable(gL, -1));
+
+	// tables becomes an upvalue of archFunc
+	lua_pushvalue(gL, -1);
+	lua_pushcclosure(gL, archFunc, 1);
+	// stack: tables, archFunc
+
+	for (hookp = roothook; hookp; hookp = hookp->next)
+		if (hookp->type == hook_NetVars)
+		{
+			lua_pushfstring(gL, FMT_HOOKID, hookp->id);
+			lua_gettable(gL, LUA_REGISTRYINDEX);
+			lua_pushvalue(gL, -2); // archFunc
+			LUA_Call(gL, 1);
+		}
+
+	lua_pop(gL, 1); // pop archFunc
+	// stack: tables
+}
+
 #endif
diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c
index 5a83d95b56a6a3a39cf7d0364c39a2866964dd26..325f00b013e5495f67d79b2ca78775e02812a4c6 100644
--- a/src/lua_hudlib.c
+++ b/src/lua_hudlib.c
@@ -16,7 +16,9 @@
 #include "r_local.h"
 #include "st_stuff.h" // hudinfo[]
 #include "g_game.h"
+#include "i_video.h" // rendermode
 #include "p_local.h" // camera_t
+#include "screen.h" // screen width/height
 #include "v_video.h"
 #include "w_wad.h"
 #include "z_zone.h"
@@ -486,7 +488,7 @@ static int libd_getColormap(lua_State *L)
 	INT32 skinnum = TC_DEFAULT;
 	skincolors_t color = luaL_optinteger(L, 2, 0);
 	UINT8* colormap = NULL;
-	//HUDSAFE
+	HUDONLY
 	if (lua_isnoneornil(L, 1))
 		; // defaults to TC_DEFAULT
 	else if (lua_type(L, 1) == LUA_TNUMBER) // skin number
@@ -510,6 +512,31 @@ static int libd_getColormap(lua_State *L)
 	return 1;
 }
 
+static int libd_width(lua_State *L)
+{
+	HUDONLY
+	lua_pushinteger(L, vid.width); // push screen width
+	return 1;
+}
+
+static int libd_height(lua_State *L)
+{
+	HUDONLY
+	lua_pushinteger(L, vid.height); // push screen height
+	return 1;
+}
+
+static int libd_renderer(lua_State *L)
+{
+	HUDONLY
+	switch (rendermode) {
+		case render_opengl: lua_pushliteral(L, "opengl");   break; // OpenGL renderer
+		case render_soft:   lua_pushliteral(L, "software"); break; // Software renderer
+		default:            lua_pushliteral(L, "none");     break; // render_none (for dedicated), in case there's any reason this should be run
+	}
+	return 1;
+}
+
 static luaL_Reg lib_draw[] = {
 	{"patchExists", libd_patchExists},
 	{"cachePatch", libd_cachePatch},
@@ -521,6 +548,9 @@ static luaL_Reg lib_draw[] = {
 	{"drawString", libd_drawString},
 	{"stringWidth", libd_stringWidth},
 	{"getColormap", libd_getColormap},
+	{"width", libd_width},
+	{"height", libd_height},
+	{"renderer", libd_renderer},
 	{NULL, NULL}
 };
 
diff --git a/src/lua_libs.h b/src/lua_libs.h
index d19ad88578de24bfa4a3f14163f2b39ac750c717..25552eacbe507a9c09f18007923959f0220a9e9a 100644
--- a/src/lua_libs.h
+++ b/src/lua_libs.h
@@ -42,6 +42,7 @@ extern lua_State *gL;
 
 #define META_CVAR "CONSVAR_T*"
 
+#define META_SECTORLINES "SECTOR_T*LINES"
 #define META_SIDENUM "LINE_T*SIDENUM"
 
 #define META_HUDINFO "HUDINFO_T*"
diff --git a/src/lua_maplib.c b/src/lua_maplib.c
index 38920c22328cefec06fcfb9d231dc13da0425d4c..b6b5147a9abbfa939c14e3bb14a5f7bc0af9cf39 100644
--- a/src/lua_maplib.c
+++ b/src/lua_maplib.c
@@ -37,6 +37,7 @@ enum sector_e {
 	sector_thinglist,
 	sector_heightsec,
 	sector_camsec,
+	sector_lines,
 	sector_ffloors
 };
 
@@ -52,6 +53,7 @@ static const char *const sector_opt[] = {
 	"thinglist",
 	"heightsec",
 	"camsec",
+	"lines",
 	"ffloors",
 	NULL};
 
@@ -260,6 +262,67 @@ static int sector_iterate(lua_State *L)
 	return 3;
 }
 
+// sector.lines, i -> sector.lines[i]
+// sector.lines.valid, for validity checking
+static int sectorlines_get(lua_State *L)
+{
+	line_t **seclines = *((line_t ***)luaL_checkudata(L, 1, META_SECTORLINES));
+	size_t i;
+	size_t numoflines = 0;
+	lua_settop(L, 2);
+	if (!lua_isnumber(L, 2))
+	{
+		int field = luaL_checkoption(L, 2, NULL, valid_opt);
+		if (!seclines)
+		{
+			if (field == 0) {
+				lua_pushboolean(L, 0);
+				return 1;
+			}
+			return luaL_error(L, "accessed sector_t doesn't exist anymore.");
+		} else if (field == 0) {
+			lua_pushboolean(L, 1);
+			return 1;
+		}
+	}
+
+	// check first linedef to figure which of its sectors owns this sector->lines pointer
+	// then check that sector's linecount to get a maximum index
+	//if (!seclines[0])
+		//return luaL_error(L, "no lines found!"); // no first linedef?????
+	if (seclines[0]->frontsector->lines == seclines)
+		numoflines = seclines[0]->frontsector->linecount;
+	else if (seclines[0]->backsector && seclines[0]->backsector->lines == seclines) // check backsector exists first
+		numoflines = seclines[0]->backsector->linecount;
+	//if neither sector has it then ???
+
+	if (!numoflines)
+		return luaL_error(L, "no lines found!");
+
+	i = (size_t)lua_tointeger(L, 2);
+	if (i >= numoflines)
+		return 0;
+	LUA_PushUserdata(L, seclines[i], META_LINE);
+	return 1;
+}
+
+static int sectorlines_num(lua_State *L)
+{
+	line_t **seclines = *((line_t ***)luaL_checkudata(L, 1, META_SECTORLINES));
+	size_t numoflines = 0;
+	// check first linedef to figure which of its sectors owns this sector->lines pointer
+	// then check that sector's linecount to get a maximum index
+	//if (!seclines[0])
+		//return luaL_error(L, "no lines found!"); // no first linedef?????
+	if (seclines[0]->frontsector->lines == seclines)
+		numoflines = seclines[0]->frontsector->linecount;
+	else if (seclines[0]->backsector && seclines[0]->backsector->lines == seclines) // check backsector exists first
+		numoflines = seclines[0]->backsector->linecount;
+	//if neither sector has it then ???
+	lua_pushinteger(L, numoflines);
+	return 1;
+}
+
 static int sector_get(lua_State *L)
 {
 	sector_t *sector = *((sector_t **)luaL_checkudata(L, 1, META_SECTOR));
@@ -325,6 +388,9 @@ static int sector_get(lua_State *L)
 			return 0;
 		LUA_PushUserdata(L, &sectors[sector->camsec], META_SECTOR);
 		return 1;
+	case sector_lines: // lines
+		LUA_PushUserdata(L, sector->lines, META_SECTORLINES);
+		return 1;
 	case sector_ffloors: // ffloors
 		lua_pushcfunction(L, lib_iterateSectorFFloors);
 		LUA_PushUserdata(L, sector->ffloors, META_FFLOOR);
@@ -1111,9 +1177,13 @@ static int ffloor_set(lua_State *L)
 	case ffloor_bottompic:
 		*ffloor->bottompic = P_AddLevelFlatRuntime(luaL_checkstring(L, 3));
 		break;
-	case ffloor_flags:
+	case ffloor_flags: {
+		ffloortype_e oldflags = ffloor->flags; // store FOF's old flags
 		ffloor->flags = luaL_checkinteger(L, 3);
+		if (ffloor->flags != oldflags)
+			ffloor->target->moved = true; // reset target sector's lightlist
 		break;
+	}
 	case ffloor_alpha:
 		ffloor->alpha = (INT32)luaL_checkinteger(L, 3);
 		break;
@@ -1168,10 +1238,10 @@ static int mapheaderinfo_get(lua_State *L)
 		lua_pushinteger(L, header->typeoflevel);
 	else if (fastcmp(field,"nextlevel"))
 		lua_pushinteger(L, header->nextlevel);
-	else if (fastcmp(field,"musicslot"))
-		lua_pushinteger(L, header->musicslot);
-	else if (fastcmp(field,"musicslottrack"))
-		lua_pushinteger(L, header->musicslottrack);
+	else if (fastcmp(field,"musname"))
+		lua_pushstring(L, header->musname);
+	else if (fastcmp(field,"mustrack"))
+		lua_pushinteger(L, header->mustrack);
 	else if (fastcmp(field,"forcecharacter"))
 		lua_pushstring(L, header->forcecharacter);
 	else if (fastcmp(field,"weather"))
@@ -1230,6 +1300,14 @@ static int mapheaderinfo_get(lua_State *L)
 
 int LUA_MapLib(lua_State *L)
 {
+	luaL_newmetatable(L, META_SECTORLINES);
+		lua_pushcfunction(L, sectorlines_get);
+		lua_setfield(L, -2, "__index");
+
+		lua_pushcfunction(L, sectorlines_num);
+		lua_setfield(L, -2, "__len");
+	lua_pop(L, 1);
+
 	luaL_newmetatable(L, META_SECTOR);
 		lua_pushcfunction(L, sector_get);
 		lua_setfield(L, -2, "__index");
diff --git a/src/lua_mobjlib.c b/src/lua_mobjlib.c
index 83e7039e4bbacb68079f78d62020bdb388a1f3ac..bf4ee0b286d11ef9310fd2a5fe1c3365adde2597 100644
--- a/src/lua_mobjlib.c
+++ b/src/lua_mobjlib.c
@@ -34,6 +34,7 @@ enum mobj_e {
 	mobj_angle,
 	mobj_sprite,
 	mobj_frame,
+	mobj_anim_duration,
 	mobj_touching_sectorlist,
 	mobj_subsector,
 	mobj_floorz,
@@ -92,6 +93,7 @@ static const char *const mobj_opt[] = {
 	"angle",
 	"sprite",
 	"frame",
+	"anim_duration",
 	"touching_sectorlist",
 	"subsector",
 	"floorz",
@@ -187,6 +189,9 @@ static int mobj_get(lua_State *L)
 	case mobj_frame:
 		lua_pushinteger(L, mo->frame);
 		break;
+	case mobj_anim_duration:
+		lua_pushinteger(L, mo->anim_duration);
+		break;
 	case mobj_touching_sectorlist:
 		return UNIMPLEMENTED;
 	case mobj_subsector:
@@ -406,6 +411,9 @@ static int mobj_set(lua_State *L)
 	case mobj_frame:
 		mo->frame = (UINT32)luaL_checkinteger(L, 3);
 		break;
+	case mobj_anim_duration:
+		mo->anim_duration = (UINT16)luaL_checkinteger(L, 3);
+		break;
 	case mobj_touching_sectorlist:
 		return UNIMPLEMENTED;
 	case mobj_subsector:
diff --git a/src/lua_script.c b/src/lua_script.c
index a7315ad622438608ad207d805ea455aec3570a3a..9925bac02ee05cf5d7f686b6ddde09005f69f5be 100644
--- a/src/lua_script.c
+++ b/src/lua_script.c
@@ -915,30 +915,6 @@ static void UnArchiveTables(void)
 	}
 }
 
-static void NetArchiveHook(lua_CFunction archFunc)
-{
-	int TABLESINDEX;
-
-	if (!gL)
-		return;
-
-	TABLESINDEX = lua_gettop(gL);
-	lua_getfield(gL, LUA_REGISTRYINDEX, "hook");
-	I_Assert(lua_istable(gL, -1));
-	lua_rawgeti(gL, -1, hook_NetVars);
-	lua_remove(gL, -2);
-	I_Assert(lua_istable(gL, -1));
-
-	lua_pushvalue(gL, TABLESINDEX);
-	lua_pushcclosure(gL, archFunc, 1);
-	lua_pushnil(gL);
-	while (lua_next(gL, -3) != 0) {
-		lua_pushvalue(gL, -3); // function
-		LUA_Call(gL, 1);
-	}
-	lua_pop(gL, 2);
-}
-
 void LUA_Step(void)
 {
 	if (!gL)
@@ -972,7 +948,7 @@ void LUA_Archive(void)
 		}
 	WRITEUINT32(save_p, UINT32_MAX); // end of mobjs marker, replaces mobjnum.
 
-	NetArchiveHook(NetArchive); // call the NetArchive hook in archive mode
+	LUAh_NetArchiveHook(NetArchive); // call the NetArchive hook in archive mode
 	ArchiveTables();
 
 	if (gL)
@@ -1003,7 +979,7 @@ void LUA_UnArchive(void)
 				UnArchiveExtVars(th); // apply variables
 	} while(mobjnum != UINT32_MAX); // repeat until end of mobjs marker.
 
-	NetArchiveHook(NetUnArchive); // call the NetArchive hook in unarchive mode
+	LUAh_NetArchiveHook(NetUnArchive); // call the NetArchive hook in unarchive mode
 	UnArchiveTables();
 
 	if (gL)
diff --git a/src/lua_script.h b/src/lua_script.h
index 292160a0b5356e2494d6557207dfe20c2167d993..ec67703c33d3b8494ad810f695be6900d11bfb17 100644
--- a/src/lua_script.h
+++ b/src/lua_script.h
@@ -55,6 +55,7 @@ void Got_Luacmd(UINT8 **cp, INT32 playernum); // lua_consolelib.c
 void LUA_CVarChanged(const char *name); // lua_consolelib.c
 int Lua_optoption(lua_State *L, int narg,
 	const char *def, const char *const lst[]);
+void LUAh_NetArchiveHook(lua_CFunction archFunc);
 
 // Console wrapper
 void COM_Lua_f(void);
diff --git a/src/m_menu.c b/src/m_menu.c
index 780de7ad5f5984e3a74f5a3e7a062938cc02de56..95752c7aacc1f34de012bb820e6f894fdd26ede8 100644
--- a/src/m_menu.c
+++ b/src/m_menu.c
@@ -4751,7 +4751,7 @@ static void M_SetupChoosePlayer(INT32 choice)
 	if (Playing() == false)
 	{
 		S_StopMusic();
-		S_ChangeMusic(mus_chrsel, true);
+		S_ChangeMusicInternal("chrsel", true);
 	}
 
 	SP_PlayerDef.prevMenu = currentMenu;
@@ -5202,7 +5202,7 @@ void M_DrawTimeAttackMenu(void)
 	lumpnum_t lumpnum;
 	char beststr[40];
 
-	S_ChangeMusic(mus_racent, true); // Eww, but needed for when user hits escape during demo playback
+	S_ChangeMusicInternal("racent", true); // Eww, but needed for when user hits escape during demo playback
 
 	V_DrawPatchFill(W_CachePatchName("SRB2BACK", PU_CACHE));
 
@@ -5365,7 +5365,7 @@ static void M_TimeAttack(INT32 choice)
 	itemOn = tastart; // "Start" is selected.
 
 	G_SetGamestate(GS_TIMEATTACK);
-	S_ChangeMusic(mus_racent, true);
+	S_ChangeMusicInternal("racent", true);
 }
 
 // Drawing function for Nights Attack
@@ -5375,7 +5375,7 @@ void M_DrawNightsAttackMenu(void)
 	lumpnum_t lumpnum;
 	char beststr[40];
 
-	S_ChangeMusic(mus_racent, true); // Eww, but needed for when user hits escape during demo playback
+	S_ChangeMusicInternal("racent", true); // Eww, but needed for when user hits escape during demo playback
 
 	V_DrawPatchFill(W_CachePatchName("SRB2BACK", PU_CACHE));
 
@@ -5498,7 +5498,7 @@ static void M_NightsAttack(INT32 choice)
 	itemOn = nastart; // "Start" is selected.
 
 	G_SetGamestate(GS_TIMEATTACK);
-	S_ChangeMusic(mus_racent, true);
+	S_ChangeMusicInternal("racent", true);
 }
 
 // Player has selected the "START" from the nights attack screen
@@ -5732,7 +5732,7 @@ static void M_ModeAttackEndGame(INT32 choice)
 	itemOn = currentMenu->lastOn;
 	G_SetGamestate(GS_TIMEATTACK);
 	modeattacking = ATTACKING_NONE;
-	S_ChangeMusic(mus_racent, true);
+	S_ChangeMusicInternal("racent", true);
 	// Update replay availability.
 	CV_AddValue(&cv_nextmap, 1);
 	CV_AddValue(&cv_nextmap, -1);
@@ -6944,7 +6944,7 @@ static void M_ToggleDigital(void)
 		if (nodigimusic) return;
 		S_Init(cv_soundvolume.value, cv_digmusicvolume.value, cv_midimusicvolume.value);
 		S_StopMusic();
-		S_ChangeMusic(mus_lclear, false);
+		S_ChangeMusicInternal("lclear", false);
 		M_StartMessage(M_GetText("Digital Music Enabled\n"), NULL, MM_NOTHING);
 	}
 	else
@@ -6971,7 +6971,7 @@ static void M_ToggleMIDI(void)
 		I_InitMIDIMusic();
 		if (nomidimusic) return;
 		S_Init(cv_soundvolume.value, cv_digmusicvolume.value, cv_midimusicvolume.value);
-		S_ChangeMusic(mus_lclear, false);
+		S_ChangeMusicInternal("lclear", false);
 		M_StartMessage(M_GetText("MIDI Music Enabled\n"), NULL, MM_NOTHING);
 	}
 	else
diff --git a/src/p_enemy.c b/src/p_enemy.c
index bc6f604810448cbf65d917a731c2d91f5a42407e..367d5714a4b50b66511a53c7fb4015a1ad294acc 100644
--- a/src/p_enemy.c
+++ b/src/p_enemy.c
@@ -3063,12 +3063,8 @@ void A_Invincibility(mobj_t *actor)
 	{
 		S_StopMusic();
 		if (mariomode)
-		{
-			S_ChangeMusic(mus_minvnc, false);
 			G_GhostAddColor(GHC_INVINCIBLE);
-		}
-		else
-			S_ChangeMusic(mus_invinc, false);
+		S_ChangeMusicInternal((mariomode) ? "minvnc" : "invinc", false);
 	}
 }
 
@@ -3104,7 +3100,7 @@ void A_SuperSneakers(mobj_t *actor)
 		else
 		{
 			S_StopMusic();
-			S_ChangeMusic(mus_shoes, false);
+			S_ChangeMusicInternal("shoes", false);
 		}
 	}
 }
diff --git a/src/p_inter.c b/src/p_inter.c
index 55d36a1dee451882bb84298c9c3c2473c0d85d1d..6ab6aaf40dd5c823a07e698e460e0a2b22fc6293 100644
--- a/src/p_inter.c
+++ b/src/p_inter.c
@@ -2076,7 +2076,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source)
 				if (P_IsLocalPlayer(target->player) && target->player == &players[consoleplayer])
 				{
 					S_StopMusic(); // Stop the Music! Tails 03-14-2000
-					S_ChangeMusic(mus_gmover, false); // Yousa dead now, Okieday? Tails 03-14-2000
+					S_ChangeMusicInternal("gmover", false); // Yousa dead now, Okieday? Tails 03-14-2000
 				}
 			}
 		}
@@ -2464,7 +2464,7 @@ static inline void P_NiGHTSDamage(mobj_t *target, mobj_t *source)
 			&& player->nightstime < 10*TICRATE)
 		{
 			//S_StartSound(NULL, sfx_timeup); // that creepy "out of time" music from NiGHTS. Dummied out, as some on the dev team thought it wasn't Sonic-y enough (Mystic, notably). Uncomment to restore. -SH
-			S_ChangeMusic(mus_drown,false);
+			S_ChangeMusicInternal("drown",false);
 		}
 	}
 }
diff --git a/src/p_local.h b/src/p_local.h
index 97b8865d4a3a629dbcae51d5922441d730be9a93..d035925c8e664a54cdbd98c2dfedfcff2c1bb3b6 100644
--- a/src/p_local.h
+++ b/src/p_local.h
@@ -212,6 +212,7 @@ void P_RemoveSavegameMobj(mobj_t *th);
 boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state);
 boolean P_SetMobjState(mobj_t *mobj, statenum_t state);
 void P_RunShields(void);
+void P_RunOverlays(void);
 void P_MobjThinker(mobj_t *mobj);
 boolean P_RailThinker(mobj_t *mobj);
 void P_PushableThinker(mobj_t *mobj);
diff --git a/src/p_mobj.c b/src/p_mobj.c
index 25ae8815a17392564337926ef0e5630d908ebd92..d2454f267616901413bdc445d270abe899357ae6 100644
--- a/src/p_mobj.c
+++ b/src/p_mobj.c
@@ -79,11 +79,31 @@ void P_AddCachedAction(mobj_t *mobj, INT32 statenum)
 	actioncachehead.prev = newaction;
 }
 
+//
+// P_CycleStateAnimation
+//
+FUNCINLINE static ATTRINLINE void P_CycleStateAnimation(mobj_t *mobj)
+{
+	// var2 determines delay between animation frames
+	if (!(mobj->frame & FF_ANIMATE) || --mobj->anim_duration != 0)
+		return;
+	mobj->anim_duration = (UINT16)mobj->state->var2;
+
+	// compare the current sprite frame to the one we started from
+	// if more than var1 away from it, swap back to the original
+	// else just advance by one
+	if (((++mobj->frame) & FF_FRAMEMASK) - (mobj->state->frame & FF_FRAMEMASK) > (UINT32)mobj->state->var1)
+		mobj->frame = (mobj->state->frame & FF_FRAMEMASK) | (mobj->frame & ~FF_FRAMEMASK);
+}
+
 //
 // P_CycleMobjState
 //
 static void P_CycleMobjState(mobj_t *mobj)
 {
+	// state animations
+	P_CycleStateAnimation(mobj);
+
 	// cycle through states,
 	// calling action functions at transitions
 	if (mobj->tics != -1)
@@ -102,6 +122,9 @@ static void P_CycleMobjState(mobj_t *mobj)
 //
 static void P_CyclePlayerMobjState(mobj_t *mobj)
 {
+	// state animations
+	P_CycleStateAnimation(mobj);
+
 	// cycle through states,
 	// calling action functions at transitions
 	if (mobj->tics != -1)
@@ -279,6 +302,7 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state)
 
 		mobj->sprite = st->sprite;
 		mobj->frame = st->frame;
+		mobj->anim_duration = (UINT16)st->var2; // only used if FF_ANIMATE is set
 
 		// Modified handling.
 		// Call action functions when the state is set
@@ -346,6 +370,7 @@ boolean P_SetMobjState(mobj_t *mobj, statenum_t state)
 		mobj->tics = st->tics;
 		mobj->sprite = st->sprite;
 		mobj->frame = st->frame;
+		mobj->anim_duration = (UINT16)st->var2; // only used if FF_ANIMATE is set
 
 		// Modified handling.
 		// Call action functions when the state is set
@@ -399,6 +424,8 @@ boolean P_SetMobjStateNF(mobj_t *mobj, statenum_t state)
 	mobj->tics = st->tics;
 	mobj->sprite = st->sprite;
 	mobj->frame = st->frame;
+	mobj->anim_duration = (UINT16)st->var2; // only used if FF_ANIMATE is set
+
 	return true;
 }
 
@@ -416,6 +443,8 @@ static boolean P_SetPrecipMobjState(precipmobj_t *mobj, statenum_t state)
 	mobj->tics = st->tics;
 	mobj->sprite = st->sprite;
 	mobj->frame = st->frame;
+	mobj->anim_duration = (UINT16)st->var2; // only used if FF_ANIMATE is set
+
 	return true;
 }
 
@@ -3716,6 +3745,8 @@ void P_NullPrecipThinker(precipmobj_t *mobj)
 
 void P_SnowThinker(precipmobj_t *mobj)
 {
+	P_CycleStateAnimation((mobj_t *)mobj);
+
 	// adjust height
 	if ((mobj->z += mobj->momz) <= mobj->floorz)
 		mobj->z = mobj->ceilingz;
@@ -3723,6 +3754,8 @@ void P_SnowThinker(precipmobj_t *mobj)
 
 void P_RainThinker(precipmobj_t *mobj)
 {
+	P_CycleStateAnimation((mobj_t *)mobj);
+
 	if (mobj->state != &states[S_RAIN1])
 	{
 		// cycle through states,
@@ -5833,8 +5866,6 @@ INT32 numshields = 0;
 void P_RunShields(void)
 {
 	INT32 i;
-	mobj_t *mo, *next;
-	fixed_t destx,desty,zoffs;
 
 	// run shields
 	for (i = 0; i < numshields; i++)
@@ -5843,9 +5874,48 @@ void P_RunShields(void)
 		P_SetTarget(&shields[i], NULL);
 	}
 	numshields = 0;
+}
+
+static boolean P_AddShield(mobj_t *thing)
+{
+	shieldtype_t shield = thing->info->speed;
+
+	if (!thing->target || thing->target->health <= 0 || !thing->target->player
+		|| (thing->target->player->powers[pw_shield] & SH_NOSTACK) == SH_NONE || thing->target->player->powers[pw_super]
+		|| thing->target->player->powers[pw_invulnerability] > 1)
+	{
+		P_RemoveMobj(thing);
+		return false;
+	}
+
+	if (shield != SH_FORCE)
+	{ // Regular shields check for themselves only
+		if ((shieldtype_t)(thing->target->player->powers[pw_shield] & SH_NOSTACK) != shield)
+		{
+			P_RemoveMobj(thing);
+			return false;
+		}
+	}
+	else if (!(thing->target->player->powers[pw_shield] & SH_FORCE))
+	{ // Force shields check for any force shield
+		P_RemoveMobj(thing);
+		return false;
+	}
+
+	// Queue has been hit... why?!?
+	if (numshields >= MAXPLAYERS*2)
+		return P_ShieldLook(thing, thing->info->speed);
 
+	P_SetTarget(&shields[numshields++], thing);
+	return true;
+}
+
+void P_RunOverlays(void)
+{
 	// run overlays
-	next = NULL;
+	mobj_t *mo, *next = NULL;
+	fixed_t destx,desty,zoffs;
+
 	for (mo = overlaycap; mo; mo = next)
 	{
 		I_Assert(!P_MobjWasRemoved(mo));
@@ -5867,7 +5937,7 @@ void P_RunShields(void)
 			else
 				viewingangle = R_PointToAngle2(mo->target->x, mo->target->y, camera.x, camera.y);
 
-			if (mo->state->var1)
+			if (!(mo->state->frame & FF_ANIMATE) && mo->state->var1)
 				viewingangle += ANGLE_180;
 			destx = mo->target->x + P_ReturnThrustX(mo->target, viewingangle, FixedMul(FRACUNIT/4, mo->scale));
 			desty = mo->target->y + P_ReturnThrustY(mo->target, viewingangle, FixedMul(FRACUNIT/4, mo->scale));
@@ -5880,9 +5950,15 @@ void P_RunShields(void)
 
 		mo->eflags = (mo->eflags & ~MFE_VERTICALFLIP) | (mo->target->eflags & MFE_VERTICALFLIP);
 		mo->scale = mo->destscale = mo->target->scale;
-		zoffs = FixedMul(((signed)mo->state->var2)*FRACUNIT, mo->scale);
 		mo->angle = mo->target->angle;
 
+		if (!(mo->state->frame & FF_ANIMATE))
+			zoffs = FixedMul(((signed)mo->state->var2)*FRACUNIT, mo->scale);
+		// if you're using FF_ANIMATE on an overlay,
+		// then you're on your own.
+		else
+			zoffs = 0;
+
 		P_UnsetThingPosition(mo);
 		mo->x = destx;
 		mo->y = desty;
@@ -5899,40 +5975,6 @@ void P_RunShields(void)
 	P_SetTarget(&overlaycap, NULL);
 }
 
-static boolean P_AddShield(mobj_t *thing)
-{
-	shieldtype_t shield = thing->info->speed;
-
-	if (!thing->target || thing->target->health <= 0 || !thing->target->player
-		|| (thing->target->player->powers[pw_shield] & SH_NOSTACK) == SH_NONE || thing->target->player->powers[pw_super]
-		|| thing->target->player->powers[pw_invulnerability] > 1)
-	{
-		P_RemoveMobj(thing);
-		return false;
-	}
-
-	if (shield != SH_FORCE)
-	{ // Regular shields check for themselves only
-		if ((shieldtype_t)(thing->target->player->powers[pw_shield] & SH_NOSTACK) != shield)
-		{
-			P_RemoveMobj(thing);
-			return false;
-		}
-	}
-	else if (!(thing->target->player->powers[pw_shield] & SH_FORCE))
-	{ // Force shields check for any force shield
-		P_RemoveMobj(thing);
-		return false;
-	}
-
-	// Queue has been hit... why?!?
-	if (numshields >= MAXPLAYERS*2)
-		return P_ShieldLook(thing, thing->info->speed);
-
-	P_SetTarget(&shields[numshields++], thing);
-	return true;
-}
-
 // Called only when MT_OVERLAY thinks.
 static void P_AddOverlay(mobj_t *thing)
 {
@@ -7502,6 +7544,8 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
 	mobj->tics = st->tics;
 	mobj->sprite = st->sprite;
 	mobj->frame = st->frame; // FF_FRAMEMASK for frame, and other bits..
+	mobj->anim_duration = (UINT16)st->var2; // only used if FF_ANIMATE is set
+
 	mobj->friction = ORIG_FRICTION;
 
 	mobj->movefactor = ORIG_FRICTION_FACTOR;
@@ -7727,6 +7771,7 @@ static precipmobj_t *P_SpawnPrecipMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype
 	mobj->tics = st->tics;
 	mobj->sprite = st->sprite;
 	mobj->frame = st->frame; // FF_FRAMEMASK for frame, and other bits..
+	mobj->anim_duration = (UINT16)st->var2; // only used if FF_ANIMATE is set
 
 	// set subsector and/or block links
 	P_SetPrecipitationThingPosition(mobj);
diff --git a/src/p_mobj.h b/src/p_mobj.h
index 224a8ca5b93fa873f0a7352af82d08f90685368e..6198f5bec1c623876265144d508d400d48bbac2c 100644
--- a/src/p_mobj.h
+++ b/src/p_mobj.h
@@ -270,6 +270,7 @@ typedef struct mobj_s
 	angle_t angle;  // orientation
 	spritenum_t sprite; // used to find patch_t and flip value
 	UINT32 frame; // frame number, plus bits see p_pspr.h
+	UINT16 anim_duration; // for FF_ANIMATE states
 
 	struct msecnode_s *touching_sectorlist; // a linked list of sectors where this object appears
 
@@ -383,7 +384,8 @@ typedef struct precipmobj_s
 	// More drawing info: to determine current sprite.
 	angle_t angle;  // orientation
 	spritenum_t sprite; // used to find patch_t and flip value
-	INT32 frame; // frame number, plus bits see p_pspr.h
+	UINT32 frame; // frame number, plus bits see p_pspr.h
+	UINT16 anim_duration; // for FF_ANIMATE states
 
 	struct mprecipsecnode_s *touching_sectorlist; // a linked list of sectors where this object appears
 
diff --git a/src/p_pspr.h b/src/p_pspr.h
index e0b57675cd45568e3826c656d8edf17fd032f2ae..53ad30abded92fa887c0dc75f64780f3a96ea7bb 100644
--- a/src/p_pspr.h
+++ b/src/p_pspr.h
@@ -36,9 +36,11 @@
 #endif
 
 /// \brief Frame flags: only the frame number
-#define FF_FRAMEMASK 0x7fff
+#define FF_FRAMEMASK 0x3fff
+/// \brief Frame flags: Simple stateless animation
+#define FF_ANIMATE 0x4000
 /// \brief Frame flags: frame always appears full bright
-#define FF_FULLBRIGHT 0x8000  //
+#define FF_FULLBRIGHT 0x8000
 /// \brief Frame flags: 0 = no trans(opaque), 1-15 = transl. table
 #define FF_TRANSMASK 0xf0000
 /// \brief shift for FF_TRANSMASK
diff --git a/src/p_saveg.c b/src/p_saveg.c
index 61f51e497f75541fdb69e1eeb31ecc7f96376228..e0112bb79b84c5169b018f090c56117efb0cdef3 100644
--- a/src/p_saveg.c
+++ b/src/p_saveg.c
@@ -1058,6 +1058,8 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
 		diff |= MD_SPRITE;
 	if (mobj->frame != mobj->state->frame)
 		diff |= MD_FRAME;
+	if (mobj->anim_duration != (UINT16)mobj->state->var2)
+		diff |= MD_FRAME;
 	if (mobj->eflags)
 		diff |= MD_EFLAGS;
 	if (mobj->player)
@@ -1178,7 +1180,10 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
 	if (diff & MD_SPRITE)
 		WRITEUINT16(save_p, mobj->sprite);
 	if (diff & MD_FRAME)
+	{
 		WRITEUINT32(save_p, mobj->frame);
+		WRITEUINT16(save_p, mobj->anim_duration);
+	}
 	if (diff & MD_EFLAGS)
 		WRITEUINT16(save_p, mobj->eflags);
 	if (diff & MD_PLAYER)
@@ -2004,9 +2009,15 @@ static void LoadMobjThinker(actionf_p1 thinker)
 	else
 		mobj->sprite = mobj->state->sprite;
 	if (diff & MD_FRAME)
+	{
 		mobj->frame = READUINT32(save_p);
+		mobj->anim_duration = READUINT16(save_p);
+	}
 	else
+	{
 		mobj->frame = mobj->state->frame;
+		mobj->anim_duration = (UINT16)mobj->state->var2;
+	}
 	if (diff & MD_EFLAGS)
 		mobj->eflags = READUINT16(save_p);
 	if (diff & MD_PLAYER)
@@ -3192,7 +3203,7 @@ static inline boolean P_NetUnArchiveMisc(void)
 
 	// tell the sound code to reset the music since we're skipping what
 	// normally sets this flag
-	mapmusic |= MUSIC_RELOADRESET;
+	mapmusflags |= MUSIC_RELOADRESET;
 
 	G_SetGamestate(READINT16(save_p));
 
diff --git a/src/p_setup.c b/src/p_setup.c
index 3491669c7d9b1ab9ac7f39a9648eabf11f166fdc..a778469fba003dd5ae58021b70609dc7fea782e7 100644
--- a/src/p_setup.c
+++ b/src/p_setup.c
@@ -180,10 +180,11 @@ static void P_ClearSingleMapHeaderInfo(INT16 i)
 	mapheaderinfo[num]->typeoflevel = 0;
 	DEH_WriteUndoline("NEXTLEVEL", va("%d", mapheaderinfo[num]->nextlevel), UNDO_NONE);
 	mapheaderinfo[num]->nextlevel = (INT16)(i + 1);
-	DEH_WriteUndoline("MUSICSLOT", va("%d", mapheaderinfo[num]->musicslot), UNDO_NONE);
-	mapheaderinfo[num]->musicslot = mus_map01m + num;
-	DEH_WriteUndoline("MUSICSLOTTRACK", va("%d", mapheaderinfo[num]->musicslottrack), UNDO_NONE);
-	mapheaderinfo[num]->musicslottrack = 0;
+	DEH_WriteUndoline("MUSIC", mapheaderinfo[num]->musname, UNDO_NONE);
+	snprintf(mapheaderinfo[num]->musname, 7, "%sM", G_BuildMapName(i));
+	mapheaderinfo[num]->musname[6] = 0;
+	DEH_WriteUndoline("MUSICTRACK", va("%d", mapheaderinfo[num]->mustrack), UNDO_NONE);
+	mapheaderinfo[num]->mustrack = 0;
 	DEH_WriteUndoline("FORCECHARACTER", va("%d", mapheaderinfo[num]->forcecharacter), UNDO_NONE);
 	mapheaderinfo[num]->forcecharacter[0] = '\0';
 	DEH_WriteUndoline("WEATHER", va("%d", mapheaderinfo[num]->weather), UNDO_NONE);
@@ -1439,6 +1440,29 @@ static void P_LoadSideDefs2(lumpnum_t lumpnum)
 #endif
 
 			case 413: // Change music
+			{
+				char process[8+1];
+
+				sd->toptexture = sd->midtexture = sd->bottomtexture = 0;
+				if (msd->bottomtexture[0] != '-' || msd->bottomtexture[1] != '\0')
+				{
+					M_Memcpy(process,msd->bottomtexture,8);
+					process[8] = '\0';
+					sd->bottomtexture = get_number(process)-1;
+				}
+				M_Memcpy(process,msd->toptexture,8);
+				process[8] = '\0';
+				sd->text = Z_Malloc(7, PU_LEVEL, NULL);
+
+				// If they type in O_ or D_ and their music name, just shrug,
+				// then copy the rest instead.
+				if ((process[0] == 'O' || process[0] == 'D') && process[7])
+					M_Memcpy(sd->text, process+2, 6);
+				else // Assume it's a proper music name.
+					M_Memcpy(sd->text, process, 6);
+				sd->text[6] = 0;
+				break;
+			}
 			case 414: // Play SFX
 			{
 				sd->toptexture = sd->midtexture = sd->bottomtexture = 0;
@@ -1449,13 +1473,6 @@ static void P_LoadSideDefs2(lumpnum_t lumpnum)
 					process[8] = '\0';
 					sd->toptexture = get_number(process);
 				}
-				if (sd->special == 413 && (msd->bottomtexture[0] != '-' || msd->bottomtexture[1] != '\0'))
-				{
-					char process[8+1];
-					M_Memcpy(process,msd->bottomtexture,8);
-					process[8] = '\0';
-					sd->bottomtexture = get_number(process)-1;
-				}
 				break;
 			}
 
@@ -2369,7 +2386,7 @@ boolean P_SetupLevel(boolean skipprecip)
 	// use gamemap to get map number.
 	// 99% of the things already did, so.
 	// Map header should always be in place at this point
-	INT32 i, loadprecip = 1;
+	INT32 i, loadprecip = 1, ranspecialwipe = 0;
 	INT32 loademblems = 1;
 	INT32 fromnetsave = 0;
 	boolean loadedbm = false;
@@ -2442,6 +2459,28 @@ boolean P_SetupLevel(boolean skipprecip)
 	// will be set by player think.
 	players[consoleplayer].viewz = 1;
 
+	// Special stage fade to white
+	// This is handled BEFORE sounds are stopped.
+	if (rendermode != render_none && G_IsSpecialStage(gamemap))
+	{
+		tic_t starttime = I_GetTime();
+		tic_t endtime = starttime + (3*TICRATE)/2;
+
+		S_StartSound(NULL, sfx_s3kaf);
+
+		F_WipeStartScreen();
+		V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 0);
+
+		F_WipeEndScreen();
+		F_RunWipe(wipedefs[wipe_speclevel_towhite], false);
+
+		// Hold on white for extra effect.
+		while (I_GetTime() < endtime)
+			I_Sleep();
+
+		ranspecialwipe = 1;
+	}
+
 	// Make sure all sounds are stopped before Z_FreeTags.
 	S_StopSounds();
 	S_ClearSfx();
@@ -2451,25 +2490,28 @@ boolean P_SetupLevel(boolean skipprecip)
 	S_Start();
 
 	// Let's fade to black here
-	if (rendermode != render_none)
+	// But only if we didn't do the special stage wipe
+	if (rendermode != render_none && !ranspecialwipe)
 	{
 		F_WipeStartScreen();
 		V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);
 
 		F_WipeEndScreen();
 		F_RunWipe(wipedefs[wipe_level_toblack], false);
+	}
 
+	// Print "SPEEDING OFF TO [ZONE] [ACT 1]..."
+	if (rendermode != render_none)
+	{
 		// Don't include these in the fade!
-		{
-			char tx[64];
-			V_DrawSmallString(1, 191, V_ALLOWLOWERCASE, M_GetText("Speeding off to..."));
-			snprintf(tx, 63, "%s%s%s",
-				mapheaderinfo[gamemap-1]->lvlttl,
-				(mapheaderinfo[gamemap-1]->levelflags & LF_NOZONE) ? "" : " ZONE",
-				(mapheaderinfo[gamemap-1]->actnum > 0) ? va(", Act %d",mapheaderinfo[gamemap-1]->actnum) : "");
-			V_DrawSmallString(1, 195, V_ALLOWLOWERCASE, tx);
-			I_UpdateNoVsync();
-		}
+		char tx[64];
+		V_DrawSmallString(1, 191, V_ALLOWLOWERCASE, M_GetText("Speeding off to..."));
+		snprintf(tx, 63, "%s%s%s",
+			mapheaderinfo[gamemap-1]->lvlttl,
+			(mapheaderinfo[gamemap-1]->levelflags & LF_NOZONE) ? "" : " ZONE",
+			(mapheaderinfo[gamemap-1]->actnum > 0) ? va(", Act %d",mapheaderinfo[gamemap-1]->actnum) : "");
+		V_DrawSmallString(1, 195, V_ALLOWLOWERCASE, tx);
+		I_UpdateNoVsync();
 	}
 
 #ifdef HAVE_BLUA
@@ -2767,7 +2809,7 @@ boolean P_SetupLevel(boolean skipprecip)
 
 	// Remove the loading shit from the screen
 	if (rendermode != render_none)
-		V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31);
+		V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, (ranspecialwipe) ? 0 : 31);
 
 	if (precache || dedicated)
 		R_PrecacheLevel();
diff --git a/src/p_spec.c b/src/p_spec.c
index 81994d46c3f18eb8ed9f11807d6646d6fea140cc..f9fa5f1f1104002ac8c53b3fb1a0bc0131dbcabd 100644
--- a/src/p_spec.c
+++ b/src/p_spec.c
@@ -2390,20 +2390,19 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
 			// console player only unless NOCLIMB is set
 			if ((line->flags & ML_NOCLIMB) || (mo && mo->player && P_IsLocalPlayer(mo->player)))
 			{
-				UINT16 musicnum = (UINT16)sides[line->sidenum[0]].toptexture; //P_AproxDistance(line->dx, line->dy)>>FRACBITS;
 				UINT16 tracknum = (UINT16)sides[line->sidenum[0]].bottomtexture;
 
-				mapmusic = musicnum | (tracknum << MUSIC_TRACKSHIFT);
+				strncpy(mapmusname, sides[line->sidenum[0]].text, 7);
+				mapmusname[6] = 0;
+
+				mapmusflags = tracknum & MUSIC_TRACKMASK;
 				if (!(line->flags & ML_BLOCKMONSTERS))
-					mapmusic |= MUSIC_RELOADRESET;
+					mapmusflags |= MUSIC_RELOADRESET;
 
-				if (musicnum >= NUMMUSIC || musicnum == mus_None)
-					S_StopMusic();
-				else
-					S_ChangeMusic(mapmusic, !(line->flags & ML_EFFECT4));
+				S_ChangeMusic(mapmusname, mapmusflags, !(line->flags & ML_EFFECT4));
 
 				// Except, you can use the ML_BLOCKMONSTERS flag to change this behavior.
-				// if (mapmusic & MUSIC_RELOADRESET) then it will reset the music in G_PlayerReborn.
+				// if (mapmusflags & MUSIC_RELOADRESET) then it will reset the music in G_PlayerReborn.
 			}
 			break;
 
@@ -3039,6 +3038,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
 				INT16 foftag = (INT16)(sides[line->sidenum[0]].rowoffset>>FRACBITS);
 				sector_t *sec; // Sector that the FOF is visible (or not visible) in
 				ffloor_t *rover; // FOF to vanish/un-vanish
+				ffloortype_e oldflags; // store FOF's old flags
 
 				for (secnum = -1; (secnum = P_FindSectorFromTag(sectag, secnum)) >= 0 ;)
 				{
@@ -3062,11 +3062,17 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
 						return;
 					}
 
+					oldflags = rover->flags;
+
 					// Abracadabra!
 					if (line->flags & ML_NOCLIMB)
 						rover->flags |= FF_EXISTS;
 					else
 						rover->flags &= ~FF_EXISTS;
+
+					// if flags changed, reset sector's light list
+					if (rover->flags != oldflags)
+						sec->moved = true;
 				}
 			}
 			break;
diff --git a/src/p_tick.c b/src/p_tick.c
index 2973505f3c71fc4b564ceff566a741481b52ba95..c72ab5b6730053222bbd796462546241c5288826 100644
--- a/src/p_tick.c
+++ b/src/p_tick.c
@@ -631,6 +631,7 @@ void P_Ticker(boolean run)
 
 	// Run shield positioning
 	P_RunShields();
+	P_RunOverlays();
 
 	P_UpdateSpecials();
 	P_RespawnSpecials();
@@ -742,6 +743,7 @@ void P_PreTicker(INT32 frames)
 
 		// Run shield positioning
 		P_RunShields();
+		P_RunOverlays();
 
 		P_UpdateSpecials();
 		P_RespawnSpecials();
diff --git a/src/p_user.c b/src/p_user.c
index b3ba5f61f786f57c608d69b3c9acd7f5fa739b3f..68916d5a6a60875dffd829294cb7c19eed4893a4 100644
--- a/src/p_user.c
+++ b/src/p_user.c
@@ -962,7 +962,7 @@ void P_DoSuperTransformation(player_t *player, boolean giverings)
 	if (!(mapheaderinfo[gamemap-1]->levelflags & LF_NOSSMUSIC) && P_IsLocalPlayer(player))
 	{
 		S_StopMusic();
-		S_ChangeMusic(mus_supers, true);
+		S_ChangeMusicInternal("supers", true);
 	}
 
 	S_StartSound(NULL, sfx_supert); //let all players hear it -mattw_cfi
@@ -1098,7 +1098,7 @@ void P_PlayLivesJingle(player_t *player)
 		if (player)
 			player->powers[pw_extralife] = extralifetics + 1;
 		S_StopMusic(); // otherwise it won't restart if this is done twice in a row
-		S_ChangeMusic(mus_xtlife, false);
+		S_ChangeMusicInternal("xtlife", false);
 	}
 }
 
@@ -1116,21 +1116,21 @@ void P_RestoreMusic(player_t *player)
 		return;
 	S_SpeedMusic(1.0f);
 	if (player->powers[pw_super] && !(mapheaderinfo[gamemap-1]->levelflags & LF_NOSSMUSIC))
-		S_ChangeMusic(mus_supers, true);
+		S_ChangeMusicInternal("supers", true);
 	else if (player->powers[pw_invulnerability] > 1)
-		S_ChangeMusic((mariomode) ? mus_minvnc : mus_invinc, false);
+		S_ChangeMusicInternal((mariomode) ? "minvnc" : "invinc", false);
 	else if (player->powers[pw_sneakers] > 1 && !player->powers[pw_super])
 	{
 		if (mapheaderinfo[gamemap-1]->levelflags & LF_SPEEDMUSIC)
 		{
 			S_SpeedMusic(1.4f);
-			S_ChangeMusic(mapmusic, true);
+			S_ChangeMusic(mapmusname, mapmusflags, true);
 		}
 		else
-			S_ChangeMusic(mus_shoes, true);
+			S_ChangeMusicInternal("shoes", true);
 	}
 	else
-		S_ChangeMusic(mapmusic, true);
+		S_ChangeMusic(mapmusname, mapmusflags, true);
 }
 
 //
@@ -2039,7 +2039,7 @@ static void P_CheckUnderwaterAndSpaceTimer(player_t *player)
 		mobj_t *killer;
 
 		if ((netgame || multiplayer) && P_IsLocalPlayer(player))
-			S_ChangeMusic(mapmusic, true);
+			S_ChangeMusic(mapmusname, mapmusflags, true);
 
 		killer = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_NULL);
 		killer->threshold = 42; // Special flag that it was drowning which killed you.
@@ -2048,7 +2048,7 @@ static void P_CheckUnderwaterAndSpaceTimer(player_t *player)
 	else if (player->powers[pw_spacetime] == 1)
 	{
 		if ((netgame || multiplayer) && P_IsLocalPlayer(player))
-			S_ChangeMusic(mapmusic, true);
+			S_ChangeMusic(mapmusname, mapmusflags, true);
 
 		P_DamageMobj(player->mo, NULL, NULL, 10000);
 	}
@@ -2083,7 +2083,7 @@ static void P_CheckUnderwaterAndSpaceTimer(player_t *player)
 		&& player == &players[consoleplayer])
 		{
 			S_StopMusic();
-			S_ChangeMusic(mus_drown, false);
+			S_ChangeMusicInternal("drown", false);
 		}
 
 		if (player->powers[pw_underwater] == 25*TICRATE + 1)
@@ -3442,27 +3442,14 @@ static void P_DoSuperStuff(player_t *player)
 			player->mo->health--;
 		}
 
+		// future todo: a skin option for this, and possibly more colors
 		switch (player->skin)
 		{
-		case 1: // Golden orange supertails.
-			if (leveltime % 9 < 5)
-				player->mo->color = SKINCOLOR_TSUPER1 + leveltime % 9;
-			else
-				player->mo->color = SKINCOLOR_TSUPER1 + 9 - leveltime % 9;
-			break;
-		case 2: // Pink superknux.
-			if (leveltime % 9 < 5)
-				player->mo->color = SKINCOLOR_KSUPER1 + leveltime % 9;
-			else
-				player->mo->color = SKINCOLOR_KSUPER1 + 9 - leveltime % 9;
-			break;
-		default: // Yousa yellow now!
-			if (leveltime % 9 < 5)
-				player->mo->color = SKINCOLOR_SUPER1 + leveltime % 9;
-			else
-				player->mo->color = SKINCOLOR_SUPER1 + 9 - leveltime % 9;
-			break;
+			case 1:  /* Tails    */ player->mo->color = SKINCOLOR_TSUPER1; break;
+			case 2:  /* Knux     */ player->mo->color = SKINCOLOR_KSUPER1; break;
+			default: /* everyone */ player->mo->color = SKINCOLOR_SUPER1; break;
 		}
+		player->mo->color += abs( ( ( leveltime >> 1 ) % 9) - 4);
 
 		if ((cmd->forwardmove != 0 || cmd->sidemove != 0 || player->pflags & (PF_CARRIED|PF_ROPEHANG|PF_ITEMHANG|PF_MACESPIN))
 		&& !(leveltime % TICRATE) && (player->mo->momx || player->mo->momy))
@@ -5592,7 +5579,7 @@ static void P_NiGHTSMovement(player_t *player)
 	}
 	else if (P_IsLocalPlayer(player) && player->nightstime == 10*TICRATE)
 //		S_StartSound(NULL, sfx_timeup); // that creepy "out of time" music from NiGHTS. Dummied out, as some on the dev team thought it wasn't Sonic-y enough (Mystic, notably). Uncomment to restore. -SH
-		S_ChangeMusic(mus_drown,false);
+		S_ChangeMusicInternal("drown",false);
 
 
 	if (player->mo->z < player->mo->floorz)
@@ -7730,7 +7717,7 @@ static void P_DeathThink(player_t *player)
 
 		// Return to level music
 		if (netgame && player->deadtimer == gameovertics && P_IsLocalPlayer(player))
-			S_ChangeMusic(mapmusic, true);
+			S_ChangeMusic(mapmusname, mapmusflags, true);
 	}
 
 	if (!player->mo)
@@ -8716,7 +8703,7 @@ void P_PlayerThink(player_t *player)
 		if (countdown == 11*TICRATE - 1)
 		{
 			if (P_IsLocalPlayer(player))
-				S_ChangeMusic(mus_drown, false);
+				S_ChangeMusicInternal("drown", false);
 		}
 
 		// If you've hit the countdown and you haven't made
diff --git a/src/r_things.c b/src/r_things.c
index 2a3f8e7713e7899e3b30f098d2389f76c289a982..bdc6c47603eaadb7dd0046148f308bb38cddfe0c 100644
--- a/src/r_things.c
+++ b/src/r_things.c
@@ -2698,9 +2698,6 @@ next_token:
 		}
 		free(buf2);
 
-		// Not in vanilla, you don't.
-		skin->flags &= ~SF_SUPER;
-
 		lump++; // if no sprite defined use spirte just after this one
 		if (skin->sprite[0] == '\0')
 		{
diff --git a/src/s_sound.c b/src/s_sound.c
index 14a8cc425affc371676b146cdbddcaefa430c836..49373d94c445e7354123a36d7c36c63da9036c8a 100644
--- a/src/s_sound.c
+++ b/src/s_sound.c
@@ -141,14 +141,6 @@ typedef struct
 static channel_t *channels = NULL;
 static INT32 numofchannels = 0;
 
-// whether songs are mus_paused
-static boolean mus_paused = 0;
-
-// music currently being played
-musicinfo_t *mus_playing = 0;
-
-static INT32 nextcleanup;
-
 //
 // Internals.
 //
@@ -307,47 +299,6 @@ static void SetChannelsNum(void)
 		channels[i].sfxinfo = 0;
 }
 
-//
-// Initializes sound stuff, including volume
-// Sets channels, SFX and music volume,
-//  allocates channel buffer, sets S_sfx lookup.
-//
-void S_Init(INT32 sfxVolume, INT32 digMusicVolume, INT32 midiMusicVolume)
-{
-	INT32 i;
-
-	if (dedicated)
-		return;
-
-	S_SetSfxVolume(sfxVolume);
-	S_SetDigMusicVolume(digMusicVolume);
-	S_SetMIDIMusicVolume(midiMusicVolume);
-
-	SetChannelsNum();
-
-	// no sounds are playing, and they are not mus_paused
-	mus_paused = 0;
-
-	// Note that sounds have not been cached (yet).
-	for (i = 1; i < NUMSFX; i++)
-	{
-		S_sfx[i].usefulness = -1; // for I_GetSfx()
-		S_sfx[i].lumpnum = LUMPERROR;
-	}
-
-	// precache sounds if requested by cmdline, or precachesound var true
-	if (!nosound && (M_CheckParm("-precachesound") || precachesound.value))
-	{
-		// Initialize external data (all sounds) at start, keep static.
-		CONS_Printf(M_GetText("Loading sounds... "));
-
-		for (i = 1; i < NUMSFX; i++)
-			if (S_sfx[i].name)
-				S_sfx[i].data = I_GetSfx(&S_sfx[i]);
-
-		CONS_Printf(M_GetText(" pre-cached all sound data\n"));
-	}
-}
 
 // Retrieve the lump number of sfx
 //
@@ -371,12 +322,6 @@ lumpnum_t S_GetSfxLumpNum(sfxinfo_t *sfx)
 	return W_GetNumForName("dsthok");
 }
 
-//
-// Per level startup code.
-// Kills playing sounds at start of level,
-//  determines music if any, changes music.
-//
-
 // Stop all sounds, load level info, THEN start sounds.
 void S_StopSounds(void)
 {
@@ -442,22 +387,6 @@ void S_StopSoundByNum(sfxenum_t sfxnum)
 	}
 }
 
-void S_Start(void)
-{
-	if (mapmusic & MUSIC_RELOADRESET)
-	{
-		mapmusic = mapheaderinfo[gamemap-1]->musicslot
-			| (mapheaderinfo[gamemap-1]->musicslottrack << MUSIC_TRACKSHIFT);
-	}
-
-	mus_paused = 0;
-
-	if (cv_resetmusic.value)
-		S_StopMusic();
-	S_ChangeMusic(mapmusic, true);
-	nextcleanup = 15;
-}
-
 void S_StartSoundAtVolume(const void *origin_p, sfxenum_t sfx_id, INT32 volume)
 {
 	INT32 sep, pitch, priority, cnum;
@@ -745,43 +674,6 @@ void S_StopSound(void *origin)
 	}
 }
 
-//
-// Stop and resume music, during game PAUSE.
-//
-void S_PauseSound(void)
-{
-	if (!nodigimusic)
-		I_PauseSong(0);
-
-	if (mus_playing && !mus_paused)
-	{
-		I_PauseSong(mus_playing->handle);
-		mus_paused = true;
-	}
-
-	// pause cd music
-#if (defined (__unix__) && !defined (MSDOS)) || defined (UNIXCOMMON) || defined (HAVE_SDL)
-	I_PauseCD();
-#else
-	I_StopCD();
-#endif
-}
-
-void S_ResumeSound(void)
-{
-	if (!nodigimusic)
-		I_ResumeSong(0);
-	else
-	if (mus_playing && mus_paused)
-	{
-		I_ResumeSong(mus_playing->handle);
-		mus_paused = false;
-	}
-
-	// resume cd music
-	I_ResumeCD();
-}
-
 //
 // Updates music & sounds
 //
@@ -883,38 +775,6 @@ void S_UpdateSounds(void)
 		}
 	}
 
-	// Clean up unused data.
-#if 0
-	{
-		static tic_t nextcleanup = 0;
-		size_t i;
-		sfxinfo_t *sfx;
-
-		if (!gametic) nextcleanup = 0;
-		if (gametic > nextcleanup)
-		{
-			for (i = 1; i < NUMSFX; i++)
-			{
-				if (S_sfx[i].usefulness == 0)
-				{
-					S_sfx[i].usefulness--;
-
-					// don't forget to unlock it !!!
-					// __dmpi_unlock_....
-					//Z_ChangeTag(S_sfx[i].data, PU_CACHE);
-					I_FreeSfx(S_sfx+i);
-					//S_sfx[i].data = 0;
-
-					CONS_Debug(DBG_GAMELOGIC, "flushed sfx %.6s\n", S_sfx[i].name);
-				}
-			}
-			nextcleanup = gametic + 15;
-		}
-	}
-#endif
-
-	// FIXTHIS: nextcleanup is probably unused
-
 	for (cnum = 0; cnum < numofchannels; cnum++)
 	{
 		c = &channels[cnum];
@@ -984,37 +844,6 @@ void S_UpdateSounds(void)
 	I_UpdateSound();
 }
 
-void S_SetDigMusicVolume(INT32 volume)
-{
-	if (volume < 0 || volume > 31)
-		CONS_Alert(CONS_WARNING, "musicvolume should be between 0-31\n");
-
-	CV_SetValue(&cv_digmusicvolume, volume&31);
-	actualdigmusicvolume = cv_digmusicvolume.value;   //check for change of var
-
-#ifdef DJGPPDOS
-	I_SetDigMusicVolume(31); // Trick for buggy dos drivers. Win32 doesn't need this.
-#endif
-
-	if (!nodigimusic)
-		I_SetDigMusicVolume(volume&31);
-}
-
-void S_SetMIDIMusicVolume(INT32 volume)
-{
-	if (volume < 0 || volume > 31)
-		CONS_Alert(CONS_WARNING, "musicvolume should be between 0-31\n");
-
-	CV_SetValue(&cv_midimusicvolume, volume&0x1f);
-	actualmidimusicvolume = cv_midimusicvolume.value;   //check for change of var
-
-#ifdef DJGPPDOS
-	I_SetMIDIMusicVolume(31); // Trick for buggy dos drivers. Win32 doesn't need this.
-#endif
-
-	I_SetMIDIMusicVolume(volume&0x1f);
-}
-
 void S_SetSfxVolume(INT32 volume)
 {
 	if (volume < 0 || volume > 31)
@@ -1031,137 +860,6 @@ void S_SetSfxVolume(INT32 volume)
 #endif
 }
 
-static boolean S_MIDIMusic(musicinfo_t *music, boolean looping)
-{
-	if (nomidimusic)
-		return true; // no error
-
-	if (music_disabled)
-		return true; // no error
-
-	// get lumpnum if neccessary
-	if (!music->lumpnum)
-	{
-		if (W_CheckNumForName(va("d_%s", music->name)) == LUMPERROR)
-			return false;
-		music->lumpnum = W_GetNumForName(va("d_%s", music->name));
-	}
-
-	// load & register it
-	music->data = W_CacheLumpNum(music->lumpnum, PU_MUSIC);
-#if defined (macintosh) && !defined (HAVE_SDL)
-	music->handle = I_RegisterSong(music_num);
-#else
-	music->handle = I_RegisterSong(music->data, W_LumpLength(music->lumpnum));
-#endif
-
-#ifdef MUSSERV
-	if (msg_id != -1)
-	{
-		struct musmsg msg_buffer;
-
-		msg_buffer.msg_type = 6;
-		memset(msg_buffer.msg_text, 0, sizeof (msg_buffer.msg_text));
-		sprintf(msg_buffer.msg_text, "d_%s", music->name);
-		msgsnd(msg_id, (struct msgbuf*)&msg_buffer, sizeof (msg_buffer.msg_text), IPC_NOWAIT);
-	}
-#endif
-
-	// play it
-	if (!I_PlaySong(music->handle, looping))
-		return false;
-
-	mus_playing = music;
-	return true;
-}
-
-static boolean S_DigMusic(musicinfo_t *music, boolean looping)
-{
-	if (nodigimusic)
-		return false; // try midi
-
-	if (digital_disabled)
-		return false; // try midi
-
-	if (!I_StartDigSong(music->name, looping))
-		return false;
-
-	mus_playing = music;
-	return true;
-}
-
-void S_ChangeMusic(UINT32 mslotnum, boolean looping)
-{
-	musicinfo_t *music;
-	musicenum_t music_num = (signed)(mslotnum & MUSIC_SONGMASK);
-	INT32 track_num = (mslotnum & MUSIC_TRACKMASK) >> MUSIC_TRACKSHIFT;
-
-#if defined (DC) || defined (_WIN32_WCE) || defined (PSP) || defined(GP2X)
-	S_ClearSfx();
-#endif
-
-	if (nomidimusic && nodigimusic)
-		return;
-
-	if (music_disabled && digital_disabled)
-		return;
-
-	// No Music
-	if (music_num == mus_None)
-	{
-		S_StopMusic();
-		return;
-	}
-
-	if (music_num >= NUMMUSIC)
-	{
-		CONS_Alert(CONS_ERROR, "Bad music number %d\n", music_num);
-		return;
-	}
-	else
-		music = &S_music[music_num];
-
-	if (mus_playing != music)
-	{
-		S_StopMusic(); // shutdown old music
-		if (!S_DigMusic(music, looping) && !S_MIDIMusic(music, looping))
-		{
-			CONS_Alert(CONS_ERROR, M_GetText("Music lump %.6s not found!\n"), music->name);
-			return;
-		}
-	}
-	I_SetSongTrack(track_num);
-}
-
-boolean S_SpeedMusic(float speed)
-{
-	return I_SetSongSpeed(speed);
-}
-
-void S_StopMusic(void)
-{
-	if (!mus_playing)
-		return;
-
-	if (mus_paused)
-		I_ResumeSong(mus_playing->handle);
-
-	if (!nodigimusic)
-		I_StopDigSong();
-
-	S_SpeedMusic(1.0f);
-	I_StopSong(mus_playing->handle);
-	I_UnRegisterSong(mus_playing->handle);
-
-#ifndef HAVE_SDL //SDL uses RWOPS
-	Z_ChangeTag(mus_playing->data, PU_CACHE);
-#endif
-
-	mus_playing->data = NULL;
-	mus_playing = NULL;
-
-}
-
 void S_ClearSfx(void)
 {
 #ifndef DJGPPDOS
@@ -1452,3 +1150,285 @@ void S_StartSoundName(void *mo, const char *soundname)
 
 	S_StartSound(mo, soundnum);
 }
+
+/// ------------------------
+/// Music
+/// ------------------------
+
+#ifdef MUSICSLOT_COMPATIBILITY
+const char *compat_special_music_slots[16] =
+{
+	"titles", // 1036  title screen
+	"read_m", // 1037  intro
+	"lclear", // 1038  level clear
+	"invinc", // 1039  invincibility
+	"shoes",  // 1040  super sneakers
+	"minvnc", // 1041  Mario invincibility
+	"drown",  // 1042  drowning
+	"gmover", // 1043  game over
+	"xtlife", // 1044  extra life
+	"contsc", // 1045  continue screen
+	"supers", // 1046  Super Sonic
+	"chrsel", // 1047  character select
+	"credit", // 1048  credits
+	"racent", // 1049  Race Results
+	"stjr",   // 1050  Sonic Team Jr. Presents
+	""
+};
+#endif
+
+#define music_playing (music_name[0]) // String is empty if no music is playing
+
+static char      music_name[7]; // up to 6-character name
+static lumpnum_t music_lumpnum; // lump number of music (used??)
+static void     *music_data;    // music raw data
+static INT32     music_handle;  // once registered, the handle for the music
+
+static boolean mus_paused     = 0;  // whether songs are mus_paused
+
+static boolean S_MIDIMusic(const char *mname, boolean looping)
+{
+	lumpnum_t mlumpnum;
+	void *mdata;
+	INT32 mhandle;
+
+	if (nomidimusic || music_disabled)
+		return false; // didn't search.
+
+	if (W_CheckNumForName(va("d_%s", mname)) == LUMPERROR)
+		return false;
+	mlumpnum = W_GetNumForName(va("d_%s", mname));
+
+	// load & register it
+	mdata = W_CacheLumpNum(mlumpnum, PU_MUSIC);
+	mhandle = I_RegisterSong(mdata, W_LumpLength(mlumpnum));
+
+#ifdef MUSSERV
+	if (msg_id != -1)
+	{
+		struct musmsg msg_buffer;
+
+		msg_buffer.msg_type = 6;
+		memset(msg_buffer.msg_text, 0, sizeof (msg_buffer.msg_text));
+		sprintf(msg_buffer.msg_text, "d_%s", mname);
+		msgsnd(msg_id, (struct msgbuf*)&msg_buffer, sizeof (msg_buffer.msg_text), IPC_NOWAIT);
+	}
+#endif
+
+	// play it
+	if (!I_PlaySong(mhandle, looping))
+		return false;
+
+	strncpy(music_name, mname, 7);
+	music_name[6] = 0;
+	music_lumpnum = mlumpnum;
+	music_data = mdata;
+	music_handle = mhandle;
+	return true;
+}
+
+static boolean S_DigMusic(const char *mname, boolean looping)
+{
+	if (nodigimusic || digital_disabled)
+		return false; // try midi
+
+	if (!I_StartDigSong(mname, looping))
+		return false;
+
+	strncpy(music_name, mname, 7);
+	music_name[6] = 0;
+	music_lumpnum = LUMPERROR;
+	music_data = NULL;
+	music_handle = 0;
+	return true;
+}
+
+void S_ChangeMusic(const char *mmusic, UINT16 mflags, boolean looping)
+{
+#if defined (DC) || defined (_WIN32_WCE) || defined (PSP) || defined(GP2X)
+	S_ClearSfx();
+#endif
+
+	if ((nomidimusic || music_disabled) && (nodigimusic || digital_disabled))
+		return;
+
+	// No Music (empty string)
+	if (mmusic[0] == 0)
+	{
+		S_StopMusic();
+		return;
+	}
+
+	if (strncmp(music_name, mmusic, 6))
+	{
+		S_StopMusic(); // shutdown old music
+		if (!S_DigMusic(mmusic, looping) && !S_MIDIMusic(mmusic, looping))
+		{
+			CONS_Alert(CONS_ERROR, M_GetText("Music lump %.6s not found!\n"), mmusic);
+			return;
+		}
+	}
+	I_SetSongTrack(mflags & MUSIC_TRACKMASK);
+}
+
+boolean S_SpeedMusic(float speed)
+{
+	return I_SetSongSpeed(speed);
+}
+
+void S_StopMusic(void)
+{
+	if (!music_playing)
+		return;
+
+	if (mus_paused)
+		I_ResumeSong(music_handle);
+
+	if (!nodigimusic)
+		I_StopDigSong();
+
+	S_SpeedMusic(1.0f);
+	I_StopSong(music_handle);
+	I_UnRegisterSong(music_handle);
+
+#ifndef HAVE_SDL //SDL uses RWOPS
+	Z_ChangeTag(music_data, PU_CACHE);
+#endif
+
+	music_data = NULL;
+	music_name[0] = 0;
+}
+
+void S_SetDigMusicVolume(INT32 volume)
+{
+	if (volume < 0 || volume > 31)
+		CONS_Alert(CONS_WARNING, "musicvolume should be between 0-31\n");
+
+	CV_SetValue(&cv_digmusicvolume, volume&31);
+	actualdigmusicvolume = cv_digmusicvolume.value;   //check for change of var
+
+#ifdef DJGPPDOS
+	I_SetDigMusicVolume(31); // Trick for buggy dos drivers. Win32 doesn't need this.
+#endif
+	if (!nodigimusic)
+		I_SetDigMusicVolume(volume&31);
+}
+
+void S_SetMIDIMusicVolume(INT32 volume)
+{
+	if (volume < 0 || volume > 31)
+		CONS_Alert(CONS_WARNING, "musicvolume should be between 0-31\n");
+
+	CV_SetValue(&cv_midimusicvolume, volume&0x1f);
+	actualmidimusicvolume = cv_midimusicvolume.value;   //check for change of var
+
+#ifdef DJGPPDOS
+	I_SetMIDIMusicVolume(31); // Trick for buggy dos drivers. Win32 doesn't need this.
+#endif
+	I_SetMIDIMusicVolume(volume&0x1f);
+}
+
+/// ------------------------
+/// Init & Others
+/// ------------------------
+
+//
+// Initializes sound stuff, including volume
+// Sets channels, SFX and music volume,
+//  allocates channel buffer, sets S_sfx lookup.
+//
+void S_Init(INT32 sfxVolume, INT32 digMusicVolume, INT32 midiMusicVolume)
+{
+	INT32 i;
+
+	if (dedicated)
+		return;
+
+	S_SetSfxVolume(sfxVolume);
+	S_SetDigMusicVolume(digMusicVolume);
+	S_SetMIDIMusicVolume(midiMusicVolume);
+
+	SetChannelsNum();
+
+	// no sounds are playing, and they are not mus_paused
+	mus_paused = 0;
+
+	// Note that sounds have not been cached (yet).
+	for (i = 1; i < NUMSFX; i++)
+	{
+		S_sfx[i].usefulness = -1; // for I_GetSfx()
+		S_sfx[i].lumpnum = LUMPERROR;
+	}
+
+	// precache sounds if requested by cmdline, or precachesound var true
+	if (!nosound && (M_CheckParm("-precachesound") || precachesound.value))
+	{
+		// Initialize external data (all sounds) at start, keep static.
+		CONS_Printf(M_GetText("Loading sounds... "));
+
+		for (i = 1; i < NUMSFX; i++)
+			if (S_sfx[i].name)
+				S_sfx[i].data = I_GetSfx(&S_sfx[i]);
+
+		CONS_Printf(M_GetText(" pre-cached all sound data\n"));
+	}
+}
+
+
+//
+// Per level startup code.
+// Kills playing sounds at start of level,
+//  determines music if any, changes music.
+//
+void S_Start(void)
+{
+	if (mapmusflags & MUSIC_RELOADRESET)
+	{
+		strncpy(mapmusname, mapheaderinfo[gamemap-1]->musname, 7);
+		mapmusname[6] = 0;
+		mapmusflags = (mapheaderinfo[gamemap-1]->mustrack & MUSIC_TRACKMASK);
+	}
+
+	mus_paused = 0;
+
+	if (cv_resetmusic.value)
+		S_StopMusic();
+	S_ChangeMusic(mapmusname, mapmusflags, true);
+}
+
+//
+// Stop and resume music, during game PAUSE.
+//
+void S_PauseAudio(void)
+{
+	if (!nodigimusic)
+		I_PauseSong(0);
+
+	if (music_playing && !mus_paused)
+	{
+		I_PauseSong(music_handle);
+		mus_paused = true;
+	}
+
+	// pause cd music
+#if (defined (__unix__) && !defined (MSDOS)) || defined (UNIXCOMMON) || defined (HAVE_SDL)
+	I_PauseCD();
+#else
+	I_StopCD();
+#endif
+}
+
+void S_ResumeAudio(void)
+{
+	if (!nodigimusic)
+		I_ResumeSong(0);
+	else
+	if (music_playing && mus_paused)
+	{
+		I_ResumeSong(music_handle);
+		mus_paused = false;
+	}
+
+	// resume cd music
+	I_ResumeCD();
+}
diff --git a/src/s_sound.h b/src/s_sound.h
index 6589ca598657c7e63222297e641f10f5e76b9b1b..d5cf3570d5de7de7ab0a240c16f468fde7afd98a 100644
--- a/src/s_sound.h
+++ b/src/s_sound.h
@@ -48,9 +48,6 @@ typedef enum
 extern consvar_t play_mode;
 #endif
 
-//in case you're wondering why:  I need to define this as extern so P_RestoreMusic can get to it so we don't do stupid song/speed changes
-extern musicinfo_t *mus_playing;
-
 typedef enum
 {
 	SF_TOTALLYSINGLE =  1, // Only play one of these sounds at a time...GLOBALLY
@@ -100,11 +97,12 @@ void S_StartSoundAtVolume(const void *origin, sfxenum_t sound_id, INT32 volume);
 // Stop sound for thing at <origin>
 void S_StopSound(void *origin);
 
-// Start music using <music_id> from sounds.h, and set whether looping
-// note: music slot is first 16 bits for songnum,
-//       next 15 bits for tracknum (gme, other formats with more than one track)
+// Start music track, arbitrary, given its name, and set whether looping
+// note: music flags 12 bits for tracknum (gme, other formats with more than one track)
+//       13-15 aren't used yet
 //       and the last bit we ignore (internal game flag for resetting music on reload)
-void S_ChangeMusic(UINT32 mslotnum, boolean looping);
+#define S_ChangeMusicInternal(a,b) S_ChangeMusic(a,0,b)
+void S_ChangeMusic(const char *mmusic, UINT16 mflags, boolean looping);
 
 // Set Speed of Music
 boolean S_SpeedMusic(float speed);
@@ -113,8 +111,8 @@ boolean S_SpeedMusic(float speed);
 void S_StopMusic(void);
 
 // Stop and resume music, during game PAUSE.
-void S_PauseSound(void);
-void S_ResumeSound(void);
+void S_PauseAudio(void);
+void S_ResumeAudio(void);
 
 //
 // Updates music & sounds
@@ -141,4 +139,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
+const char *compat_special_music_slots[16];
+#endif
+
 #endif
diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c
index 50e5013946e9f59b2ab407163b3a8c16598bb718..0f96f47339e4fee106b506e9266e8f9546b94968 100644
--- a/src/sdl/mixer_sound.c
+++ b/src/sdl/mixer_sound.c
@@ -395,6 +395,7 @@ void I_FreeSfx(sfxinfo_t *sfx)
 	if (sfx->data)
 		Mix_FreeChunk(sfx->data);
 	sfx->data = NULL;
+	sfx->lumpnum = LUMPERROR;
 }
 
 INT32 I_StartSound(sfxenum_t id, UINT8 vol, UINT8 sep, UINT8 pitch, UINT8 priority)
diff --git a/src/sounds.c b/src/sounds.c
index 1ec86e7bc9349c4f3fb130898f467183877f4be1..97bdf23ec41fc2742448605b74372353155efc26 100644
--- a/src/sounds.c
+++ b/src/sounds.c
@@ -20,1067 +20,6 @@
 #include "w_wad.h"
 #include "lua_script.h"
 
-//
-// Information about all the music
-//
-
-musicinfo_t S_music[NUMMUSIC] =
-{
-	{NULL, 0, NULL, -1},
-	{"map01m", 0, NULL, -1},
-	{"map02m", 0, NULL, -1},
-	{"map03m", 0, NULL, -1},
-	{"map04m", 0, NULL, -1},
-	{"map05m", 0, NULL, -1},
-	{"map06m", 0, NULL, -1},
-	{"map07m", 0, NULL, -1},
-	{"map08m", 0, NULL, -1},
-	{"map09m", 0, NULL, -1},
-	{"map10m", 0, NULL, -1},
-	{"map11m", 0, NULL, -1},
-	{"map12m", 0, NULL, -1},
-	{"map13m", 0, NULL, -1},
-	{"map14m", 0, NULL, -1},
-	{"map15m", 0, NULL, -1},
-	{"map16m", 0, NULL, -1},
-	{"map17m", 0, NULL, -1},
-	{"map18m", 0, NULL, -1},
-	{"map19m", 0, NULL, -1},
-	{"map20m", 0, NULL, -1},
-	{"map21m", 0, NULL, -1},
-	{"map22m", 0, NULL, -1},
-	{"map23m", 0, NULL, -1},
-	{"map24m", 0, NULL, -1},
-	{"map25m", 0, NULL, -1},
-	{"map26m", 0, NULL, -1},
-	{"map27m", 0, NULL, -1},
-	{"map28m", 0, NULL, -1},
-	{"map29m", 0, NULL, -1},
-	{"map30m", 0, NULL, -1},
-	{"map31m", 0, NULL, -1},
-	{"map32m", 0, NULL, -1},
-	{"map33m", 0, NULL, -1},
-	{"map34m", 0, NULL, -1},
-	{"map35m", 0, NULL, -1},
-	{"map36m", 0, NULL, -1},
-	{"map37m", 0, NULL, -1},
-	{"map38m", 0, NULL, -1},
-	{"map39m", 0, NULL, -1},
-	{"map40m", 0, NULL, -1},
-	{"map41m", 0, NULL, -1},
-	{"map42m", 0, NULL, -1},
-	{"map43m", 0, NULL, -1},
-	{"map44m", 0, NULL, -1},
-	{"map45m", 0, NULL, -1},
-	{"map46m", 0, NULL, -1},
-	{"map47m", 0, NULL, -1},
-	{"map48m", 0, NULL, -1},
-	{"map49m", 0, NULL, -1},
-	{"map50m", 0, NULL, -1},
-	{"map51m", 0, NULL, -1},
-	{"map52m", 0, NULL, -1},
-	{"map53m", 0, NULL, -1},
-	{"map54m", 0, NULL, -1},
-	{"map55m", 0, NULL, -1},
-	{"map56m", 0, NULL, -1},
-	{"map57m", 0, NULL, -1},
-	{"map58m", 0, NULL, -1},
-	{"map59m", 0, NULL, -1},
-	{"map60m", 0, NULL, -1},
-	{"map61m", 0, NULL, -1},
-	{"map62m", 0, NULL, -1},
-	{"map63m", 0, NULL, -1},
-	{"map64m", 0, NULL, -1},
-	{"map65m", 0, NULL, -1},
-	{"map66m", 0, NULL, -1},
-	{"map67m", 0, NULL, -1},
-	{"map68m", 0, NULL, -1},
-	{"map69m", 0, NULL, -1},
-	{"map70m", 0, NULL, -1},
-	{"map71m", 0, NULL, -1},
-	{"map72m", 0, NULL, -1},
-	{"map73m", 0, NULL, -1},
-	{"map74m", 0, NULL, -1},
-	{"map75m", 0, NULL, -1},
-	{"map76m", 0, NULL, -1},
-	{"map77m", 0, NULL, -1},
-	{"map78m", 0, NULL, -1},
-	{"map79m", 0, NULL, -1},
-	{"map80m", 0, NULL, -1},
-	{"map81m", 0, NULL, -1},
-	{"map82m", 0, NULL, -1},
-	{"map83m", 0, NULL, -1},
-	{"map84m", 0, NULL, -1},
-	{"map85m", 0, NULL, -1},
-	{"map86m", 0, NULL, -1},
-	{"map87m", 0, NULL, -1},
-	{"map88m", 0, NULL, -1},
-	{"map89m", 0, NULL, -1},
-	{"map90m", 0, NULL, -1},
-	{"map91m", 0, NULL, -1},
-	{"map92m", 0, NULL, -1},
-	{"map93m", 0, NULL, -1},
-	{"map94m", 0, NULL, -1},
-	{"map95m", 0, NULL, -1},
-	{"map96m", 0, NULL, -1},
-	{"map97m", 0, NULL, -1},
-	{"map98m", 0, NULL, -1},
-	{"map99m", 0, NULL, -1},
-	{"mapa0m", 0, NULL, -1},
-	{"mapa1m", 0, NULL, -1},
-	{"mapa2m", 0, NULL, -1},
-	{"mapa3m", 0, NULL, -1},
-	{"mapa4m", 0, NULL, -1},
-	{"mapa5m", 0, NULL, -1},
-	{"mapa6m", 0, NULL, -1},
-	{"mapa7m", 0, NULL, -1},
-	{"mapa8m", 0, NULL, -1},
-	{"mapa9m", 0, NULL, -1},
-	{"mapaam", 0, NULL, -1},
-	{"mapabm", 0, NULL, -1},
-	{"mapacm", 0, NULL, -1},
-	{"mapadm", 0, NULL, -1},
-	{"mapaem", 0, NULL, -1},
-	{"mapafm", 0, NULL, -1},
-	{"mapagm", 0, NULL, -1},
-	{"mapahm", 0, NULL, -1},
-	{"mapaim", 0, NULL, -1},
-	{"mapajm", 0, NULL, -1},
-	{"mapakm", 0, NULL, -1},
-	{"mapalm", 0, NULL, -1},
-	{"mapamm", 0, NULL, -1},
-	{"mapanm", 0, NULL, -1},
-	{"mapaom", 0, NULL, -1},
-	{"mapapm", 0, NULL, -1},
-	{"mapaqm", 0, NULL, -1},
-	{"maparm", 0, NULL, -1},
-	{"mapasm", 0, NULL, -1},
-	{"mapatm", 0, NULL, -1},
-	{"mapaum", 0, NULL, -1},
-	{"mapavm", 0, NULL, -1},
-	{"mapawm", 0, NULL, -1},
-	{"mapaxm", 0, NULL, -1},
-	{"mapaym", 0, NULL, -1},
-	{"mapazm", 0, NULL, -1},
-	{"mapb0m", 0, NULL, -1},
-	{"mapb1m", 0, NULL, -1},
-	{"mapb2m", 0, NULL, -1},
-	{"mapb3m", 0, NULL, -1},
-	{"mapb4m", 0, NULL, -1},
-	{"mapb5m", 0, NULL, -1},
-	{"mapb6m", 0, NULL, -1},
-	{"mapb7m", 0, NULL, -1},
-	{"mapb8m", 0, NULL, -1},
-	{"mapb9m", 0, NULL, -1},
-	{"mapbam", 0, NULL, -1},
-	{"mapbbm", 0, NULL, -1},
-	{"mapbcm", 0, NULL, -1},
-	{"mapbdm", 0, NULL, -1},
-	{"mapbem", 0, NULL, -1},
-	{"mapbfm", 0, NULL, -1},
-	{"mapbgm", 0, NULL, -1},
-	{"mapbhm", 0, NULL, -1},
-	{"mapbim", 0, NULL, -1},
-	{"mapbjm", 0, NULL, -1},
-	{"mapbkm", 0, NULL, -1},
-	{"mapblm", 0, NULL, -1},
-	{"mapbmm", 0, NULL, -1},
-	{"mapbnm", 0, NULL, -1},
-	{"mapbom", 0, NULL, -1},
-	{"mapbpm", 0, NULL, -1},
-	{"mapbqm", 0, NULL, -1},
-	{"mapbrm", 0, NULL, -1},
-	{"mapbsm", 0, NULL, -1},
-	{"mapbtm", 0, NULL, -1},
-	{"mapbum", 0, NULL, -1},
-	{"mapbvm", 0, NULL, -1},
-	{"mapbwm", 0, NULL, -1},
-	{"mapbxm", 0, NULL, -1},
-	{"mapbym", 0, NULL, -1},
-	{"mapbzm", 0, NULL, -1},
-	{"mapc0m", 0, NULL, -1},
-	{"mapc1m", 0, NULL, -1},
-	{"mapc2m", 0, NULL, -1},
-	{"mapc3m", 0, NULL, -1},
-	{"mapc4m", 0, NULL, -1},
-	{"mapc5m", 0, NULL, -1},
-	{"mapc6m", 0, NULL, -1},
-	{"mapc7m", 0, NULL, -1},
-	{"mapc8m", 0, NULL, -1},
-	{"mapc9m", 0, NULL, -1},
-	{"mapcam", 0, NULL, -1},
-	{"mapcbm", 0, NULL, -1},
-	{"mapccm", 0, NULL, -1},
-	{"mapcdm", 0, NULL, -1},
-	{"mapcem", 0, NULL, -1},
-	{"mapcfm", 0, NULL, -1},
-	{"mapcgm", 0, NULL, -1},
-	{"mapchm", 0, NULL, -1},
-	{"mapcim", 0, NULL, -1},
-	{"mapcjm", 0, NULL, -1},
-	{"mapckm", 0, NULL, -1},
-	{"mapclm", 0, NULL, -1},
-	{"mapcmm", 0, NULL, -1},
-	{"mapcnm", 0, NULL, -1},
-	{"mapcom", 0, NULL, -1},
-	{"mapcpm", 0, NULL, -1},
-	{"mapcqm", 0, NULL, -1},
-	{"mapcrm", 0, NULL, -1},
-	{"mapcsm", 0, NULL, -1},
-	{"mapctm", 0, NULL, -1},
-	{"mapcum", 0, NULL, -1},
-	{"mapcvm", 0, NULL, -1},
-	{"mapcwm", 0, NULL, -1},
-	{"mapcxm", 0, NULL, -1},
-	{"mapcym", 0, NULL, -1},
-	{"mapczm", 0, NULL, -1},
-	{"mapd0m", 0, NULL, -1},
-	{"mapd1m", 0, NULL, -1},
-	{"mapd2m", 0, NULL, -1},
-	{"mapd3m", 0, NULL, -1},
-	{"mapd4m", 0, NULL, -1},
-	{"mapd5m", 0, NULL, -1},
-	{"mapd6m", 0, NULL, -1},
-	{"mapd7m", 0, NULL, -1},
-	{"mapd8m", 0, NULL, -1},
-	{"mapd9m", 0, NULL, -1},
-	{"mapdam", 0, NULL, -1},
-	{"mapdbm", 0, NULL, -1},
-	{"mapdcm", 0, NULL, -1},
-	{"mapddm", 0, NULL, -1},
-	{"mapdem", 0, NULL, -1},
-	{"mapdfm", 0, NULL, -1},
-	{"mapdgm", 0, NULL, -1},
-	{"mapdhm", 0, NULL, -1},
-	{"mapdim", 0, NULL, -1},
-	{"mapdjm", 0, NULL, -1},
-	{"mapdkm", 0, NULL, -1},
-	{"mapdlm", 0, NULL, -1},
-	{"mapdmm", 0, NULL, -1},
-	{"mapdnm", 0, NULL, -1},
-	{"mapdom", 0, NULL, -1},
-	{"mapdpm", 0, NULL, -1},
-	{"mapdqm", 0, NULL, -1},
-	{"mapdrm", 0, NULL, -1},
-	{"mapdsm", 0, NULL, -1},
-	{"mapdtm", 0, NULL, -1},
-	{"mapdum", 0, NULL, -1},
-	{"mapdvm", 0, NULL, -1},
-	{"mapdwm", 0, NULL, -1},
-	{"mapdxm", 0, NULL, -1},
-	{"mapdym", 0, NULL, -1},
-	{"mapdzm", 0, NULL, -1},
-	{"mape0m", 0, NULL, -1},
-	{"mape1m", 0, NULL, -1},
-	{"mape2m", 0, NULL, -1},
-	{"mape3m", 0, NULL, -1},
-	{"mape4m", 0, NULL, -1},
-	{"mape5m", 0, NULL, -1},
-	{"mape6m", 0, NULL, -1},
-	{"mape7m", 0, NULL, -1},
-	{"mape8m", 0, NULL, -1},
-	{"mape9m", 0, NULL, -1},
-	{"mapeam", 0, NULL, -1},
-	{"mapebm", 0, NULL, -1},
-	{"mapecm", 0, NULL, -1},
-	{"mapedm", 0, NULL, -1},
-	{"mapeem", 0, NULL, -1},
-	{"mapefm", 0, NULL, -1},
-	{"mapegm", 0, NULL, -1},
-	{"mapehm", 0, NULL, -1},
-	{"mapeim", 0, NULL, -1},
-	{"mapejm", 0, NULL, -1},
-	{"mapekm", 0, NULL, -1},
-	{"mapelm", 0, NULL, -1},
-	{"mapemm", 0, NULL, -1},
-	{"mapenm", 0, NULL, -1},
-	{"mapeom", 0, NULL, -1},
-	{"mapepm", 0, NULL, -1},
-	{"mapeqm", 0, NULL, -1},
-	{"maperm", 0, NULL, -1},
-	{"mapesm", 0, NULL, -1},
-	{"mapetm", 0, NULL, -1},
-	{"mapeum", 0, NULL, -1},
-	{"mapevm", 0, NULL, -1},
-	{"mapewm", 0, NULL, -1},
-	{"mapexm", 0, NULL, -1},
-	{"mapeym", 0, NULL, -1},
-	{"mapezm", 0, NULL, -1},
-	{"mapf0m", 0, NULL, -1},
-	{"mapf1m", 0, NULL, -1},
-	{"mapf2m", 0, NULL, -1},
-	{"mapf3m", 0, NULL, -1},
-	{"mapf4m", 0, NULL, -1},
-	{"mapf5m", 0, NULL, -1},
-	{"mapf6m", 0, NULL, -1},
-	{"mapf7m", 0, NULL, -1},
-	{"mapf8m", 0, NULL, -1},
-	{"mapf9m", 0, NULL, -1},
-	{"mapfam", 0, NULL, -1},
-	{"mapfbm", 0, NULL, -1},
-	{"mapfcm", 0, NULL, -1},
-	{"mapfdm", 0, NULL, -1},
-	{"mapfem", 0, NULL, -1},
-	{"mapffm", 0, NULL, -1},
-	{"mapfgm", 0, NULL, -1},
-	{"mapfhm", 0, NULL, -1},
-	{"mapfim", 0, NULL, -1},
-	{"mapfjm", 0, NULL, -1},
-	{"mapfkm", 0, NULL, -1},
-	{"mapflm", 0, NULL, -1},
-	{"mapfmm", 0, NULL, -1},
-	{"mapfnm", 0, NULL, -1},
-	{"mapfom", 0, NULL, -1},
-	{"mapfpm", 0, NULL, -1},
-	{"mapfqm", 0, NULL, -1},
-	{"mapfrm", 0, NULL, -1},
-	{"mapfsm", 0, NULL, -1},
-	{"mapftm", 0, NULL, -1},
-	{"mapfum", 0, NULL, -1},
-	{"mapfvm", 0, NULL, -1},
-	{"mapfwm", 0, NULL, -1},
-	{"mapfxm", 0, NULL, -1},
-	{"mapfym", 0, NULL, -1},
-	{"mapfzm", 0, NULL, -1},
-	{"mapg0m", 0, NULL, -1},
-	{"mapg1m", 0, NULL, -1},
-	{"mapg2m", 0, NULL, -1},
-	{"mapg3m", 0, NULL, -1},
-	{"mapg4m", 0, NULL, -1},
-	{"mapg5m", 0, NULL, -1},
-	{"mapg6m", 0, NULL, -1},
-	{"mapg7m", 0, NULL, -1},
-	{"mapg8m", 0, NULL, -1},
-	{"mapg9m", 0, NULL, -1},
-	{"mapgam", 0, NULL, -1},
-	{"mapgbm", 0, NULL, -1},
-	{"mapgcm", 0, NULL, -1},
-	{"mapgdm", 0, NULL, -1},
-	{"mapgem", 0, NULL, -1},
-	{"mapgfm", 0, NULL, -1},
-	{"mapggm", 0, NULL, -1},
-	{"mapghm", 0, NULL, -1},
-	{"mapgim", 0, NULL, -1},
-	{"mapgjm", 0, NULL, -1},
-	{"mapgkm", 0, NULL, -1},
-	{"mapglm", 0, NULL, -1},
-	{"mapgmm", 0, NULL, -1},
-	{"mapgnm", 0, NULL, -1},
-	{"mapgom", 0, NULL, -1},
-	{"mapgpm", 0, NULL, -1},
-	{"mapgqm", 0, NULL, -1},
-	{"mapgrm", 0, NULL, -1},
-	{"mapgsm", 0, NULL, -1},
-	{"mapgtm", 0, NULL, -1},
-	{"mapgum", 0, NULL, -1},
-	{"mapgvm", 0, NULL, -1},
-	{"mapgwm", 0, NULL, -1},
-	{"mapgxm", 0, NULL, -1},
-	{"mapgym", 0, NULL, -1},
-	{"mapgzm", 0, NULL, -1},
-	{"maph0m", 0, NULL, -1},
-	{"maph1m", 0, NULL, -1},
-	{"maph2m", 0, NULL, -1},
-	{"maph3m", 0, NULL, -1},
-	{"maph4m", 0, NULL, -1},
-	{"maph5m", 0, NULL, -1},
-	{"maph6m", 0, NULL, -1},
-	{"maph7m", 0, NULL, -1},
-	{"maph8m", 0, NULL, -1},
-	{"maph9m", 0, NULL, -1},
-	{"mapham", 0, NULL, -1},
-	{"maphbm", 0, NULL, -1},
-	{"maphcm", 0, NULL, -1},
-	{"maphdm", 0, NULL, -1},
-	{"maphem", 0, NULL, -1},
-	{"maphfm", 0, NULL, -1},
-	{"maphgm", 0, NULL, -1},
-	{"maphhm", 0, NULL, -1},
-	{"maphim", 0, NULL, -1},
-	{"maphjm", 0, NULL, -1},
-	{"maphkm", 0, NULL, -1},
-	{"maphlm", 0, NULL, -1},
-	{"maphmm", 0, NULL, -1},
-	{"maphnm", 0, NULL, -1},
-	{"maphom", 0, NULL, -1},
-	{"maphpm", 0, NULL, -1},
-	{"maphqm", 0, NULL, -1},
-	{"maphrm", 0, NULL, -1},
-	{"maphsm", 0, NULL, -1},
-	{"maphtm", 0, NULL, -1},
-	{"maphum", 0, NULL, -1},
-	{"maphvm", 0, NULL, -1},
-	{"maphwm", 0, NULL, -1},
-	{"maphxm", 0, NULL, -1},
-	{"maphym", 0, NULL, -1},
-	{"maphzm", 0, NULL, -1},
-	{"mapi0m", 0, NULL, -1},
-	{"mapi1m", 0, NULL, -1},
-	{"mapi2m", 0, NULL, -1},
-	{"mapi3m", 0, NULL, -1},
-	{"mapi4m", 0, NULL, -1},
-	{"mapi5m", 0, NULL, -1},
-	{"mapi6m", 0, NULL, -1},
-	{"mapi7m", 0, NULL, -1},
-	{"mapi8m", 0, NULL, -1},
-	{"mapi9m", 0, NULL, -1},
-	{"mapiam", 0, NULL, -1},
-	{"mapibm", 0, NULL, -1},
-	{"mapicm", 0, NULL, -1},
-	{"mapidm", 0, NULL, -1},
-	{"mapiem", 0, NULL, -1},
-	{"mapifm", 0, NULL, -1},
-	{"mapigm", 0, NULL, -1},
-	{"mapihm", 0, NULL, -1},
-	{"mapiim", 0, NULL, -1},
-	{"mapijm", 0, NULL, -1},
-	{"mapikm", 0, NULL, -1},
-	{"mapilm", 0, NULL, -1},
-	{"mapimm", 0, NULL, -1},
-	{"mapinm", 0, NULL, -1},
-	{"mapiom", 0, NULL, -1},
-	{"mapipm", 0, NULL, -1},
-	{"mapiqm", 0, NULL, -1},
-	{"mapirm", 0, NULL, -1},
-	{"mapism", 0, NULL, -1},
-	{"mapitm", 0, NULL, -1},
-	{"mapium", 0, NULL, -1},
-	{"mapivm", 0, NULL, -1},
-	{"mapiwm", 0, NULL, -1},
-	{"mapixm", 0, NULL, -1},
-	{"mapiym", 0, NULL, -1},
-	{"mapizm", 0, NULL, -1},
-	{"mapj0m", 0, NULL, -1},
-	{"mapj1m", 0, NULL, -1},
-	{"mapj2m", 0, NULL, -1},
-	{"mapj3m", 0, NULL, -1},
-	{"mapj4m", 0, NULL, -1},
-	{"mapj5m", 0, NULL, -1},
-	{"mapj6m", 0, NULL, -1},
-	{"mapj7m", 0, NULL, -1},
-	{"mapj8m", 0, NULL, -1},
-	{"mapj9m", 0, NULL, -1},
-	{"mapjam", 0, NULL, -1},
-	{"mapjbm", 0, NULL, -1},
-	{"mapjcm", 0, NULL, -1},
-	{"mapjdm", 0, NULL, -1},
-	{"mapjem", 0, NULL, -1},
-	{"mapjfm", 0, NULL, -1},
-	{"mapjgm", 0, NULL, -1},
-	{"mapjhm", 0, NULL, -1},
-	{"mapjim", 0, NULL, -1},
-	{"mapjjm", 0, NULL, -1},
-	{"mapjkm", 0, NULL, -1},
-	{"mapjlm", 0, NULL, -1},
-	{"mapjmm", 0, NULL, -1},
-	{"mapjnm", 0, NULL, -1},
-	{"mapjom", 0, NULL, -1},
-	{"mapjpm", 0, NULL, -1},
-	{"mapjqm", 0, NULL, -1},
-	{"mapjrm", 0, NULL, -1},
-	{"mapjsm", 0, NULL, -1},
-	{"mapjtm", 0, NULL, -1},
-	{"mapjum", 0, NULL, -1},
-	{"mapjvm", 0, NULL, -1},
-	{"mapjwm", 0, NULL, -1},
-	{"mapjxm", 0, NULL, -1},
-	{"mapjym", 0, NULL, -1},
-	{"mapjzm", 0, NULL, -1},
-	{"mapk0m", 0, NULL, -1},
-	{"mapk1m", 0, NULL, -1},
-	{"mapk2m", 0, NULL, -1},
-	{"mapk3m", 0, NULL, -1},
-	{"mapk4m", 0, NULL, -1},
-	{"mapk5m", 0, NULL, -1},
-	{"mapk6m", 0, NULL, -1},
-	{"mapk7m", 0, NULL, -1},
-	{"mapk8m", 0, NULL, -1},
-	{"mapk9m", 0, NULL, -1},
-	{"mapkam", 0, NULL, -1},
-	{"mapkbm", 0, NULL, -1},
-	{"mapkcm", 0, NULL, -1},
-	{"mapkdm", 0, NULL, -1},
-	{"mapkem", 0, NULL, -1},
-	{"mapkfm", 0, NULL, -1},
-	{"mapkgm", 0, NULL, -1},
-	{"mapkhm", 0, NULL, -1},
-	{"mapkim", 0, NULL, -1},
-	{"mapkjm", 0, NULL, -1},
-	{"mapkkm", 0, NULL, -1},
-	{"mapklm", 0, NULL, -1},
-	{"mapkmm", 0, NULL, -1},
-	{"mapknm", 0, NULL, -1},
-	{"mapkom", 0, NULL, -1},
-	{"mapkpm", 0, NULL, -1},
-	{"mapkqm", 0, NULL, -1},
-	{"mapkrm", 0, NULL, -1},
-	{"mapksm", 0, NULL, -1},
-	{"mapktm", 0, NULL, -1},
-	{"mapkum", 0, NULL, -1},
-	{"mapkvm", 0, NULL, -1},
-	{"mapkwm", 0, NULL, -1},
-	{"mapkxm", 0, NULL, -1},
-	{"mapkym", 0, NULL, -1},
-	{"mapkzm", 0, NULL, -1},
-	{"mapl0m", 0, NULL, -1},
-	{"mapl1m", 0, NULL, -1},
-	{"mapl2m", 0, NULL, -1},
-	{"mapl3m", 0, NULL, -1},
-	{"mapl4m", 0, NULL, -1},
-	{"mapl5m", 0, NULL, -1},
-	{"mapl6m", 0, NULL, -1},
-	{"mapl7m", 0, NULL, -1},
-	{"mapl8m", 0, NULL, -1},
-	{"mapl9m", 0, NULL, -1},
-	{"maplam", 0, NULL, -1},
-	{"maplbm", 0, NULL, -1},
-	{"maplcm", 0, NULL, -1},
-	{"mapldm", 0, NULL, -1},
-	{"maplem", 0, NULL, -1},
-	{"maplfm", 0, NULL, -1},
-	{"maplgm", 0, NULL, -1},
-	{"maplhm", 0, NULL, -1},
-	{"maplim", 0, NULL, -1},
-	{"mapljm", 0, NULL, -1},
-	{"maplkm", 0, NULL, -1},
-	{"mapllm", 0, NULL, -1},
-	{"maplmm", 0, NULL, -1},
-	{"maplnm", 0, NULL, -1},
-	{"maplom", 0, NULL, -1},
-	{"maplpm", 0, NULL, -1},
-	{"maplqm", 0, NULL, -1},
-	{"maplrm", 0, NULL, -1},
-	{"maplsm", 0, NULL, -1},
-	{"mapltm", 0, NULL, -1},
-	{"maplum", 0, NULL, -1},
-	{"maplvm", 0, NULL, -1},
-	{"maplwm", 0, NULL, -1},
-	{"maplxm", 0, NULL, -1},
-	{"maplym", 0, NULL, -1},
-	{"maplzm", 0, NULL, -1},
-	{"mapm0m", 0, NULL, -1},
-	{"mapm1m", 0, NULL, -1},
-	{"mapm2m", 0, NULL, -1},
-	{"mapm3m", 0, NULL, -1},
-	{"mapm4m", 0, NULL, -1},
-	{"mapm5m", 0, NULL, -1},
-	{"mapm6m", 0, NULL, -1},
-	{"mapm7m", 0, NULL, -1},
-	{"mapm8m", 0, NULL, -1},
-	{"mapm9m", 0, NULL, -1},
-	{"mapmam", 0, NULL, -1},
-	{"mapmbm", 0, NULL, -1},
-	{"mapmcm", 0, NULL, -1},
-	{"mapmdm", 0, NULL, -1},
-	{"mapmem", 0, NULL, -1},
-	{"mapmfm", 0, NULL, -1},
-	{"mapmgm", 0, NULL, -1},
-	{"mapmhm", 0, NULL, -1},
-	{"mapmim", 0, NULL, -1},
-	{"mapmjm", 0, NULL, -1},
-	{"mapmkm", 0, NULL, -1},
-	{"mapmlm", 0, NULL, -1},
-	{"mapmmm", 0, NULL, -1},
-	{"mapmnm", 0, NULL, -1},
-	{"mapmom", 0, NULL, -1},
-	{"mapmpm", 0, NULL, -1},
-	{"mapmqm", 0, NULL, -1},
-	{"mapmrm", 0, NULL, -1},
-	{"mapmsm", 0, NULL, -1},
-	{"mapmtm", 0, NULL, -1},
-	{"mapmum", 0, NULL, -1},
-	{"mapmvm", 0, NULL, -1},
-	{"mapmwm", 0, NULL, -1},
-	{"mapmxm", 0, NULL, -1},
-	{"mapmym", 0, NULL, -1},
-	{"mapmzm", 0, NULL, -1},
-	{"mapn0m", 0, NULL, -1},
-	{"mapn1m", 0, NULL, -1},
-	{"mapn2m", 0, NULL, -1},
-	{"mapn3m", 0, NULL, -1},
-	{"mapn4m", 0, NULL, -1},
-	{"mapn5m", 0, NULL, -1},
-	{"mapn6m", 0, NULL, -1},
-	{"mapn7m", 0, NULL, -1},
-	{"mapn8m", 0, NULL, -1},
-	{"mapn9m", 0, NULL, -1},
-	{"mapnam", 0, NULL, -1},
-	{"mapnbm", 0, NULL, -1},
-	{"mapncm", 0, NULL, -1},
-	{"mapndm", 0, NULL, -1},
-	{"mapnem", 0, NULL, -1},
-	{"mapnfm", 0, NULL, -1},
-	{"mapngm", 0, NULL, -1},
-	{"mapnhm", 0, NULL, -1},
-	{"mapnim", 0, NULL, -1},
-	{"mapnjm", 0, NULL, -1},
-	{"mapnkm", 0, NULL, -1},
-	{"mapnlm", 0, NULL, -1},
-	{"mapnmm", 0, NULL, -1},
-	{"mapnnm", 0, NULL, -1},
-	{"mapnom", 0, NULL, -1},
-	{"mapnpm", 0, NULL, -1},
-	{"mapnqm", 0, NULL, -1},
-	{"mapnrm", 0, NULL, -1},
-	{"mapnsm", 0, NULL, -1},
-	{"mapntm", 0, NULL, -1},
-	{"mapnum", 0, NULL, -1},
-	{"mapnvm", 0, NULL, -1},
-	{"mapnwm", 0, NULL, -1},
-	{"mapnxm", 0, NULL, -1},
-	{"mapnym", 0, NULL, -1},
-	{"mapnzm", 0, NULL, -1},
-	{"mapo0m", 0, NULL, -1},
-	{"mapo1m", 0, NULL, -1},
-	{"mapo2m", 0, NULL, -1},
-	{"mapo3m", 0, NULL, -1},
-	{"mapo4m", 0, NULL, -1},
-	{"mapo5m", 0, NULL, -1},
-	{"mapo6m", 0, NULL, -1},
-	{"mapo7m", 0, NULL, -1},
-	{"mapo8m", 0, NULL, -1},
-	{"mapo9m", 0, NULL, -1},
-	{"mapoam", 0, NULL, -1},
-	{"mapobm", 0, NULL, -1},
-	{"mapocm", 0, NULL, -1},
-	{"mapodm", 0, NULL, -1},
-	{"mapoem", 0, NULL, -1},
-	{"mapofm", 0, NULL, -1},
-	{"mapogm", 0, NULL, -1},
-	{"mapohm", 0, NULL, -1},
-	{"mapoim", 0, NULL, -1},
-	{"mapojm", 0, NULL, -1},
-	{"mapokm", 0, NULL, -1},
-	{"mapolm", 0, NULL, -1},
-	{"mapomm", 0, NULL, -1},
-	{"maponm", 0, NULL, -1},
-	{"mapoom", 0, NULL, -1},
-	{"mapopm", 0, NULL, -1},
-	{"mapoqm", 0, NULL, -1},
-	{"maporm", 0, NULL, -1},
-	{"maposm", 0, NULL, -1},
-	{"mapotm", 0, NULL, -1},
-	{"mapoum", 0, NULL, -1},
-	{"mapovm", 0, NULL, -1},
-	{"mapowm", 0, NULL, -1},
-	{"mapoxm", 0, NULL, -1},
-	{"mapoym", 0, NULL, -1},
-	{"mapozm", 0, NULL, -1},
-	{"mapp0m", 0, NULL, -1},
-	{"mapp1m", 0, NULL, -1},
-	{"mapp2m", 0, NULL, -1},
-	{"mapp3m", 0, NULL, -1},
-	{"mapp4m", 0, NULL, -1},
-	{"mapp5m", 0, NULL, -1},
-	{"mapp6m", 0, NULL, -1},
-	{"mapp7m", 0, NULL, -1},
-	{"mapp8m", 0, NULL, -1},
-	{"mapp9m", 0, NULL, -1},
-	{"mappam", 0, NULL, -1},
-	{"mappbm", 0, NULL, -1},
-	{"mappcm", 0, NULL, -1},
-	{"mappdm", 0, NULL, -1},
-	{"mappem", 0, NULL, -1},
-	{"mappfm", 0, NULL, -1},
-	{"mappgm", 0, NULL, -1},
-	{"mapphm", 0, NULL, -1},
-	{"mappim", 0, NULL, -1},
-	{"mappjm", 0, NULL, -1},
-	{"mappkm", 0, NULL, -1},
-	{"mapplm", 0, NULL, -1},
-	{"mappmm", 0, NULL, -1},
-	{"mappnm", 0, NULL, -1},
-	{"mappom", 0, NULL, -1},
-	{"mapppm", 0, NULL, -1},
-	{"mappqm", 0, NULL, -1},
-	{"mapprm", 0, NULL, -1},
-	{"mappsm", 0, NULL, -1},
-	{"mapptm", 0, NULL, -1},
-	{"mappum", 0, NULL, -1},
-	{"mappvm", 0, NULL, -1},
-	{"mappwm", 0, NULL, -1},
-	{"mappxm", 0, NULL, -1},
-	{"mappym", 0, NULL, -1},
-	{"mappzm", 0, NULL, -1},
-	{"mapq0m", 0, NULL, -1},
-	{"mapq1m", 0, NULL, -1},
-	{"mapq2m", 0, NULL, -1},
-	{"mapq3m", 0, NULL, -1},
-	{"mapq4m", 0, NULL, -1},
-	{"mapq5m", 0, NULL, -1},
-	{"mapq6m", 0, NULL, -1},
-	{"mapq7m", 0, NULL, -1},
-	{"mapq8m", 0, NULL, -1},
-	{"mapq9m", 0, NULL, -1},
-	{"mapqam", 0, NULL, -1},
-	{"mapqbm", 0, NULL, -1},
-	{"mapqcm", 0, NULL, -1},
-	{"mapqdm", 0, NULL, -1},
-	{"mapqem", 0, NULL, -1},
-	{"mapqfm", 0, NULL, -1},
-	{"mapqgm", 0, NULL, -1},
-	{"mapqhm", 0, NULL, -1},
-	{"mapqim", 0, NULL, -1},
-	{"mapqjm", 0, NULL, -1},
-	{"mapqkm", 0, NULL, -1},
-	{"mapqlm", 0, NULL, -1},
-	{"mapqmm", 0, NULL, -1},
-	{"mapqnm", 0, NULL, -1},
-	{"mapqom", 0, NULL, -1},
-	{"mapqpm", 0, NULL, -1},
-	{"mapqqm", 0, NULL, -1},
-	{"mapqrm", 0, NULL, -1},
-	{"mapqsm", 0, NULL, -1},
-	{"mapqtm", 0, NULL, -1},
-	{"mapqum", 0, NULL, -1},
-	{"mapqvm", 0, NULL, -1},
-	{"mapqwm", 0, NULL, -1},
-	{"mapqxm", 0, NULL, -1},
-	{"mapqym", 0, NULL, -1},
-	{"mapqzm", 0, NULL, -1},
-	{"mapr0m", 0, NULL, -1},
-	{"mapr1m", 0, NULL, -1},
-	{"mapr2m", 0, NULL, -1},
-	{"mapr3m", 0, NULL, -1},
-	{"mapr4m", 0, NULL, -1},
-	{"mapr5m", 0, NULL, -1},
-	{"mapr6m", 0, NULL, -1},
-	{"mapr7m", 0, NULL, -1},
-	{"mapr8m", 0, NULL, -1},
-	{"mapr9m", 0, NULL, -1},
-	{"mapram", 0, NULL, -1},
-	{"maprbm", 0, NULL, -1},
-	{"maprcm", 0, NULL, -1},
-	{"maprdm", 0, NULL, -1},
-	{"maprem", 0, NULL, -1},
-	{"maprfm", 0, NULL, -1},
-	{"maprgm", 0, NULL, -1},
-	{"maprhm", 0, NULL, -1},
-	{"maprim", 0, NULL, -1},
-	{"maprjm", 0, NULL, -1},
-	{"maprkm", 0, NULL, -1},
-	{"maprlm", 0, NULL, -1},
-	{"maprmm", 0, NULL, -1},
-	{"maprnm", 0, NULL, -1},
-	{"maprom", 0, NULL, -1},
-	{"maprpm", 0, NULL, -1},
-	{"maprqm", 0, NULL, -1},
-	{"maprrm", 0, NULL, -1},
-	{"maprsm", 0, NULL, -1},
-	{"maprtm", 0, NULL, -1},
-	{"maprum", 0, NULL, -1},
-	{"maprvm", 0, NULL, -1},
-	{"maprwm", 0, NULL, -1},
-	{"maprxm", 0, NULL, -1},
-	{"maprym", 0, NULL, -1},
-	{"maprzm", 0, NULL, -1},
-	{"maps0m", 0, NULL, -1},
-	{"maps1m", 0, NULL, -1},
-	{"maps2m", 0, NULL, -1},
-	{"maps3m", 0, NULL, -1},
-	{"maps4m", 0, NULL, -1},
-	{"maps5m", 0, NULL, -1},
-	{"maps6m", 0, NULL, -1},
-	{"maps7m", 0, NULL, -1},
-	{"maps8m", 0, NULL, -1},
-	{"maps9m", 0, NULL, -1},
-	{"mapsam", 0, NULL, -1},
-	{"mapsbm", 0, NULL, -1},
-	{"mapscm", 0, NULL, -1},
-	{"mapsdm", 0, NULL, -1},
-	{"mapsem", 0, NULL, -1},
-	{"mapsfm", 0, NULL, -1},
-	{"mapsgm", 0, NULL, -1},
-	{"mapshm", 0, NULL, -1},
-	{"mapsim", 0, NULL, -1},
-	{"mapsjm", 0, NULL, -1},
-	{"mapskm", 0, NULL, -1},
-	{"mapslm", 0, NULL, -1},
-	{"mapsmm", 0, NULL, -1},
-	{"mapsnm", 0, NULL, -1},
-	{"mapsom", 0, NULL, -1},
-	{"mapspm", 0, NULL, -1},
-	{"mapsqm", 0, NULL, -1},
-	{"mapsrm", 0, NULL, -1},
-	{"mapssm", 0, NULL, -1},
-	{"mapstm", 0, NULL, -1},
-	{"mapsum", 0, NULL, -1},
-	{"mapsvm", 0, NULL, -1},
-	{"mapswm", 0, NULL, -1},
-	{"mapsxm", 0, NULL, -1},
-	{"mapsym", 0, NULL, -1},
-	{"mapszm", 0, NULL, -1},
-	{"mapt0m", 0, NULL, -1},
-	{"mapt1m", 0, NULL, -1},
-	{"mapt2m", 0, NULL, -1},
-	{"mapt3m", 0, NULL, -1},
-	{"mapt4m", 0, NULL, -1},
-	{"mapt5m", 0, NULL, -1},
-	{"mapt6m", 0, NULL, -1},
-	{"mapt7m", 0, NULL, -1},
-	{"mapt8m", 0, NULL, -1},
-	{"mapt9m", 0, NULL, -1},
-	{"maptam", 0, NULL, -1},
-	{"maptbm", 0, NULL, -1},
-	{"maptcm", 0, NULL, -1},
-	{"maptdm", 0, NULL, -1},
-	{"maptem", 0, NULL, -1},
-	{"maptfm", 0, NULL, -1},
-	{"maptgm", 0, NULL, -1},
-	{"mapthm", 0, NULL, -1},
-	{"maptim", 0, NULL, -1},
-	{"maptjm", 0, NULL, -1},
-	{"maptkm", 0, NULL, -1},
-	{"maptlm", 0, NULL, -1},
-	{"maptmm", 0, NULL, -1},
-	{"maptnm", 0, NULL, -1},
-	{"maptom", 0, NULL, -1},
-	{"maptpm", 0, NULL, -1},
-	{"maptqm", 0, NULL, -1},
-	{"maptrm", 0, NULL, -1},
-	{"maptsm", 0, NULL, -1},
-	{"mapttm", 0, NULL, -1},
-	{"maptum", 0, NULL, -1},
-	{"maptvm", 0, NULL, -1},
-	{"maptwm", 0, NULL, -1},
-	{"maptxm", 0, NULL, -1},
-	{"maptym", 0, NULL, -1},
-	{"maptzm", 0, NULL, -1},
-	{"mapu0m", 0, NULL, -1},
-	{"mapu1m", 0, NULL, -1},
-	{"mapu2m", 0, NULL, -1},
-	{"mapu3m", 0, NULL, -1},
-	{"mapu4m", 0, NULL, -1},
-	{"mapu5m", 0, NULL, -1},
-	{"mapu6m", 0, NULL, -1},
-	{"mapu7m", 0, NULL, -1},
-	{"mapu8m", 0, NULL, -1},
-	{"mapu9m", 0, NULL, -1},
-	{"mapuam", 0, NULL, -1},
-	{"mapubm", 0, NULL, -1},
-	{"mapucm", 0, NULL, -1},
-	{"mapudm", 0, NULL, -1},
-	{"mapuem", 0, NULL, -1},
-	{"mapufm", 0, NULL, -1},
-	{"mapugm", 0, NULL, -1},
-	{"mapuhm", 0, NULL, -1},
-	{"mapuim", 0, NULL, -1},
-	{"mapujm", 0, NULL, -1},
-	{"mapukm", 0, NULL, -1},
-	{"mapulm", 0, NULL, -1},
-	{"mapumm", 0, NULL, -1},
-	{"mapunm", 0, NULL, -1},
-	{"mapuom", 0, NULL, -1},
-	{"mapupm", 0, NULL, -1},
-	{"mapuqm", 0, NULL, -1},
-	{"mapurm", 0, NULL, -1},
-	{"mapusm", 0, NULL, -1},
-	{"maputm", 0, NULL, -1},
-	{"mapuum", 0, NULL, -1},
-	{"mapuvm", 0, NULL, -1},
-	{"mapuwm", 0, NULL, -1},
-	{"mapuxm", 0, NULL, -1},
-	{"mapuym", 0, NULL, -1},
-	{"mapuzm", 0, NULL, -1},
-	{"mapv0m", 0, NULL, -1},
-	{"mapv1m", 0, NULL, -1},
-	{"mapv2m", 0, NULL, -1},
-	{"mapv3m", 0, NULL, -1},
-	{"mapv4m", 0, NULL, -1},
-	{"mapv5m", 0, NULL, -1},
-	{"mapv6m", 0, NULL, -1},
-	{"mapv7m", 0, NULL, -1},
-	{"mapv8m", 0, NULL, -1},
-	{"mapv9m", 0, NULL, -1},
-	{"mapvam", 0, NULL, -1},
-	{"mapvbm", 0, NULL, -1},
-	{"mapvcm", 0, NULL, -1},
-	{"mapvdm", 0, NULL, -1},
-	{"mapvem", 0, NULL, -1},
-	{"mapvfm", 0, NULL, -1},
-	{"mapvgm", 0, NULL, -1},
-	{"mapvhm", 0, NULL, -1},
-	{"mapvim", 0, NULL, -1},
-	{"mapvjm", 0, NULL, -1},
-	{"mapvkm", 0, NULL, -1},
-	{"mapvlm", 0, NULL, -1},
-	{"mapvmm", 0, NULL, -1},
-	{"mapvnm", 0, NULL, -1},
-	{"mapvom", 0, NULL, -1},
-	{"mapvpm", 0, NULL, -1},
-	{"mapvqm", 0, NULL, -1},
-	{"mapvrm", 0, NULL, -1},
-	{"mapvsm", 0, NULL, -1},
-	{"mapvtm", 0, NULL, -1},
-	{"mapvum", 0, NULL, -1},
-	{"mapvvm", 0, NULL, -1},
-	{"mapvwm", 0, NULL, -1},
-	{"mapvxm", 0, NULL, -1},
-	{"mapvym", 0, NULL, -1},
-	{"mapvzm", 0, NULL, -1},
-	{"mapw0m", 0, NULL, -1},
-	{"mapw1m", 0, NULL, -1},
-	{"mapw2m", 0, NULL, -1},
-	{"mapw3m", 0, NULL, -1},
-	{"mapw4m", 0, NULL, -1},
-	{"mapw5m", 0, NULL, -1},
-	{"mapw6m", 0, NULL, -1},
-	{"mapw7m", 0, NULL, -1},
-	{"mapw8m", 0, NULL, -1},
-	{"mapw9m", 0, NULL, -1},
-	{"mapwam", 0, NULL, -1},
-	{"mapwbm", 0, NULL, -1},
-	{"mapwcm", 0, NULL, -1},
-	{"mapwdm", 0, NULL, -1},
-	{"mapwem", 0, NULL, -1},
-	{"mapwfm", 0, NULL, -1},
-	{"mapwgm", 0, NULL, -1},
-	{"mapwhm", 0, NULL, -1},
-	{"mapwim", 0, NULL, -1},
-	{"mapwjm", 0, NULL, -1},
-	{"mapwkm", 0, NULL, -1},
-	{"mapwlm", 0, NULL, -1},
-	{"mapwmm", 0, NULL, -1},
-	{"mapwnm", 0, NULL, -1},
-	{"mapwom", 0, NULL, -1},
-	{"mapwpm", 0, NULL, -1},
-	{"mapwqm", 0, NULL, -1},
-	{"mapwrm", 0, NULL, -1},
-	{"mapwsm", 0, NULL, -1},
-	{"mapwtm", 0, NULL, -1},
-	{"mapwum", 0, NULL, -1},
-	{"mapwvm", 0, NULL, -1},
-	{"mapwwm", 0, NULL, -1},
-	{"mapwxm", 0, NULL, -1},
-	{"mapwym", 0, NULL, -1},
-	{"mapwzm", 0, NULL, -1},
-	{"mapx0m", 0, NULL, -1},
-	{"mapx1m", 0, NULL, -1},
-	{"mapx2m", 0, NULL, -1},
-	{"mapx3m", 0, NULL, -1},
-	{"mapx4m", 0, NULL, -1},
-	{"mapx5m", 0, NULL, -1},
-	{"mapx6m", 0, NULL, -1},
-	{"mapx7m", 0, NULL, -1},
-	{"mapx8m", 0, NULL, -1},
-	{"mapx9m", 0, NULL, -1},
-	{"mapxam", 0, NULL, -1},
-	{"mapxbm", 0, NULL, -1},
-	{"mapxcm", 0, NULL, -1},
-	{"mapxdm", 0, NULL, -1},
-	{"mapxem", 0, NULL, -1},
-	{"mapxfm", 0, NULL, -1},
-	{"mapxgm", 0, NULL, -1},
-	{"mapxhm", 0, NULL, -1},
-	{"mapxim", 0, NULL, -1},
-	{"mapxjm", 0, NULL, -1},
-	{"mapxkm", 0, NULL, -1},
-	{"mapxlm", 0, NULL, -1},
-	{"mapxmm", 0, NULL, -1},
-	{"mapxnm", 0, NULL, -1},
-	{"mapxom", 0, NULL, -1},
-	{"mapxpm", 0, NULL, -1},
-	{"mapxqm", 0, NULL, -1},
-	{"mapxrm", 0, NULL, -1},
-	{"mapxsm", 0, NULL, -1},
-	{"mapxtm", 0, NULL, -1},
-	{"mapxum", 0, NULL, -1},
-	{"mapxvm", 0, NULL, -1},
-	{"mapxwm", 0, NULL, -1},
-	{"mapxxm", 0, NULL, -1},
-	{"mapxym", 0, NULL, -1},
-	{"mapxzm", 0, NULL, -1},
-	{"mapy0m", 0, NULL, -1},
-	{"mapy1m", 0, NULL, -1},
-	{"mapy2m", 0, NULL, -1},
-	{"mapy3m", 0, NULL, -1},
-	{"mapy4m", 0, NULL, -1},
-	{"mapy5m", 0, NULL, -1},
-	{"mapy6m", 0, NULL, -1},
-	{"mapy7m", 0, NULL, -1},
-	{"mapy8m", 0, NULL, -1},
-	{"mapy9m", 0, NULL, -1},
-	{"mapyam", 0, NULL, -1},
-	{"mapybm", 0, NULL, -1},
-	{"mapycm", 0, NULL, -1},
-	{"mapydm", 0, NULL, -1},
-	{"mapyem", 0, NULL, -1},
-	{"mapyfm", 0, NULL, -1},
-	{"mapygm", 0, NULL, -1},
-	{"mapyhm", 0, NULL, -1},
-	{"mapyim", 0, NULL, -1},
-	{"mapyjm", 0, NULL, -1},
-	{"mapykm", 0, NULL, -1},
-	{"mapylm", 0, NULL, -1},
-	{"mapymm", 0, NULL, -1},
-	{"mapynm", 0, NULL, -1},
-	{"mapyom", 0, NULL, -1},
-	{"mapypm", 0, NULL, -1},
-	{"mapyqm", 0, NULL, -1},
-	{"mapyrm", 0, NULL, -1},
-	{"mapysm", 0, NULL, -1},
-	{"mapytm", 0, NULL, -1},
-	{"mapyum", 0, NULL, -1},
-	{"mapyvm", 0, NULL, -1},
-	{"mapywm", 0, NULL, -1},
-	{"mapyxm", 0, NULL, -1},
-	{"mapyym", 0, NULL, -1},
-	{"mapyzm", 0, NULL, -1},
-	{"mapz0m", 0, NULL, -1},
-	{"mapz1m", 0, NULL, -1},
-	{"mapz2m", 0, NULL, -1},
-	{"mapz3m", 0, NULL, -1},
-	{"mapz4m", 0, NULL, -1},
-	{"mapz5m", 0, NULL, -1},
-	{"mapz6m", 0, NULL, -1},
-	{"mapz7m", 0, NULL, -1},
-	{"mapz8m", 0, NULL, -1},
-	{"mapz9m", 0, NULL, -1},
-	{"mapzam", 0, NULL, -1},
-	{"mapzbm", 0, NULL, -1},
-	{"mapzcm", 0, NULL, -1},
-	{"mapzdm", 0, NULL, -1},
-	{"mapzem", 0, NULL, -1},
-	{"mapzfm", 0, NULL, -1},
-	{"mapzgm", 0, NULL, -1},
-	{"mapzhm", 0, NULL, -1},
-	{"mapzim", 0, NULL, -1},
-	{"mapzjm", 0, NULL, -1},
-	{"mapzkm", 0, NULL, -1},
-	{"mapzlm", 0, NULL, -1},
-	{"mapzmm", 0, NULL, -1},
-	{"mapznm", 0, NULL, -1},
-	{"mapzom", 0, NULL, -1},
-	{"mapzpm", 0, NULL, -1},
-	{"mapzqm", 0, NULL, -1},
-	{"mapzrm", 0, NULL, -1},
-	{"mapzsm", 0, NULL, -1},
-	{"mapztm", 0, NULL, -1},
-	{"mapzum", 0, NULL, -1},
-	{"mapzvm", 0, NULL, -1},
-	{"mapzwm", 0, NULL, -1},
-	{"mapzxm", 0, NULL, -1},
-	{"mapzym", 0, NULL, -1},
-	{"mapzzm", 0, NULL, -1},
-
-	{"titles", 0, NULL, -1}, // Title screen
-	{"read_m", 0, NULL, -1}, // Intro
-	{"lclear", 0, NULL, -1}, // Level clear
-	{"invinc", 0, NULL, -1}, // Invincibility
-	{"shoes", 0, NULL, -1}, // Super sneakers
-	{"minvnc", 0, NULL, -1}, // Mario invincibility
-	{"drown", 0, NULL, -1}, // Drowning
-	{"gmover", 0, NULL, -1}, // Game over
-	{"xtlife", 0, NULL, -1}, // Extra life
-	{"contsc", 0, NULL, -1}, // Continue screen
-	{"supers", 0, NULL, -1}, // Super Sonic
-	{"chrsel", 0, NULL, -1}, // Character select
-	{"credit", 0, NULL, -1}, // Credits
-	{"racent", 0, NULL, -1}, // Race Results
-	{"stjr",   0, NULL, -1}, // Sonic Team Jr. Presents
-};
-
-
 //
 // Information about all the sfx
 //
diff --git a/src/sounds.h b/src/sounds.h
index c5851a346b8944c8f14386a57a2fdfb92bd29fe2..4388d02cf4c75d16e4f3d7c8885096aeec5dfa75 100644
--- a/src/sounds.h
+++ b/src/sounds.h
@@ -86,1095 +86,9 @@ struct sfxinfo_struct
 	lumpnum_t lumpnum;
 };
 
-//
-// MusicInfo struct.
-//
-typedef struct
-{
-	// up to 6-character name
-	const char *name;
-
-	// lump number of music
-	lumpnum_t lumpnum;
-
-	// music data
-	void *data;
-
-	// music handle once registered
-	INT32 handle;
-} musicinfo_t;
-
 // the complete set of sound effects
 extern sfxinfo_t S_sfx[];
 
-// the complete set of music
-extern musicinfo_t S_music[];
-
-//
-// Identifiers for all music in game.
-//
-
-// Music list (don't edit this comment!)
-typedef enum
-{
-	mus_None,
-	mus_map01m,
-	mus_map02m,
-	mus_map03m,
-	mus_map04m,
-	mus_map05m,
-	mus_map06m,
-	mus_map07m,
-	mus_map08m,
-	mus_map09m,
-	mus_map10m,
-	mus_map11m,
-	mus_map12m,
-	mus_map13m,
-	mus_map14m,
-	mus_map15m,
-	mus_map16m,
-	mus_map17m,
-	mus_map18m,
-	mus_map19m,
-	mus_map20m,
-	mus_map21m,
-	mus_map22m,
-	mus_map23m,
-	mus_map24m,
-	mus_map25m,
-	mus_map26m,
-	mus_map27m,
-	mus_map28m,
-	mus_map29m,
-	mus_map30m,
-	mus_map31m,
-	mus_map32m,
-	mus_map33m,
-	mus_map34m,
-	mus_map35m,
-	mus_map36m,
-	mus_map37m,
-	mus_map38m,
-	mus_map39m,
-	mus_map40m,
-	mus_map41m,
-	mus_map42m,
-	mus_map43m,
-	mus_map44m,
-	mus_map45m,
-	mus_map46m,
-	mus_map47m,
-	mus_map48m,
-	mus_map49m,
-	mus_map50m,
-	mus_map51m,
-	mus_map52m,
-	mus_map53m,
-	mus_map54m,
-	mus_map55m,
-	mus_map56m,
-	mus_map57m,
-	mus_map58m,
-	mus_map59m,
-	mus_map60m,
-	mus_map61m,
-	mus_map62m,
-	mus_map63m,
-	mus_map64m,
-	mus_map65m,
-	mus_map66m,
-	mus_map67m,
-	mus_map68m,
-	mus_map69m,
-	mus_map70m,
-	mus_map71m,
-	mus_map72m,
-	mus_map73m,
-	mus_map74m,
-	mus_map75m,
-	mus_map76m,
-	mus_map77m,
-	mus_map78m,
-	mus_map79m,
-	mus_map80m,
-	mus_map81m,
-	mus_map82m,
-	mus_map83m,
-	mus_map84m,
-	mus_map85m,
-	mus_map86m,
-	mus_map87m,
-	mus_map88m,
-	mus_map89m,
-	mus_map90m,
-	mus_map91m,
-	mus_map92m,
-	mus_map93m,
-	mus_map94m,
-	mus_map95m,
-	mus_map96m,
-	mus_map97m,
-	mus_map98m,
-	mus_map99m,
-	mus_mapa0m,
-	mus_mapa1m,
-	mus_mapa2m,
-	mus_mapa3m,
-	mus_mapa4m,
-	mus_mapa5m,
-	mus_mapa6m,
-	mus_mapa7m,
-	mus_mapa8m,
-	mus_mapa9m,
-	mus_mapaam,
-	mus_mapabm,
-	mus_mapacm,
-	mus_mapadm,
-	mus_mapaem,
-	mus_mapafm,
-	mus_mapagm,
-	mus_mapahm,
-	mus_mapaim,
-	mus_mapajm,
-	mus_mapakm,
-	mus_mapalm,
-	mus_mapamm,
-	mus_mapanm,
-	mus_mapaom,
-	mus_mapapm,
-	mus_mapaqm,
-	mus_maparm,
-	mus_mapasm,
-	mus_mapatm,
-	mus_mapaum,
-	mus_mapavm,
-	mus_mapawm,
-	mus_mapaxm,
-	mus_mapaym,
-	mus_mapazm,
-	mus_mapb0m,
-	mus_mapb1m,
-	mus_mapb2m,
-	mus_mapb3m,
-	mus_mapb4m,
-	mus_mapb5m,
-	mus_mapb6m,
-	mus_mapb7m,
-	mus_mapb8m,
-	mus_mapb9m,
-	mus_mapbam,
-	mus_mapbbm,
-	mus_mapbcm,
-	mus_mapbdm,
-	mus_mapbem,
-	mus_mapbfm,
-	mus_mapbgm,
-	mus_mapbhm,
-	mus_mapbim,
-	mus_mapbjm,
-	mus_mapbkm,
-	mus_mapblm,
-	mus_mapbmm,
-	mus_mapbnm,
-	mus_mapbom,
-	mus_mapbpm,
-	mus_mapbqm,
-	mus_mapbrm,
-	mus_mapbsm,
-	mus_mapbtm,
-	mus_mapbum,
-	mus_mapbvm,
-	mus_mapbwm,
-	mus_mapbxm,
-	mus_mapbym,
-	mus_mapbzm,
-	mus_mapc0m,
-	mus_mapc1m,
-	mus_mapc2m,
-	mus_mapc3m,
-	mus_mapc4m,
-	mus_mapc5m,
-	mus_mapc6m,
-	mus_mapc7m,
-	mus_mapc8m,
-	mus_mapc9m,
-	mus_mapcam,
-	mus_mapcbm,
-	mus_mapccm,
-	mus_mapcdm,
-	mus_mapcem,
-	mus_mapcfm,
-	mus_mapcgm,
-	mus_mapchm,
-	mus_mapcim,
-	mus_mapcjm,
-	mus_mapckm,
-	mus_mapclm,
-	mus_mapcmm,
-	mus_mapcnm,
-	mus_mapcom,
-	mus_mapcpm,
-	mus_mapcqm,
-	mus_mapcrm,
-	mus_mapcsm,
-	mus_mapctm,
-	mus_mapcum,
-	mus_mapcvm,
-	mus_mapcwm,
-	mus_mapcxm,
-	mus_mapcym,
-	mus_mapczm,
-	mus_mapd0m,
-	mus_mapd1m,
-	mus_mapd2m,
-	mus_mapd3m,
-	mus_mapd4m,
-	mus_mapd5m,
-	mus_mapd6m,
-	mus_mapd7m,
-	mus_mapd8m,
-	mus_mapd9m,
-	mus_mapdam,
-	mus_mapdbm,
-	mus_mapdcm,
-	mus_mapddm,
-	mus_mapdem,
-	mus_mapdfm,
-	mus_mapdgm,
-	mus_mapdhm,
-	mus_mapdim,
-	mus_mapdjm,
-	mus_mapdkm,
-	mus_mapdlm,
-	mus_mapdmm,
-	mus_mapdnm,
-	mus_mapdom,
-	mus_mapdpm,
-	mus_mapdqm,
-	mus_mapdrm,
-	mus_mapdsm,
-	mus_mapdtm,
-	mus_mapdum,
-	mus_mapdvm,
-	mus_mapdwm,
-	mus_mapdxm,
-	mus_mapdym,
-	mus_mapdzm,
-	mus_mape0m,
-	mus_mape1m,
-	mus_mape2m,
-	mus_mape3m,
-	mus_mape4m,
-	mus_mape5m,
-	mus_mape6m,
-	mus_mape7m,
-	mus_mape8m,
-	mus_mape9m,
-	mus_mapeam,
-	mus_mapebm,
-	mus_mapecm,
-	mus_mapedm,
-	mus_mapeem,
-	mus_mapefm,
-	mus_mapegm,
-	mus_mapehm,
-	mus_mapeim,
-	mus_mapejm,
-	mus_mapekm,
-	mus_mapelm,
-	mus_mapemm,
-	mus_mapenm,
-	mus_mapeom,
-	mus_mapepm,
-	mus_mapeqm,
-	mus_maperm,
-	mus_mapesm,
-	mus_mapetm,
-	mus_mapeum,
-	mus_mapevm,
-	mus_mapewm,
-	mus_mapexm,
-	mus_mapeym,
-	mus_mapezm,
-	mus_mapf0m,
-	mus_mapf1m,
-	mus_mapf2m,
-	mus_mapf3m,
-	mus_mapf4m,
-	mus_mapf5m,
-	mus_mapf6m,
-	mus_mapf7m,
-	mus_mapf8m,
-	mus_mapf9m,
-	mus_mapfam,
-	mus_mapfbm,
-	mus_mapfcm,
-	mus_mapfdm,
-	mus_mapfem,
-	mus_mapffm,
-	mus_mapfgm,
-	mus_mapfhm,
-	mus_mapfim,
-	mus_mapfjm,
-	mus_mapfkm,
-	mus_mapflm,
-	mus_mapfmm,
-	mus_mapfnm,
-	mus_mapfom,
-	mus_mapfpm,
-	mus_mapfqm,
-	mus_mapfrm,
-	mus_mapfsm,
-	mus_mapftm,
-	mus_mapfum,
-	mus_mapfvm,
-	mus_mapfwm,
-	mus_mapfxm,
-	mus_mapfym,
-	mus_mapfzm,
-	mus_mapg0m,
-	mus_mapg1m,
-	mus_mapg2m,
-	mus_mapg3m,
-	mus_mapg4m,
-	mus_mapg5m,
-	mus_mapg6m,
-	mus_mapg7m,
-	mus_mapg8m,
-	mus_mapg9m,
-	mus_mapgam,
-	mus_mapgbm,
-	mus_mapgcm,
-	mus_mapgdm,
-	mus_mapgem,
-	mus_mapgfm,
-	mus_mapggm,
-	mus_mapghm,
-	mus_mapgim,
-	mus_mapgjm,
-	mus_mapgkm,
-	mus_mapglm,
-	mus_mapgmm,
-	mus_mapgnm,
-	mus_mapgom,
-	mus_mapgpm,
-	mus_mapgqm,
-	mus_mapgrm,
-	mus_mapgsm,
-	mus_mapgtm,
-	mus_mapgum,
-	mus_mapgvm,
-	mus_mapgwm,
-	mus_mapgxm,
-	mus_mapgym,
-	mus_mapgzm,
-	mus_maph0m,
-	mus_maph1m,
-	mus_maph2m,
-	mus_maph3m,
-	mus_maph4m,
-	mus_maph5m,
-	mus_maph6m,
-	mus_maph7m,
-	mus_maph8m,
-	mus_maph9m,
-	mus_mapham,
-	mus_maphbm,
-	mus_maphcm,
-	mus_maphdm,
-	mus_maphem,
-	mus_maphfm,
-	mus_maphgm,
-	mus_maphhm,
-	mus_maphim,
-	mus_maphjm,
-	mus_maphkm,
-	mus_maphlm,
-	mus_maphmm,
-	mus_maphnm,
-	mus_maphom,
-	mus_maphpm,
-	mus_maphqm,
-	mus_maphrm,
-	mus_maphsm,
-	mus_maphtm,
-	mus_maphum,
-	mus_maphvm,
-	mus_maphwm,
-	mus_maphxm,
-	mus_maphym,
-	mus_maphzm,
-	mus_mapi0m,
-	mus_mapi1m,
-	mus_mapi2m,
-	mus_mapi3m,
-	mus_mapi4m,
-	mus_mapi5m,
-	mus_mapi6m,
-	mus_mapi7m,
-	mus_mapi8m,
-	mus_mapi9m,
-	mus_mapiam,
-	mus_mapibm,
-	mus_mapicm,
-	mus_mapidm,
-	mus_mapiem,
-	mus_mapifm,
-	mus_mapigm,
-	mus_mapihm,
-	mus_mapiim,
-	mus_mapijm,
-	mus_mapikm,
-	mus_mapilm,
-	mus_mapimm,
-	mus_mapinm,
-	mus_mapiom,
-	mus_mapipm,
-	mus_mapiqm,
-	mus_mapirm,
-	mus_mapism,
-	mus_mapitm,
-	mus_mapium,
-	mus_mapivm,
-	mus_mapiwm,
-	mus_mapixm,
-	mus_mapiym,
-	mus_mapizm,
-	mus_mapj0m,
-	mus_mapj1m,
-	mus_mapj2m,
-	mus_mapj3m,
-	mus_mapj4m,
-	mus_mapj5m,
-	mus_mapj6m,
-	mus_mapj7m,
-	mus_mapj8m,
-	mus_mapj9m,
-	mus_mapjam,
-	mus_mapjbm,
-	mus_mapjcm,
-	mus_mapjdm,
-	mus_mapjem,
-	mus_mapjfm,
-	mus_mapjgm,
-	mus_mapjhm,
-	mus_mapjim,
-	mus_mapjjm,
-	mus_mapjkm,
-	mus_mapjlm,
-	mus_mapjmm,
-	mus_mapjnm,
-	mus_mapjom,
-	mus_mapjpm,
-	mus_mapjqm,
-	mus_mapjrm,
-	mus_mapjsm,
-	mus_mapjtm,
-	mus_mapjum,
-	mus_mapjvm,
-	mus_mapjwm,
-	mus_mapjxm,
-	mus_mapjym,
-	mus_mapjzm,
-	mus_mapk0m,
-	mus_mapk1m,
-	mus_mapk2m,
-	mus_mapk3m,
-	mus_mapk4m,
-	mus_mapk5m,
-	mus_mapk6m,
-	mus_mapk7m,
-	mus_mapk8m,
-	mus_mapk9m,
-	mus_mapkam,
-	mus_mapkbm,
-	mus_mapkcm,
-	mus_mapkdm,
-	mus_mapkem,
-	mus_mapkfm,
-	mus_mapkgm,
-	mus_mapkhm,
-	mus_mapkim,
-	mus_mapkjm,
-	mus_mapkkm,
-	mus_mapklm,
-	mus_mapkmm,
-	mus_mapknm,
-	mus_mapkom,
-	mus_mapkpm,
-	mus_mapkqm,
-	mus_mapkrm,
-	mus_mapksm,
-	mus_mapktm,
-	mus_mapkum,
-	mus_mapkvm,
-	mus_mapkwm,
-	mus_mapkxm,
-	mus_mapkym,
-	mus_mapkzm,
-	mus_mapl0m,
-	mus_mapl1m,
-	mus_mapl2m,
-	mus_mapl3m,
-	mus_mapl4m,
-	mus_mapl5m,
-	mus_mapl6m,
-	mus_mapl7m,
-	mus_mapl8m,
-	mus_mapl9m,
-	mus_maplam,
-	mus_maplbm,
-	mus_maplcm,
-	mus_mapldm,
-	mus_maplem,
-	mus_maplfm,
-	mus_maplgm,
-	mus_maplhm,
-	mus_maplim,
-	mus_mapljm,
-	mus_maplkm,
-	mus_mapllm,
-	mus_maplmm,
-	mus_maplnm,
-	mus_maplom,
-	mus_maplpm,
-	mus_maplqm,
-	mus_maplrm,
-	mus_maplsm,
-	mus_mapltm,
-	mus_maplum,
-	mus_maplvm,
-	mus_maplwm,
-	mus_maplxm,
-	mus_maplym,
-	mus_maplzm,
-	mus_mapm0m,
-	mus_mapm1m,
-	mus_mapm2m,
-	mus_mapm3m,
-	mus_mapm4m,
-	mus_mapm5m,
-	mus_mapm6m,
-	mus_mapm7m,
-	mus_mapm8m,
-	mus_mapm9m,
-	mus_mapmam,
-	mus_mapmbm,
-	mus_mapmcm,
-	mus_mapmdm,
-	mus_mapmem,
-	mus_mapmfm,
-	mus_mapmgm,
-	mus_mapmhm,
-	mus_mapmim,
-	mus_mapmjm,
-	mus_mapmkm,
-	mus_mapmlm,
-	mus_mapmmm,
-	mus_mapmnm,
-	mus_mapmom,
-	mus_mapmpm,
-	mus_mapmqm,
-	mus_mapmrm,
-	mus_mapmsm,
-	mus_mapmtm,
-	mus_mapmum,
-	mus_mapmvm,
-	mus_mapmwm,
-	mus_mapmxm,
-	mus_mapmym,
-	mus_mapmzm,
-	mus_mapn0m,
-	mus_mapn1m,
-	mus_mapn2m,
-	mus_mapn3m,
-	mus_mapn4m,
-	mus_mapn5m,
-	mus_mapn6m,
-	mus_mapn7m,
-	mus_mapn8m,
-	mus_mapn9m,
-	mus_mapnam,
-	mus_mapnbm,
-	mus_mapncm,
-	mus_mapndm,
-	mus_mapnem,
-	mus_mapnfm,
-	mus_mapngm,
-	mus_mapnhm,
-	mus_mapnim,
-	mus_mapnjm,
-	mus_mapnkm,
-	mus_mapnlm,
-	mus_mapnmm,
-	mus_mapnnm,
-	mus_mapnom,
-	mus_mapnpm,
-	mus_mapnqm,
-	mus_mapnrm,
-	mus_mapnsm,
-	mus_mapntm,
-	mus_mapnum,
-	mus_mapnvm,
-	mus_mapnwm,
-	mus_mapnxm,
-	mus_mapnym,
-	mus_mapnzm,
-	mus_mapo0m,
-	mus_mapo1m,
-	mus_mapo2m,
-	mus_mapo3m,
-	mus_mapo4m,
-	mus_mapo5m,
-	mus_mapo6m,
-	mus_mapo7m,
-	mus_mapo8m,
-	mus_mapo9m,
-	mus_mapoam,
-	mus_mapobm,
-	mus_mapocm,
-	mus_mapodm,
-	mus_mapoem,
-	mus_mapofm,
-	mus_mapogm,
-	mus_mapohm,
-	mus_mapoim,
-	mus_mapojm,
-	mus_mapokm,
-	mus_mapolm,
-	mus_mapomm,
-	mus_maponm,
-	mus_mapoom,
-	mus_mapopm,
-	mus_mapoqm,
-	mus_maporm,
-	mus_maposm,
-	mus_mapotm,
-	mus_mapoum,
-	mus_mapovm,
-	mus_mapowm,
-	mus_mapoxm,
-	mus_mapoym,
-	mus_mapozm,
-	mus_mapp0m,
-	mus_mapp1m,
-	mus_mapp2m,
-	mus_mapp3m,
-	mus_mapp4m,
-	mus_mapp5m,
-	mus_mapp6m,
-	mus_mapp7m,
-	mus_mapp8m,
-	mus_mapp9m,
-	mus_mappam,
-	mus_mappbm,
-	mus_mappcm,
-	mus_mappdm,
-	mus_mappem,
-	mus_mappfm,
-	mus_mappgm,
-	mus_mapphm,
-	mus_mappim,
-	mus_mappjm,
-	mus_mappkm,
-	mus_mapplm,
-	mus_mappmm,
-	mus_mappnm,
-	mus_mappom,
-	mus_mapppm,
-	mus_mappqm,
-	mus_mapprm,
-	mus_mappsm,
-	mus_mapptm,
-	mus_mappum,
-	mus_mappvm,
-	mus_mappwm,
-	mus_mappxm,
-	mus_mappym,
-	mus_mappzm,
-	mus_mapq0m,
-	mus_mapq1m,
-	mus_mapq2m,
-	mus_mapq3m,
-	mus_mapq4m,
-	mus_mapq5m,
-	mus_mapq6m,
-	mus_mapq7m,
-	mus_mapq8m,
-	mus_mapq9m,
-	mus_mapqam,
-	mus_mapqbm,
-	mus_mapqcm,
-	mus_mapqdm,
-	mus_mapqem,
-	mus_mapqfm,
-	mus_mapqgm,
-	mus_mapqhm,
-	mus_mapqim,
-	mus_mapqjm,
-	mus_mapqkm,
-	mus_mapqlm,
-	mus_mapqmm,
-	mus_mapqnm,
-	mus_mapqom,
-	mus_mapqpm,
-	mus_mapqqm,
-	mus_mapqrm,
-	mus_mapqsm,
-	mus_mapqtm,
-	mus_mapqum,
-	mus_mapqvm,
-	mus_mapqwm,
-	mus_mapqxm,
-	mus_mapqym,
-	mus_mapqzm,
-	mus_mapr0m,
-	mus_mapr1m,
-	mus_mapr2m,
-	mus_mapr3m,
-	mus_mapr4m,
-	mus_mapr5m,
-	mus_mapr6m,
-	mus_mapr7m,
-	mus_mapr8m,
-	mus_mapr9m,
-	mus_mapram,
-	mus_maprbm,
-	mus_maprcm,
-	mus_maprdm,
-	mus_maprem,
-	mus_maprfm,
-	mus_maprgm,
-	mus_maprhm,
-	mus_maprim,
-	mus_maprjm,
-	mus_maprkm,
-	mus_maprlm,
-	mus_maprmm,
-	mus_maprnm,
-	mus_maprom,
-	mus_maprpm,
-	mus_maprqm,
-	mus_maprrm,
-	mus_maprsm,
-	mus_maprtm,
-	mus_maprum,
-	mus_maprvm,
-	mus_maprwm,
-	mus_maprxm,
-	mus_maprym,
-	mus_maprzm,
-	mus_maps0m,
-	mus_maps1m,
-	mus_maps2m,
-	mus_maps3m,
-	mus_maps4m,
-	mus_maps5m,
-	mus_maps6m,
-	mus_maps7m,
-	mus_maps8m,
-	mus_maps9m,
-	mus_mapsam,
-	mus_mapsbm,
-	mus_mapscm,
-	mus_mapsdm,
-	mus_mapsem,
-	mus_mapsfm,
-	mus_mapsgm,
-	mus_mapshm,
-	mus_mapsim,
-	mus_mapsjm,
-	mus_mapskm,
-	mus_mapslm,
-	mus_mapsmm,
-	mus_mapsnm,
-	mus_mapsom,
-	mus_mapspm,
-	mus_mapsqm,
-	mus_mapsrm,
-	mus_mapssm,
-	mus_mapstm,
-	mus_mapsum,
-	mus_mapsvm,
-	mus_mapswm,
-	mus_mapsxm,
-	mus_mapsym,
-	mus_mapszm,
-	mus_mapt0m,
-	mus_mapt1m,
-	mus_mapt2m,
-	mus_mapt3m,
-	mus_mapt4m,
-	mus_mapt5m,
-	mus_mapt6m,
-	mus_mapt7m,
-	mus_mapt8m,
-	mus_mapt9m,
-	mus_maptam,
-	mus_maptbm,
-	mus_maptcm,
-	mus_maptdm,
-	mus_maptem,
-	mus_maptfm,
-	mus_maptgm,
-	mus_mapthm,
-	mus_maptim,
-	mus_maptjm,
-	mus_maptkm,
-	mus_maptlm,
-	mus_maptmm,
-	mus_maptnm,
-	mus_maptom,
-	mus_maptpm,
-	mus_maptqm,
-	mus_maptrm,
-	mus_maptsm,
-	mus_mapttm,
-	mus_maptum,
-	mus_maptvm,
-	mus_maptwm,
-	mus_maptxm,
-	mus_maptym,
-	mus_maptzm,
-	mus_mapu0m,
-	mus_mapu1m,
-	mus_mapu2m,
-	mus_mapu3m,
-	mus_mapu4m,
-	mus_mapu5m,
-	mus_mapu6m,
-	mus_mapu7m,
-	mus_mapu8m,
-	mus_mapu9m,
-	mus_mapuam,
-	mus_mapubm,
-	mus_mapucm,
-	mus_mapudm,
-	mus_mapuem,
-	mus_mapufm,
-	mus_mapugm,
-	mus_mapuhm,
-	mus_mapuim,
-	mus_mapujm,
-	mus_mapukm,
-	mus_mapulm,
-	mus_mapumm,
-	mus_mapunm,
-	mus_mapuom,
-	mus_mapupm,
-	mus_mapuqm,
-	mus_mapurm,
-	mus_mapusm,
-	mus_maputm,
-	mus_mapuum,
-	mus_mapuvm,
-	mus_mapuwm,
-	mus_mapuxm,
-	mus_mapuym,
-	mus_mapuzm,
-	mus_mapv0m,
-	mus_mapv1m,
-	mus_mapv2m,
-	mus_mapv3m,
-	mus_mapv4m,
-	mus_mapv5m,
-	mus_mapv6m,
-	mus_mapv7m,
-	mus_mapv8m,
-	mus_mapv9m,
-	mus_mapvam,
-	mus_mapvbm,
-	mus_mapvcm,
-	mus_mapvdm,
-	mus_mapvem,
-	mus_mapvfm,
-	mus_mapvgm,
-	mus_mapvhm,
-	mus_mapvim,
-	mus_mapvjm,
-	mus_mapvkm,
-	mus_mapvlm,
-	mus_mapvmm,
-	mus_mapvnm,
-	mus_mapvom,
-	mus_mapvpm,
-	mus_mapvqm,
-	mus_mapvrm,
-	mus_mapvsm,
-	mus_mapvtm,
-	mus_mapvum,
-	mus_mapvvm,
-	mus_mapvwm,
-	mus_mapvxm,
-	mus_mapvym,
-	mus_mapvzm,
-	mus_mapw0m,
-	mus_mapw1m,
-	mus_mapw2m,
-	mus_mapw3m,
-	mus_mapw4m,
-	mus_mapw5m,
-	mus_mapw6m,
-	mus_mapw7m,
-	mus_mapw8m,
-	mus_mapw9m,
-	mus_mapwam,
-	mus_mapwbm,
-	mus_mapwcm,
-	mus_mapwdm,
-	mus_mapwem,
-	mus_mapwfm,
-	mus_mapwgm,
-	mus_mapwhm,
-	mus_mapwim,
-	mus_mapwjm,
-	mus_mapwkm,
-	mus_mapwlm,
-	mus_mapwmm,
-	mus_mapwnm,
-	mus_mapwom,
-	mus_mapwpm,
-	mus_mapwqm,
-	mus_mapwrm,
-	mus_mapwsm,
-	mus_mapwtm,
-	mus_mapwum,
-	mus_mapwvm,
-	mus_mapwwm,
-	mus_mapwxm,
-	mus_mapwym,
-	mus_mapwzm,
-	mus_mapx0m,
-	mus_mapx1m,
-	mus_mapx2m,
-	mus_mapx3m,
-	mus_mapx4m,
-	mus_mapx5m,
-	mus_mapx6m,
-	mus_mapx7m,
-	mus_mapx8m,
-	mus_mapx9m,
-	mus_mapxam,
-	mus_mapxbm,
-	mus_mapxcm,
-	mus_mapxdm,
-	mus_mapxem,
-	mus_mapxfm,
-	mus_mapxgm,
-	mus_mapxhm,
-	mus_mapxim,
-	mus_mapxjm,
-	mus_mapxkm,
-	mus_mapxlm,
-	mus_mapxmm,
-	mus_mapxnm,
-	mus_mapxom,
-	mus_mapxpm,
-	mus_mapxqm,
-	mus_mapxrm,
-	mus_mapxsm,
-	mus_mapxtm,
-	mus_mapxum,
-	mus_mapxvm,
-	mus_mapxwm,
-	mus_mapxxm,
-	mus_mapxym,
-	mus_mapxzm,
-	mus_mapy0m,
-	mus_mapy1m,
-	mus_mapy2m,
-	mus_mapy3m,
-	mus_mapy4m,
-	mus_mapy5m,
-	mus_mapy6m,
-	mus_mapy7m,
-	mus_mapy8m,
-	mus_mapy9m,
-	mus_mapyam,
-	mus_mapybm,
-	mus_mapycm,
-	mus_mapydm,
-	mus_mapyem,
-	mus_mapyfm,
-	mus_mapygm,
-	mus_mapyhm,
-	mus_mapyim,
-	mus_mapyjm,
-	mus_mapykm,
-	mus_mapylm,
-	mus_mapymm,
-	mus_mapynm,
-	mus_mapyom,
-	mus_mapypm,
-	mus_mapyqm,
-	mus_mapyrm,
-	mus_mapysm,
-	mus_mapytm,
-	mus_mapyum,
-	mus_mapyvm,
-	mus_mapywm,
-	mus_mapyxm,
-	mus_mapyym,
-	mus_mapyzm,
-	mus_mapz0m,
-	mus_mapz1m,
-	mus_mapz2m,
-	mus_mapz3m,
-	mus_mapz4m,
-	mus_mapz5m,
-	mus_mapz6m,
-	mus_mapz7m,
-	mus_mapz8m,
-	mus_mapz9m,
-	mus_mapzam,
-	mus_mapzbm,
-	mus_mapzcm,
-	mus_mapzdm,
-	mus_mapzem,
-	mus_mapzfm,
-	mus_mapzgm,
-	mus_mapzhm,
-	mus_mapzim,
-	mus_mapzjm,
-	mus_mapzkm,
-	mus_mapzlm,
-	mus_mapzmm,
-	mus_mapznm,
-	mus_mapzom,
-	mus_mapzpm,
-	mus_mapzqm,
-	mus_mapzrm,
-	mus_mapzsm,
-	mus_mapztm,
-	mus_mapzum,
-	mus_mapzvm,
-	mus_mapzwm,
-	mus_mapzxm,
-	mus_mapzym,
-	mus_mapzzm,
-
-	mus_titles, // title screen
-	mus_read_m, // intro
-	mus_lclear, // level clear
-	mus_invinc, // invincibility
-	mus_shoes,  // super sneakers
-	mus_minvnc, // Mario invincibility
-	mus_drown,  // drowning
-	mus_gmover, // game over
-	mus_xtlife, // extra life
-	mus_contsc, // continue screen
-	mus_supers, // Super Sonic
-	mus_chrsel, // character select
-	mus_credit, // credits
-	mus_racent, // Race Results
-	mus_stjr,   // Sonic Team Jr. Presents
-
-	NUMMUSIC
-} musicenum_t;
-// Note: song number should be a UINT16, as mapmusic only uses 16 bits for music slot number.
-//       (the rest is track number and an internal reload flag)
-
 //
 // Identifiers for all sfx in game.
 //
diff --git a/src/w_wad.c b/src/w_wad.c
index 9d6a11fb5c9f863def81c261a5893aa4aded98a8..132df8fcb838d97e0ad56e29ee19c269c5932459 100644
--- a/src/w_wad.c
+++ b/src/w_wad.c
@@ -32,6 +32,7 @@
 
 #include "w_wad.h"
 #include "z_zone.h"
+#include "fastcmp.h"
 
 #include "i_video.h" // rendermode
 #include "d_netfil.h"
@@ -147,24 +148,32 @@ static inline void W_LoadDehackedLumps(UINT16 wadnum)
 	}
 #endif
 
-	// Check for MAINCFG
-	for (lump = 0;lump != INT16_MAX;lump++)
-	{
-		lump = W_CheckNumForNamePwad("MAINCFG", wadnum, lump);
-		if (lump == INT16_MAX)
-			break;
-		CONS_Printf(M_GetText("Loading main config from %s\n"), wadfiles[wadnum]->filename);
-		DEH_LoadDehackedLumpPwad(wadnum, lump);
-	}
-
-	// Check for OBJCTCFG
-	for (lump = 0;lump < INT16_MAX;lump++)
 	{
-		lump = W_CheckNumForNamePwad("OBJCTCFG", wadnum, lump);
-		if (lump == INT16_MAX)
-			break;
-		CONS_Printf(M_GetText("Loading object config from %s\n"), wadfiles[wadnum]->filename);
-		DEH_LoadDehackedLumpPwad(wadnum, lump);
+		lumpinfo_t *lump_p = wadfiles[wadnum]->lumpinfo;
+		for (lump = 0; lump < wadfiles[wadnum]->numlumps; lump++, lump_p++)
+			if (memcmp(lump_p->name,"SOC_",4)==0) // Check for generic SOC lump
+			{	// shameless copy+paste of code from LUA_LoadLump
+				char *name = malloc(strlen(wadfiles[wadnum]->filename)+10);
+				strcpy(name, wadfiles[wadnum]->filename);
+				if (!fasticmp(&name[strlen(name) - 4], ".soc")) {
+					// If it's not a .soc file, copy the lump name in too.
+					name[strlen(wadfiles[wadnum]->filename)] = '|';
+					M_Memcpy(name+strlen(wadfiles[wadnum]->filename)+1, lump_p->name, 8);
+					name[strlen(wadfiles[wadnum]->filename)+9] = '\0';
+				}
+				CONS_Printf(M_GetText("Loading SOC from %s\n"), name);
+				DEH_LoadDehackedLumpPwad(wadnum, lump);
+			}
+			else if (memcmp(lump_p->name,"MAINCFG",8)==0) // Check for MAINCFG
+			{
+				CONS_Printf(M_GetText("Loading main config from %s\n"), wadfiles[wadnum]->filename);
+				DEH_LoadDehackedLumpPwad(wadnum, lump);
+			}
+			else if (memcmp(lump_p->name,"OBJCTCFG",8)==0) // Check for OBJCTCFG
+			{
+				CONS_Printf(M_GetText("Loading object config from %s\n"), wadfiles[wadnum]->filename);
+				DEH_LoadDehackedLumpPwad(wadnum, lump);
+			}
 	}
 
 #ifdef SCANTHINGS
diff --git a/src/y_inter.c b/src/y_inter.c
index 2f2edf7ca71eef368671f501c88db3e745f52959..104c1004daa0243243601392ff0296de1bb7a3bb 100644
--- a/src/y_inter.c
+++ b/src/y_inter.c
@@ -632,7 +632,7 @@ void Y_Ticker(void)
 		boolean anybonuses = false;
 
 		if (!intertic) // first time only
-			S_ChangeMusic(mus_lclear, false); // don't loop it
+			S_ChangeMusicInternal("lclear", false); // don't loop it
 
 		if (intertic < TICRATE) // one second pause before tally begins
 			return;
@@ -693,7 +693,7 @@ void Y_Ticker(void)
 
 		if (!intertic) // first time only
 		{
-			S_ChangeMusic(mus_lclear, false); // don't loop it
+			S_ChangeMusicInternal("lclear", false); // don't loop it
 			tallydonetic = 0;
 		}
 
@@ -754,7 +754,7 @@ void Y_Ticker(void)
 	else if (intertype == int_match || intertype == int_ctf || intertype == int_teammatch) // match
 	{
 		if (!intertic) // first time only
-			S_ChangeMusic(mus_racent, true); // loop it
+			S_ChangeMusicInternal("racent", true); // loop it
 
 		// If a player has left or joined, recalculate scores.
 		if (data.match.numplayers != D_NumPlayers())
@@ -763,7 +763,7 @@ void Y_Ticker(void)
 	else if (intertype == int_race || intertype == int_classicrace) // race
 	{
 		if (!intertic) // first time only
-			S_ChangeMusic(mus_racent, true); // loop it
+			S_ChangeMusicInternal("racent", true); // loop it
 
 		// Don't bother recalcing for race. It doesn't make as much sense.
 	}