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