diff --git a/src/dehacked.c b/src/dehacked.c index 5149fddd5..b92850cce 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -632,6 +632,8 @@ static void readfreeslots(MYFILE *f) // TODO: Name too long (truncated) warnings. if (fastcmp(type, "SFX")) S_AddSoundFx(word, false, 0, false); + else if (fastcmp(type, "MUS")) + S_AddMusic(word, -1); else if (fastcmp(type, "SPR")) { for (i = SPR_FIRSTFREESLOT; i <= SPR_LASTFREESLOT; i++) @@ -2005,6 +2007,63 @@ static void readsound(MYFILE *f, INT32 num, const char *savesfxnames[]) (void)savesfxnames; } +//yellowtd: readmusic: may be a clone but does its desired purpose c: +static void readmusic(MYFILE *f, UINT16 num, const char *savemusicnames[]) +{ + char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL); + char *word; + char *tmp; + INT32 value; + + do + { + if (myfgets(s, MAXLINELEN, f)) + { + if (s[0] == '\n') + break; + + tmp = strchr(s, '#'); + if (tmp) + *tmp = '\0'; + + value = searchvalue(s); + + word = strtok(s, " "); + if (word) + strupr(word); + else + break; + +/* if (fastcmp(word, "OFFSET")) + { + value -= 150360; + if (value <= 64) + value /= 8; + else if (value <= 260) + value = (value+4)/8; + else + value = (value+8)/8; + if (value >= -1 && value < sfx_freeslot0 - 1) + S_sfx[num].name = savesfxnames[value+1]; + else + deh_warning("Sound %d: offset out of bounds", num); + } + else */if (fastcmp(word, "DUMMYVAL")) + { + + DEH_WriteUndoline(word, va("%d", S_music[num].dummyval), UNDO_NONE); + S_music[num].dummyval = value; + } + else + deh_warning("Music %d : unknown word '%s'",num,word); + } + } while (!myfeof(f)); + + Z_Free(s); + + (void)savemusicnames; +} + /** Checks if a game data file name for a mod is good. * "Good" means that it contains only alphanumerics, _, and -; * ends in ".dat"; has at least one character before the ".dat"; @@ -3223,7 +3282,8 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad) //XBOXSTATIC actionf_t saveactions[NUMSTATES]; //XBOXSTATIC const char *savesprnames[NUMSPRITES]; XBOXSTATIC const char *savesfxnames[NUMSFX]; - + XBOXSTATIC const char *savemusicnames[NUMMUSIC]; + if (!deh_loaded) initfreeslots(); @@ -3237,7 +3297,10 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad) */ for (i = 0; i < NUMSFX; i++) savesfxnames[i] = S_sfx[i].name; - + + for (i = 0; i < NUMMUSIC; i++) + savemusicnames[i] = S_music[i].name; + gamedataadded = false; // it doesn't test the version of SRB2 and version of dehacked file @@ -3448,6 +3511,19 @@ static void DEH_LoadDehackedFile(MYFILE *f, UINT16 wad) } DEH_WriteUndoline(word, word2, UNDO_HEADER); } + else if (fastcmp(word, "MUSIC")) + { + if (i == 0 && word2[0] != '0') // If word2 isn't a number + i = get_mus(word2); // find a sound by name + if (i < NUMMUSIC && i >= 0) + readmusic(f, i, savemusicnames); + else + { + deh_warning("Music %d out of range (0 - %d)", i, NUMMUSIC-1); + ignorelines(f); + } + DEH_WriteUndoline(word, word2, UNDO_HEADER); + } /* else if (fastcmp(word, "SPRITE")) { if (i < NUMSPRITES && i >= 0) @@ -8251,6 +8327,17 @@ static inline int lib_freeslot(lua_State *L) } else return r; } + else if (fastcmp(type, "MUS")) { + musicenum_t music; + strlwr(word); + CONS_Printf("Music mus_%s allocated.\n",word); + music = S_AddMusic(word, -1); + if (music != mus_None) { + lua_pushinteger(L, music); + r++; + } else + return r; + } else if (fastcmp(type, "SPR")) { char wad; diff --git a/src/lua_infolib.c b/src/lua_infolib.c index 2c968218c..d1bbf96e9 100644 --- a/src/lua_infolib.c +++ b/src/lua_infolib.c @@ -52,6 +52,39 @@ const char *const sfxinfo_wopt[] = { "flags", NULL}; + +//==================== +enum musicinfo_read { + musicinfor_name, + musicinfor_lumpnum, + musicinfor_data, + musicinfor_handle, + musicinfor_dummyval +}; +const char *const musicinfo_ropt[] = { + "name", + "lumpnum", + "data", + "handle", + "dummyval", + NULL}; + +enum musicinfo_write { + musicinfow_name, + musicinfow_lumpnum, + musicinfow_data, + musicinfow_handle, + musicinfow_dummyval +}; +const char *const musicinfo_wopt[] = { + "name", + "lumpnum", + "data", + "handle", + "dummyval", + NULL}; +//==================== + // // Sprite Names // @@ -846,6 +879,116 @@ static int sfxinfo_num(lua_State *L) return 1; } +////////////// +// MUS INFO // +////////////// +static int lib_getMusicInfo(lua_State *L) +{ + UINT32 i; + lua_remove(L, 1); + + i = luaL_checkinteger(L, 1); + LUA_PushUserdata(L, &S_music[i], META_MUSICINFO); + return 1; +} +static int lib_setMusicInfo(lua_State *L) +{ + musicinfo_t *info; + + lua_remove(L, 1); + info = &S_music[luaL_checkinteger(L, 1)]; // get the mobjinfo to assign to. + luaL_checktype(L, 2, LUA_TTABLE); // check that we've been passed a table. + lua_remove(L, 1); // pop mobjtype num, don't need it any more. + lua_settop(L, 1); // cut the stack here. the only thing left now is the table of data we're assigning to the mobjinfo. + + + + if (hud_running) + return luaL_error(L, "Do not alter musicinfo in HUD rendering code!"); + + lua_pushnil(L); + while (lua_next(L, 1)) { + enum musicinfo_write i; + + if (lua_isnumber(L, 2)) + i = lua_tointeger(L, 2) - 1; // lua is one based, this enum is zero based. + else + i = luaL_checkoption(L, 2, NULL, musicinfo_wopt); + + switch(i) + { + case musicinfow_dummyval: + info->dummyval = (INT32)luaL_checkinteger(L, 3); + break; + default: + break; + } + lua_pop(L, 1); + } + + return 0; +} + +static int lib_musiclen(lua_State *L) +{ + lua_pushinteger(L, NUMMUSIC); + return 1; +} + +// musicinfo_t *, field +static int musicinfo_get(lua_State *L) +{ + musicinfo_t *music = *((musicinfo_t **)luaL_checkudata(L, 1, META_MUSICINFO)); + enum musicinfo_read field = luaL_checkoption(L, 2, NULL, musicinfo_ropt); + + I_Assert(music != NULL); + + switch (field) + { + case musicinfor_dummyval: + lua_pushinteger(L, music->dummyval); + return 1; + default: + return luaL_error(L, "impossible error"); + } + return 0; +} +static int musicinfo_set(lua_State *L) +{ + musicinfo_t *music = *((musicinfo_t **)luaL_checkudata(L, 1, META_MUSICINFO)); + enum musicinfo_write field = luaL_checkoption(L, 2, NULL, musicinfo_wopt); + + if (hud_running) + return luaL_error(L, "Do not alter S_music in HUD rendering code!"); + + I_Assert(music != NULL); + + lua_remove(L, 1); // remove sfxinfo + lua_remove(L, 1); // remove field + lua_settop(L, 1); // leave only one value + + switch (field) + { + case musicinfow_dummyval: + music->dummyval = luaL_checkinteger(L, 1); + break; + default: + return luaL_error(L, "impossible error"); + } + return 0; +} + +static int musicinfo_num(lua_State *L) +{ + musicinfo_t *music = *((musicinfo_t **)luaL_checkudata(L, 1, META_MUSICINFO)); + + I_Assert(music != NULL); + I_Assert(music >= S_music); + + lua_pushinteger(L, (UINT32)(music-S_music)); + return 1; +} + ////////////////////////////// // // Now push all these functions into the Lua state! @@ -893,7 +1036,18 @@ int LUA_InfoLib(lua_State *L) lua_pushcfunction(L, sfxinfo_num); lua_setfield(L, -2, "__len"); lua_pop(L, 1); + + luaL_newmetatable(L, META_MUSICINFO); + lua_pushcfunction(L, musicinfo_get); + lua_setfield(L, -2, "__index"); + lua_pushcfunction(L, musicinfo_set); + lua_setfield(L, -2, "__newindex"); + + lua_pushcfunction(L, musicinfo_num); + lua_setfield(L, -2, "__len"); + lua_pop(L, 1); + lua_newuserdata(L, 0); lua_createtable(L, 0, 2); lua_pushcfunction(L, lib_getSprname); @@ -944,6 +1098,21 @@ int LUA_InfoLib(lua_State *L) lua_pushvalue(L, -1); lua_setglobal(L, "S_sfx"); lua_setglobal(L, "sfxinfo"); + + lua_newuserdata(L, 0); + lua_createtable(L, 0, 2); + lua_pushcfunction(L, lib_getMusicInfo); + lua_setfield(L, -2, "__index"); + + lua_pushcfunction(L, lib_setMusicInfo); + lua_setfield(L, -2, "__newindex"); + + lua_pushcfunction(L, lib_musiclen); + lua_setfield(L, -2, "__len"); + lua_setmetatable(L, -2); + lua_pushvalue(L, -1); + lua_setglobal(L, "S_music"); + lua_setglobal(L, "musicinfo"); return 0; } diff --git a/src/lua_libs.h b/src/lua_libs.h index d19ad8857..290b8b5fe 100644 --- a/src/lua_libs.h +++ b/src/lua_libs.h @@ -22,6 +22,7 @@ extern lua_State *gL; #define META_STATE "STATE_T*" #define META_MOBJINFO "MOBJINFO_T*" #define META_SFXINFO "SFXINFO_T*" +#define META_MUSICINFO "MUSICINFO_T*" #define META_MOBJ "MOBJ_T*" #define META_MAPTHING "MAPTHING_T*" diff --git a/src/sounds.c b/src/sounds.c index c03d6cea2..5d543fade 100644 --- a/src/sounds.c +++ b/src/sounds.c @@ -1532,14 +1532,17 @@ sfxinfo_t S_sfx[NUMSFX] = }; char freeslotnames[sfx_freeslot0 + NUMSFXFREESLOTS + NUMSKINSFXSLOTS][7]; +char musicfreeslotnames[mus_frees0 + NUMMUSFREESLOTS][7]; -// Prepare free sfx slots to add sfx at run time +// Prepare free sfx slots to add sfx at run time (yellowtd: Include musics too~!) void S_InitRuntimeSounds (void) { sfxenum_t i; + musicenum_t x; INT32 value; char soundname[7]; - + char musicname[7]; + for (i = sfx_freeslot0; i <= sfx_lastskinsoundslot; i++) { value = (i+1) - sfx_freeslot0; @@ -1566,6 +1569,28 @@ void S_InitRuntimeSounds (void) S_sfx[i].usefulness = -1; S_sfx[i].lumpnum = LUMPERROR; } + + for (x = mus_frees0; x <= mus_lstfre; x++) + { + value = (x+1) - mus_frees0; + + if (value < 10) + sprintf(musicname, "fre00%d", value); + else if (value < 100) + sprintf(musicname, "fre0%d", value); + else if (value < 1000) + sprintf(musicname, "fre%d", value); + else + sprintf(musicname, "fr%d", value); + + strcpy(musicfreeslotnames[value-1], musicname); + + S_music[x].name = musicfreeslotnames[value-1]; + S_music[x].data = NULL; + S_music[x].lumpnum = 0; + S_music[x].handle = -1; + S_music[x].dummyval = 0; + } } // Add a new sound fx into a free sfx slot. @@ -1601,6 +1626,31 @@ sfxenum_t S_AddSoundFx(const char *name, boolean singular, INT32 flags, boolean return 0; } +musicenum_t S_AddMusic(const char *name, INT32 dummyval) +{ + musicenum_t i, slot; + + slot = mus_frees0; + + for (i = slot; i < NUMMUSIC; i++) + { + //Dummy value because no .priority exists + if (!S_music[i].dummyval) + { + strncpy(musicfreeslotnames[i-mus_frees0], name, 6); + S_music[i].dummyval = dummyval; + S_music[i].handle = -1; + S_music[i].lumpnum = 0; + + /// \todo if precached load it here + S_music[i].data = NULL; + return i; + } + } + CONS_Alert(CONS_WARNING, M_GetText("No more free music slots\n")); + return 0; +} + void S_RemoveSoundFx(sfxenum_t id) { if (id >= sfx_freeslot0 && id <= sfx_lastskinsoundslot diff --git a/src/sounds.h b/src/sounds.h index c5851a346..438d53b92 100644 --- a/src/sounds.h +++ b/src/sounds.h @@ -102,6 +102,11 @@ typedef struct // music handle once registered INT32 handle; + + //yellowtd: Music has no options unlike sfxinfo_t + //So we apply a dummy value for such + INT32 dummyval; + } musicinfo_t; // the complete set of sound effects @@ -114,6 +119,8 @@ extern musicinfo_t S_music[]; // Identifiers for all music in game. // +#define NUMMUSFREESLOTS 800 + // Music list (don't edit this comment!) typedef enum { @@ -1169,7 +1176,15 @@ typedef enum mus_credit, // credits mus_racent, // Race Results mus_stjr, // Sonic Team Jr. Presents - + + //yellowtd: Freeslots for musics. The magic begins elsewhere + // free slots for S_AddMusic() at run-time -------------------- + mus_frees0, + // + // ... 60 free musics here ... + // + mus_lstfre = mus_frees0 + NUMMUSFREESLOTS-1, + // end of freeslots --------------------------------------------- NUMMUSIC } musicenum_t; // Note: song number should be a UINT16, as mapmusic only uses 16 bits for music slot number. @@ -1631,6 +1646,7 @@ typedef enum void S_InitRuntimeSounds(void); sfxenum_t S_AddSoundFx(const char *name, boolean singular, INT32 flags, boolean skinsound); +musicenum_t S_AddMusic(const char *name, INT32 dummyval); void S_RemoveSoundFx(sfxenum_t id); #endif