mirror of
https://git.do.srb2.org/STJr/SRB2.git
synced 2025-01-18 07:22:28 +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_position;
|
||||||
static UINT32 queue_fadeinms;
|
static UINT32 queue_fadeinms;
|
||||||
|
|
||||||
static musicstack_t music_stack[NUMMUSICSTACKS];
|
|
||||||
|
|
||||||
static tic_t pause_starttic;
|
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!
|
/// 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)
|
void S_SetStackAdjustmentStart(void)
|
||||||
{
|
{
|
||||||
|
@ -1348,152 +1347,145 @@ void S_AdjustMusicStackTics(void)
|
||||||
{
|
{
|
||||||
if (pause_starttic)
|
if (pause_starttic)
|
||||||
{
|
{
|
||||||
size_t i;
|
musicstack_t *mst;
|
||||||
for (i = 0; i < NUMMUSICSTACKS-1; i++)
|
for (mst = music_stacks; mst; mst = mst->next)
|
||||||
{
|
mst->tic += gametic - pause_starttic;
|
||||||
if (!music_stack[i].status)
|
|
||||||
break;
|
|
||||||
music_stack[i].tic += gametic - pause_starttic;
|
|
||||||
}
|
|
||||||
pause_starttic = 0;
|
pause_starttic = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void S_ResetMusicStack(void)
|
static void S_ResetMusicStack(void)
|
||||||
{
|
{
|
||||||
size_t i;
|
musicstack_t *mst, *mst_next;
|
||||||
for (i = 0; i < NUMMUSICSTACKS; i++)
|
for (mst = music_stacks; mst; mst = mst_next)
|
||||||
music_stack[i] = empty_music_stack_entry;
|
{
|
||||||
|
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);
|
if (mst == entry)
|
||||||
music_stack[i].musname[6] = 0;
|
{
|
||||||
music_stack[i].musflags = music_stack[i+1].musflags;
|
// Remove ourselves from the chain and link
|
||||||
music_stack[i].looping = music_stack[i+1].looping;
|
// prev and next together
|
||||||
music_stack[i].position = music_stack[i+1].position;
|
|
||||||
music_stack[i].tic = music_stack[i+1].tic;
|
if (mst->prev)
|
||||||
music_stack[i].status = music_stack[i+1].status;
|
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;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Z_Free(entry);
|
||||||
// clear the last slot
|
|
||||||
music_stack[NUMMUSICSTACKS-1] = empty_music_stack_entry;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void S_RemoveMusicStackEntryByStatus(UINT16 status)
|
static void S_RemoveMusicStackEntryByStatus(UINT16 status)
|
||||||
{
|
{
|
||||||
int i;
|
musicstack_t *mst, *mst_next;
|
||||||
|
|
||||||
if (!status)
|
if (!status)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (i = 0; i < NUMMUSICSTACKS-1; i++)
|
for (mst = music_stacks; mst; mst = mst_next)
|
||||||
{
|
{
|
||||||
if (music_stack[i].status == status)
|
mst_next = mst->next;
|
||||||
{
|
if (mst->status == status)
|
||||||
S_RemoveMusicStackEntry(i);
|
S_RemoveMusicStackEntry(mst);
|
||||||
i--; // try this position again
|
|
||||||
}
|
|
||||||
else if (!music_stack[i].status)
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void S_AddMusicStackEntry(const char *mname, UINT16 mflags, boolean looping, UINT32 position, UINT16 status)
|
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 the first entry is empty, force master onto it
|
||||||
if (!music_stack[0].status && status != JT_MASTER)
|
if (!music_stacks)
|
||||||
S_AddMusicStackEntry(mapmusname, mapmusflags, true, S_GetMusicPosition(), JT_MASTER);
|
{
|
||||||
|
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 (status == JT_MASTER)
|
||||||
if (music_stack[NUMMUSICSTACKS-1].status)
|
return; // we just added the user's entry here
|
||||||
S_RemoveMusicStackEntry(1);
|
}
|
||||||
|
|
||||||
// look for an empty slot to park ourselves
|
// look for an empty slot to park ourselves
|
||||||
for (i = 0; i < NUMMUSICSTACKS; i++)
|
for (mst = music_stacks; mst->next; mst = mst->next);
|
||||||
{
|
|
||||||
// entry doesn't exist? park ourselves here!
|
// create our new entry
|
||||||
if (!music_stack[i].status)
|
new_mst = Z_Calloc(sizeof (*new_mst), PU_MUSIC, NULL);
|
||||||
{
|
strncpy(new_mst->musname, mname, 7);
|
||||||
strncpy(music_stack[i].musname, mname, 7);
|
new_mst->musname[6] = 0;
|
||||||
music_stack[i].musname[6] = 0;
|
new_mst->musflags = mflags;
|
||||||
music_stack[i].musflags = mflags;
|
new_mst->looping = looping;
|
||||||
music_stack[i].looping = looping;
|
new_mst->position = position;
|
||||||
music_stack[i].position = position;
|
new_mst->tic = gametic;
|
||||||
music_stack[i].tic = gametic;
|
new_mst->status = status;
|
||||||
music_stack[i].status = status;
|
|
||||||
break;
|
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
|
// if the first entry is empty, force master onto it
|
||||||
// fixes a memory corruption bug
|
// 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);
|
S_AddMusicStackEntry(mapmusname, mapmusflags, true, S_GetMusicPosition(), JT_MASTER);
|
||||||
|
|
||||||
if (startindex < 0)
|
if (startindex >= 0)
|
||||||
startindex = fromfirst ? 0 : NUMMUSICSTACKS-1;
|
|
||||||
|
|
||||||
if (fromfirst)
|
|
||||||
{
|
{
|
||||||
for (i = startindex; i < NUMMUSICSTACKS; i++)
|
INT16 i = 0;
|
||||||
{
|
for (mst = music_stacks; mst && i <= startindex; mst = mst->next, i++)
|
||||||
if (!music_stack[i].status) // we're counting up, so this must mean we reached the end
|
start_mst = mst;
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
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...
|
if (P_EvaluateMusicStatus(mst->status))
|
||||||
continue;
|
|
||||||
else if (!status || music_stack[i].status == status)
|
|
||||||
{
|
{
|
||||||
if (P_EvaluateMusicStatus(music_stack[i].status))
|
if (!S_MusicExists(mst->musname, !midi_disabled, !digital_disabled)) // paranoia
|
||||||
{
|
S_RemoveMusicStackEntry(mst); // then continue
|
||||||
if (!S_MusicExists(music_stack[i].musname, !midi_disabled, !digital_disabled)) // paranoia
|
|
||||||
S_RemoveMusicStackEntry(i); // then continue
|
|
||||||
else
|
|
||||||
return music_stack[i];
|
|
||||||
}
|
|
||||||
else
|
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)
|
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
|
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
|
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");
|
CONS_Alert(CONS_ERROR, "Music stack can only have one JT_MASTER entry.\n");
|
||||||
return;
|
return;
|
||||||
|
@ -1521,47 +1513,58 @@ boolean S_RecallMusic(UINT16 status, boolean fromfirst)
|
||||||
{
|
{
|
||||||
UINT32 newpos = 0;
|
UINT32 newpos = 0;
|
||||||
boolean mapmuschanged = false;
|
boolean mapmuschanged = false;
|
||||||
musicstack_t entry;
|
musicstack_t *result;
|
||||||
|
musicstack_t *entry = Z_Calloc(sizeof (*result), PU_MUSIC, NULL);
|
||||||
|
|
||||||
if (status)
|
if (status)
|
||||||
entry = S_GetMusicStackEntry(status, fromfirst, -1);
|
result = S_GetMusicStackEntry(status, fromfirst, -1);
|
||||||
else
|
else
|
||||||
entry = S_GetMusicStackEntry(JT_NONE, false, -1);
|
result = S_GetMusicStackEntry(JT_NONE, false, -1);
|
||||||
|
|
||||||
if (!S_MusicExists(entry.musname, !midi_disabled, !digital_disabled))
|
if (result && !S_MusicExists(result->musname, !midi_disabled, !digital_disabled))
|
||||||
return false; // bad bad bad!!
|
{
|
||||||
|
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
|
// 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);
|
strncpy(entry->musname, mapmusname, 7);
|
||||||
entry.musflags = mapmusflags;
|
entry->musflags = mapmusflags;
|
||||||
entry.looping = true;
|
entry->looping = true;
|
||||||
entry.position = mapmusposition;
|
entry->position = mapmusposition;
|
||||||
entry.tic = gametic;
|
entry->tic = gametic;
|
||||||
entry.status = JT_MASTER;
|
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();
|
S_ResetMusicStack();
|
||||||
}
|
}
|
||||||
else
|
else if (!entry->status)
|
||||||
{
|
{
|
||||||
if (!entry.status)
|
Z_Free(entry);
|
||||||
return false;
|
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)
|
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
|
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
|
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())
|
if (newpos > 0 && S_MusicPlaying())
|
||||||
S_SetMusicPosition(newpos);
|
S_SetMusicPosition(newpos);
|
||||||
|
@ -1576,6 +1579,7 @@ boolean S_RecallMusic(UINT16 status, boolean fromfirst)
|
||||||
music_stack_fadein = JINGLEPOSTFADE;
|
music_stack_fadein = JINGLEPOSTFADE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Z_Free(entry);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -144,20 +144,23 @@ UINT32 S_GetMusicPosition(void);
|
||||||
// Music Stacking (Jingles)
|
// Music Stacking (Jingles)
|
||||||
//
|
//
|
||||||
|
|
||||||
typedef struct {
|
typedef struct musicstack_s
|
||||||
|
{
|
||||||
char musname[7];
|
char musname[7];
|
||||||
UINT16 musflags;
|
UINT16 musflags;
|
||||||
boolean looping;
|
boolean looping;
|
||||||
UINT32 position;
|
UINT32 position;
|
||||||
tic_t tic;
|
tic_t tic;
|
||||||
UINT16 status;
|
UINT16 status;
|
||||||
|
|
||||||
|
struct musicstack_s *prev;
|
||||||
|
struct musicstack_s *next;
|
||||||
} musicstack_t;
|
} musicstack_t;
|
||||||
|
|
||||||
char music_stack_nextmusname[7];
|
char music_stack_nextmusname[7];
|
||||||
boolean music_stack_noposition;
|
boolean music_stack_noposition;
|
||||||
UINT32 music_stack_fadeout;
|
UINT32 music_stack_fadeout;
|
||||||
UINT32 music_stack_fadein;
|
UINT32 music_stack_fadein;
|
||||||
#define NUMMUSICSTACKS 10 // hahaha wait until someone needs > 10 resumes
|
|
||||||
|
|
||||||
void S_SetStackAdjustmentStart(void);
|
void S_SetStackAdjustmentStart(void);
|
||||||
void S_AdjustMusicStackTics(void);
|
void S_AdjustMusicStackTics(void);
|
||||||
|
|
Loading…
Reference in a new issue