mirror of
https://git.do.srb2.org/STJr/SRB2.git
synced 2025-01-17 23:21:22 +00:00
MP Jingle: Changed music_stacks from fixed array to next/prev chain
This commit is contained in:
parent
7cd1bfb8d7
commit
78c1b99cd4
2 changed files with 126 additions and 119 deletions
238
src/s_sound.c
238
src/s_sound.c
|
@ -1229,8 +1229,6 @@ static boolean queue_looping;
|
|||
static UINT32 queue_position;
|
||||
static UINT32 queue_fadeinms;
|
||||
|
||||
static musicstack_t music_stack[NUMMUSICSTACKS];
|
||||
|
||||
static tic_t pause_starttic;
|
||||
|
||||
/// ------------------------
|
||||
|
@ -1336,7 +1334,8 @@ UINT32 S_GetMusicPosition(void)
|
|||
/// In this section: mazmazz doesn't know how to do dynamic arrays or struct pointers!
|
||||
/// ------------------------
|
||||
|
||||
static const musicstack_t empty_music_stack_entry = {"\0", 0, false, 0, 0, 0};
|
||||
static musicstack_t *music_stacks = NULL;
|
||||
static musicstack_t *last_music_stack = NULL;
|
||||
|
||||
void S_SetStackAdjustmentStart(void)
|
||||
{
|
||||
|
@ -1348,152 +1347,145 @@ void S_AdjustMusicStackTics(void)
|
|||
{
|
||||
if (pause_starttic)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < NUMMUSICSTACKS-1; i++)
|
||||
{
|
||||
if (!music_stack[i].status)
|
||||
break;
|
||||
music_stack[i].tic += gametic - pause_starttic;
|
||||
}
|
||||
musicstack_t *mst;
|
||||
for (mst = music_stacks; mst; mst = mst->next)
|
||||
mst->tic += gametic - pause_starttic;
|
||||
pause_starttic = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void S_ResetMusicStack(void)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < NUMMUSICSTACKS; i++)
|
||||
music_stack[i] = empty_music_stack_entry;
|
||||
musicstack_t *mst, *mst_next;
|
||||
for (mst = music_stacks; mst; mst = mst_next)
|
||||
{
|
||||
mst_next = mst->next;
|
||||
Z_Free(mst);
|
||||
}
|
||||
music_stacks = last_music_stack = NULL;
|
||||
}
|
||||
|
||||
static void S_RemoveMusicStackEntry(size_t i)
|
||||
static void S_RemoveMusicStackEntry(musicstack_t *entry)
|
||||
{
|
||||
for (; i < NUMMUSICSTACKS-1; i++)
|
||||
musicstack_t *mst;
|
||||
for (mst = music_stacks; mst; mst = mst->next)
|
||||
{
|
||||
strncpy(music_stack[i].musname, music_stack[i+1].musname, 7);
|
||||
music_stack[i].musname[6] = 0;
|
||||
music_stack[i].musflags = music_stack[i+1].musflags;
|
||||
music_stack[i].looping = music_stack[i+1].looping;
|
||||
music_stack[i].position = music_stack[i+1].position;
|
||||
music_stack[i].tic = music_stack[i+1].tic;
|
||||
music_stack[i].status = music_stack[i+1].status;
|
||||
if (mst == entry)
|
||||
{
|
||||
// Remove ourselves from the chain and link
|
||||
// prev and next together
|
||||
|
||||
if (mst->prev)
|
||||
mst->prev->next = mst->next;
|
||||
else
|
||||
music_stacks = mst->next;
|
||||
|
||||
if (mst->next)
|
||||
mst->next->prev = mst->prev;
|
||||
else
|
||||
last_music_stack = mst->prev;
|
||||
|
||||
if (!music_stack[i].status)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// clear the last slot
|
||||
music_stack[NUMMUSICSTACKS-1] = empty_music_stack_entry;
|
||||
Z_Free(entry);
|
||||
}
|
||||
|
||||
static void S_RemoveMusicStackEntryByStatus(UINT16 status)
|
||||
{
|
||||
int i;
|
||||
musicstack_t *mst, *mst_next;
|
||||
|
||||
if (!status)
|
||||
return;
|
||||
|
||||
for (i = 0; i < NUMMUSICSTACKS-1; i++)
|
||||
for (mst = music_stacks; mst; mst = mst_next)
|
||||
{
|
||||
if (music_stack[i].status == status)
|
||||
{
|
||||
S_RemoveMusicStackEntry(i);
|
||||
i--; // try this position again
|
||||
}
|
||||
else if (!music_stack[i].status)
|
||||
break;
|
||||
mst_next = mst->next;
|
||||
if (mst->status == status)
|
||||
S_RemoveMusicStackEntry(mst);
|
||||
}
|
||||
}
|
||||
|
||||
static void S_AddMusicStackEntry(const char *mname, UINT16 mflags, boolean looping, UINT32 position, UINT16 status)
|
||||
{
|
||||
size_t i;
|
||||
musicstack_t *mst, *new_mst;
|
||||
|
||||
// if the first entry is empty, force master onto it
|
||||
if (!music_stack[0].status && status != JT_MASTER)
|
||||
S_AddMusicStackEntry(mapmusname, mapmusflags, true, S_GetMusicPosition(), JT_MASTER);
|
||||
if (!music_stacks)
|
||||
{
|
||||
music_stacks = Z_Calloc(sizeof (*mst), PU_MUSIC, NULL);
|
||||
strncpy(music_stacks->musname, (status == JT_MASTER ? mname : mapmusname), 7);
|
||||
music_stacks->musflags = (status == JT_MASTER ? mflags : mapmusflags);
|
||||
music_stacks->looping = (status == JT_MASTER ? looping : true);
|
||||
music_stacks->position = (status == JT_MASTER ? position : S_GetMusicPosition());
|
||||
music_stacks->tic = gametic;
|
||||
music_stacks->status = JT_MASTER;
|
||||
|
||||
// are all slots taken? forget the earliest one (save master) and move down the rest
|
||||
if (music_stack[NUMMUSICSTACKS-1].status)
|
||||
S_RemoveMusicStackEntry(1);
|
||||
if (status == JT_MASTER)
|
||||
return; // we just added the user's entry here
|
||||
}
|
||||
|
||||
// look for an empty slot to park ourselves
|
||||
for (i = 0; i < NUMMUSICSTACKS; i++)
|
||||
{
|
||||
// entry doesn't exist? park ourselves here!
|
||||
if (!music_stack[i].status)
|
||||
{
|
||||
strncpy(music_stack[i].musname, mname, 7);
|
||||
music_stack[i].musname[6] = 0;
|
||||
music_stack[i].musflags = mflags;
|
||||
music_stack[i].looping = looping;
|
||||
music_stack[i].position = position;
|
||||
music_stack[i].tic = gametic;
|
||||
music_stack[i].status = status;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (mst = music_stacks; mst->next; mst = mst->next);
|
||||
|
||||
// create our new entry
|
||||
new_mst = Z_Calloc(sizeof (*new_mst), PU_MUSIC, NULL);
|
||||
strncpy(new_mst->musname, mname, 7);
|
||||
new_mst->musname[6] = 0;
|
||||
new_mst->musflags = mflags;
|
||||
new_mst->looping = looping;
|
||||
new_mst->position = position;
|
||||
new_mst->tic = gametic;
|
||||
new_mst->status = status;
|
||||
|
||||
mst->next = new_mst;
|
||||
new_mst->prev = mst;
|
||||
new_mst->next = NULL;
|
||||
last_music_stack = new_mst;
|
||||
}
|
||||
|
||||
static musicstack_t S_GetMusicStackEntry(UINT16 status, boolean fromfirst, INT16 startindex)
|
||||
static musicstack_t *S_GetMusicStackEntry(UINT16 status, boolean fromfirst, INT16 startindex)
|
||||
{
|
||||
INT16 i;
|
||||
musicstack_t *mst, *start_mst = NULL, *mst_next;
|
||||
|
||||
// if the first entry is empty, force master onto it
|
||||
// fixes a memory corruption bug
|
||||
if (!music_stack[0].status && status != JT_MASTER)
|
||||
if (!music_stacks && status != JT_MASTER)
|
||||
S_AddMusicStackEntry(mapmusname, mapmusflags, true, S_GetMusicPosition(), JT_MASTER);
|
||||
|
||||
if (startindex < 0)
|
||||
startindex = fromfirst ? 0 : NUMMUSICSTACKS-1;
|
||||
|
||||
if (fromfirst)
|
||||
if (startindex >= 0)
|
||||
{
|
||||
for (i = startindex; i < NUMMUSICSTACKS; i++)
|
||||
{
|
||||
if (!music_stack[i].status) // we're counting up, so this must mean we reached the end
|
||||
break;
|
||||
else if (!status || music_stack[i].status == status)
|
||||
{
|
||||
if (P_EvaluateMusicStatus(music_stack[i].status))
|
||||
{
|
||||
if (!S_MusicExists(music_stack[i].musname, !midi_disabled, !digital_disabled)) // paranoia
|
||||
S_RemoveMusicStackEntry(i); // then continue
|
||||
else
|
||||
return music_stack[i];
|
||||
}
|
||||
else
|
||||
S_RemoveMusicStackEntry(i); // then continue
|
||||
}
|
||||
}
|
||||
INT16 i = 0;
|
||||
for (mst = music_stacks; mst && i <= startindex; mst = mst->next, i++)
|
||||
start_mst = mst;
|
||||
}
|
||||
else
|
||||
start_mst = (fromfirst ? music_stacks : last_music_stack);
|
||||
|
||||
for (mst = start_mst; mst; mst = mst_next)
|
||||
{
|
||||
for (i = startindex; i >= 0; i--) // this line is why i is signed; otherwise, would wrap around to max value
|
||||
mst_next = (fromfirst ? mst->next : mst->prev);
|
||||
|
||||
if (!status || mst->status == status)
|
||||
{
|
||||
if (!music_stack[i].status) // since we're counting down, we have to skip a few...
|
||||
continue;
|
||||
else if (!status || music_stack[i].status == status)
|
||||
if (P_EvaluateMusicStatus(mst->status))
|
||||
{
|
||||
if (P_EvaluateMusicStatus(music_stack[i].status))
|
||||
{
|
||||
if (!S_MusicExists(music_stack[i].musname, !midi_disabled, !digital_disabled)) // paranoia
|
||||
S_RemoveMusicStackEntry(i); // then continue
|
||||
else
|
||||
return music_stack[i];
|
||||
}
|
||||
if (!S_MusicExists(mst->musname, !midi_disabled, !digital_disabled)) // paranoia
|
||||
S_RemoveMusicStackEntry(mst); // then continue
|
||||
else
|
||||
S_RemoveMusicStackEntry(i); // then continue
|
||||
return mst;
|
||||
}
|
||||
else
|
||||
S_RemoveMusicStackEntry(mst); // then continue
|
||||
}
|
||||
}
|
||||
|
||||
return empty_music_stack_entry;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void S_RetainMusic(const char *mname, UINT16 mflags, boolean looping, UINT32 position, UINT16 status)
|
||||
{
|
||||
size_t i;
|
||||
musicstack_t *mst;
|
||||
|
||||
if (!status) // we use this as a null indicator, don't push
|
||||
{
|
||||
|
@ -1502,9 +1494,9 @@ void S_RetainMusic(const char *mname, UINT16 mflags, boolean looping, UINT32 pos
|
|||
}
|
||||
else if (status == JT_MASTER) // enforce only one JT_MASTER
|
||||
{
|
||||
for (i = 0; i < NUMMUSICSTACKS; i++)
|
||||
for (mst = music_stacks; mst; mst = mst->next)
|
||||
{
|
||||
if (music_stack[i].status == JT_MASTER)
|
||||
if (mst->status == JT_MASTER)
|
||||
{
|
||||
CONS_Alert(CONS_ERROR, "Music stack can only have one JT_MASTER entry.\n");
|
||||
return;
|
||||
|
@ -1521,47 +1513,58 @@ boolean S_RecallMusic(UINT16 status, boolean fromfirst)
|
|||
{
|
||||
UINT32 newpos = 0;
|
||||
boolean mapmuschanged = false;
|
||||
musicstack_t entry;
|
||||
musicstack_t *result;
|
||||
musicstack_t *entry = Z_Calloc(sizeof (*result), PU_MUSIC, NULL);
|
||||
|
||||
if (status)
|
||||
entry = S_GetMusicStackEntry(status, fromfirst, -1);
|
||||
result = S_GetMusicStackEntry(status, fromfirst, -1);
|
||||
else
|
||||
entry = S_GetMusicStackEntry(JT_NONE, false, -1);
|
||||
result = S_GetMusicStackEntry(JT_NONE, false, -1);
|
||||
|
||||
if (!S_MusicExists(entry.musname, !midi_disabled, !digital_disabled))
|
||||
return false; // bad bad bad!!
|
||||
if (result && !S_MusicExists(result->musname, !midi_disabled, !digital_disabled))
|
||||
{
|
||||
Z_Free(entry);
|
||||
return false; // music doesn't exist, so don't do anything
|
||||
}
|
||||
|
||||
// make a copy of result, since we make modifications to our copy
|
||||
if (result)
|
||||
{
|
||||
*entry = *result;
|
||||
strncpy(entry->musname, result->musname, 7);
|
||||
}
|
||||
|
||||
// no result, just grab mapmusname
|
||||
if (!entry.musname[0] || ((status == JT_MASTER || !music_stack[0].status) && !entry.status))
|
||||
if (!result || !entry->musname[0] || ((status == JT_MASTER || (music_stacks ? !music_stacks->status : false)) && !entry->status))
|
||||
{
|
||||
strncpy(entry.musname, mapmusname, 7);
|
||||
entry.musflags = mapmusflags;
|
||||
entry.looping = true;
|
||||
entry.position = mapmusposition;
|
||||
entry.tic = gametic;
|
||||
entry.status = JT_MASTER;
|
||||
strncpy(entry->musname, mapmusname, 7);
|
||||
entry->musflags = mapmusflags;
|
||||
entry->looping = true;
|
||||
entry->position = mapmusposition;
|
||||
entry->tic = gametic;
|
||||
entry->status = JT_MASTER;
|
||||
}
|
||||
|
||||
if (entry.status == JT_MASTER)
|
||||
if (entry->status == JT_MASTER)
|
||||
{
|
||||
mapmuschanged = strnicmp(entry.musname, mapmusname, 7);
|
||||
mapmuschanged = strnicmp(entry->musname, mapmusname, 7);
|
||||
S_ResetMusicStack();
|
||||
}
|
||||
else
|
||||
else if (!entry->status)
|
||||
{
|
||||
if (!entry.status)
|
||||
return false;
|
||||
Z_Free(entry);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!mapmuschanged && strncmp(entry.musname, S_MusicName(), 7)) // don't restart music if we're already playing it
|
||||
if (!mapmuschanged && strncmp(entry->musname, S_MusicName(), 7)) // don't restart music if we're already playing it
|
||||
{
|
||||
if (music_stack_fadeout)
|
||||
S_ChangeMusicEx(entry.musname, entry.musflags, entry.looping, 0, music_stack_fadeout, 0);
|
||||
S_ChangeMusicEx(entry->musname, entry->musflags, entry->looping, 0, music_stack_fadeout, 0);
|
||||
else
|
||||
{
|
||||
S_ChangeMusicEx(entry.musname, entry.musflags, entry.looping, 0, 0, music_stack_fadein);
|
||||
S_ChangeMusicEx(entry->musname, entry->musflags, entry->looping, 0, 0, music_stack_fadein);
|
||||
if (!music_stack_noposition) // HACK: Global boolean to toggle position resuming, e.g., de-superize
|
||||
newpos = entry.position + (S_GetMusicLength() ? (UINT32)((float)(gametic - entry.tic)/(float)TICRATE*(float)MUSICRATE) : 0);
|
||||
newpos = entry->position + (S_GetMusicLength() ? (UINT32)((float)(gametic - entry->tic)/(float)TICRATE*(float)MUSICRATE) : 0);
|
||||
|
||||
if (newpos > 0 && S_MusicPlaying())
|
||||
S_SetMusicPosition(newpos);
|
||||
|
@ -1576,6 +1579,7 @@ boolean S_RecallMusic(UINT16 status, boolean fromfirst)
|
|||
music_stack_fadein = JINGLEPOSTFADE;
|
||||
}
|
||||
|
||||
Z_Free(entry);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -144,20 +144,23 @@ UINT32 S_GetMusicPosition(void);
|
|||
// Music Stacking (Jingles)
|
||||
//
|
||||
|
||||
typedef struct {
|
||||
typedef struct musicstack_s
|
||||
{
|
||||
char musname[7];
|
||||
UINT16 musflags;
|
||||
boolean looping;
|
||||
UINT32 position;
|
||||
tic_t tic;
|
||||
UINT16 status;
|
||||
|
||||
struct musicstack_s *prev;
|
||||
struct musicstack_s *next;
|
||||
} musicstack_t;
|
||||
|
||||
char music_stack_nextmusname[7];
|
||||
boolean music_stack_noposition;
|
||||
UINT32 music_stack_fadeout;
|
||||
UINT32 music_stack_fadein;
|
||||
#define NUMMUSICSTACKS 10 // hahaha wait until someone needs > 10 resumes
|
||||
|
||||
void S_SetStackAdjustmentStart(void);
|
||||
void S_AdjustMusicStackTics(void);
|
||||
|
|
Loading…
Reference in a new issue