MP Jingle: Changed music_stacks from fixed array to next/prev chain

This commit is contained in:
mazmazz 2018-09-20 16:37:14 -04:00
parent 7cd1bfb8d7
commit 78c1b99cd4
2 changed files with 126 additions and 119 deletions

View file

@ -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;
} }

View file

@ -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);