Merge branch 'jam-project' into 'master'

Stereo Mode

See merge request KartKrew/Kart!1097
This commit is contained in:
Oni 2023-03-31 01:07:38 +00:00
commit dec66ee9b1
51 changed files with 1133 additions and 71 deletions

View file

@ -953,7 +953,10 @@ void D_SRB2Loop(void)
// consoleplayer -> displayplayers (hear sounds from viewpoint)
S_UpdateSounds(); // move positional sounds
if (realtics > 0 || singletics)
{
S_UpdateClosedCaptions();
S_TickSoundTest();
}
#ifdef HW3SOUND
HW3S_EndFrameUpdate();

View file

@ -1187,8 +1187,42 @@ void readlevelheader(MYFILE *f, char * name)
mapheaderinfo[num]->musname_size = j;
}
}
else if (fastcmp(word, "MUSICSLOT"))
deh_warning("Level header %d: MusicSlot parameter is deprecated and will be removed.\nUse \"Music\" instead.", num);
else if (fastcmp(word, "ASSOCIATEDMUSIC"))
{
if (fastcmp(word2, "NONE"))
{
mapheaderinfo[num]->associatedmus[0][0] = 0; // becomes empty string
mapheaderinfo[num]->associatedmus_size = 0;
}
else
{
UINT8 j = 0; // i was declared elsewhere
tmp = strtok(word2, ",");
do {
if (j >= MAXMUSNAMES)
break;
deh_strlcpy(mapheaderinfo[num]->associatedmus[j], tmp,
sizeof(mapheaderinfo[num]->associatedmus[j]), va("Level header %d: associated music", num));
j++;
} while ((tmp = strtok(NULL,",")) != NULL);
if (tmp != NULL)
deh_warning("Level header %d: additional associated music slots past %d discarded", num, MAXMUSNAMES);
mapheaderinfo[num]->associatedmus_size = j;
}
}
else if (fastcmp(word, "POSITIONMUSIC"))
{
if (fastcmp(word2, "NONE"))
{
mapheaderinfo[num]->positionmus[0] = 0; // becomes empty string
}
else
{
deh_strlcpy(mapheaderinfo[num]->positionmus, word2,
sizeof(mapheaderinfo[num]->positionmus), va("Level header %d: POSITION!! music", num));
}
}
else if (fastcmp(word, "MUSICTRACK"))
mapheaderinfo[num]->mustrack = ((UINT16)i - 1);
else if (fastcmp(word, "MUSICPOS"))

View file

@ -445,9 +445,12 @@ struct mapheader_t
// Music information
char musname[MAXMUSNAMES][7]; ///< Music tracks to play. First dimension is the track number, second is the music string. "" for no music.
char associatedmus[MAXMUSNAMES][7]; ///< Associated music tracks for sound test unlock.
char positionmus[7]; ///< Custom Position track. Doesn't play in Encore or other fun game-controlled contexts
UINT8 musname_size; ///< Number of music tracks defined
UINT8 associatedmus_size; ///< Number of associated music tracks defined
UINT16 mustrack; ///< Subsong to play. Only really relevant for music modules and specific formats supported by GME. 0 to ignore.
UINT32 muspos; ///< Music position to jump to.
UINT8 musname_size; ///< Number of music tracks defined
// Sky information
UINT8 weather; ///< See preciptype_t

View file

@ -129,6 +129,12 @@ void M_HandlePauseMenuGametype(INT32 choice);
// MENU TYPEDEFS
//
typedef enum
{
MBF_UD_LR_FLIPPED = 1, // flip up-down and left-right axes
MBF_SOUNDLESS = 2, // do not play base menu sounds
} menubehaviourflags_t;
struct menuitem_t
{
UINT16 status; // show IT_xxx
@ -154,6 +160,7 @@ struct menu_t
INT16 x, y; // x, y of menu
INT16 extra1, extra2; // Can be whatever really! Options menu uses extra1 for bg colour.
INT16 behaviourflags; // menubehaviourflags_t
const char *music; // Track to play in M_PlayMenuJam. NULL for default, "." to stop
INT16 transitionID; // only transition if IDs match
@ -419,10 +426,14 @@ extern menuitem_t MISC_ChallengesStatsDummyMenu[];
extern menu_t MISC_ChallengesDef;
extern menu_t MISC_StatisticsDef;
extern menuitem_t MISC_SoundTest[];
extern menu_t MISC_SoundTestDef;
// We'll need this since we're gonna have to dynamically enable and disable options depending on which state we're in.
typedef enum
{
mpause_addons = 0,
mpause_stereo,
mpause_changegametype,
mpause_switchmap,
mpause_restartmap,
@ -574,7 +585,9 @@ boolean M_NextOpt(void);
boolean M_PrevOpt(void);
boolean M_MenuConfirmPressed(UINT8 pid);
boolean M_MenuConfirmHeld(UINT8 pid);
boolean M_MenuBackPressed(UINT8 pid);
boolean M_MenuBackHeld(UINT8 pid);
boolean M_MenuExtraPressed(UINT8 pid);
boolean M_MenuExtraHeld(UINT8 pid);
@ -1000,6 +1013,16 @@ extern struct extrasmenu_s {
} extrasmenu;
typedef enum
{
extras_addons = 0,
extras_challenges,
//extras_tutorial,
extras_statistics,
extras_eggtv,
extras_stereo,
} extras_e;
void M_InitExtras(INT32 choice); // init for the struct
void M_ExtrasTick(void);
boolean M_ExtrasInputs(INT32 ch);
@ -1196,6 +1219,21 @@ void M_Statistics(INT32 choice);
void M_DrawStatistics(void);
boolean M_StatisticsInputs(INT32 ch);
typedef enum
{
stereospecial_none = 0,
stereospecial_back,
stereospecial_pause,
stereospecial_play,
stereospecial_seq,
stereospecial_vol,
stereospecial_track,
} stereospecial_e;
void M_SoundTest(INT32 choice);
void M_DrawSoundTest(void);
consvar_t *M_GetSoundTestVolumeCvar(void);
// These defines make it a little easier to make menus
#define DEFAULTMENUSTYLE(source, prev, x, y)\
{\
@ -1204,6 +1242,8 @@ boolean M_StatisticsInputs(INT32 ch);
0,\
source,\
x, y,\
0, 0,\
0,\
NULL,\
0, 0,\
M_DrawGenericMenu,\
@ -1222,6 +1262,7 @@ boolean M_StatisticsInputs(INT32 ch);
source,\
0, 0,\
0, 0,\
0,\
NULL,\
1, 5,\
M_DrawKartGamemodeMenu,\
@ -1239,6 +1280,7 @@ boolean M_StatisticsInputs(INT32 ch);
source,\
0, 0,\
0, 0,\
0,\
"EXTRAS",\
1, 5,\
M_DrawImageDef,\

View file

@ -5925,3 +5925,269 @@ void M_DrawStatistics(void)
}
#undef STATSSTEP
void M_DrawSoundTest(void)
{
UINT8 pid = 0; // todo: Add ability for any splitscreen player to bring up the menu.
INT32 x, y, i, cursorx = 0;
INT32 titleoffset = 0, titlewidth;
const char *titletext;
patch_t *btn = W_CachePatchName("STER_BTN", PU_CACHE);
if (gamestate == GS_MENU)
{
patch_t *bg = W_CachePatchName("M_XTRABG", PU_CACHE);
V_DrawFixedPatch(0, 0, FRACUNIT, 0, bg, NULL);
}
V_DrawFixedPatch(0, 0, FRACUNIT, 0, W_CachePatchName("STER_BG", PU_CACHE), NULL);
x = 24;
y = 18;
V_SetClipRect(
x << FRACBITS, y << FRACBITS,
272 << FRACBITS, 106 << FRACBITS,
0
);
y += 32;
if (soundtest.current != NULL)
{
if (soundtest.current->sequence.map < nummapheaders)
{
K_DrawMapThumbnail(
0, 0,
BASEVIDWIDTH<<FRACBITS,
V_20TRANS|V_ADD,
soundtest.current->sequence.map,
NULL);
V_DrawFixedPatch(
0, 0,
FRACUNIT,
V_60TRANS|V_SUBTRACT,
W_CachePatchName("STER_DOT", PU_CACHE),
NULL
);
}
titletext = soundtest.current->title;
V_DrawThinString(x, y, V_ALLOWLOWERCASE|V_6WIDTHSPACE, titletext);
if (soundtest.current->numtracks > 1)
V_DrawThinString(x, (y += 10), V_ALLOWLOWERCASE|V_6WIDTHSPACE, va("Track %c", 'A'+soundtest.currenttrack));
if (soundtest.current->author)
V_DrawThinString(x, (y += 10), V_ALLOWLOWERCASE|V_6WIDTHSPACE, soundtest.current->author);
if (soundtest.current->source)
V_DrawThinString(x, (y += 10), V_ALLOWLOWERCASE|V_6WIDTHSPACE, soundtest.current->source);
if (soundtest.current->composers)
V_DrawThinString(x, (y += 10), V_ALLOWLOWERCASE|V_6WIDTHSPACE, soundtest.current->composers);
}
else
{
const char *sfxstr = (cv_soundtest.value) ? S_sfx[cv_soundtest.value].name : "N/A";
titletext = "Sound Test";
V_DrawThinString(x, y, V_ALLOWLOWERCASE|V_6WIDTHSPACE, "Track ");
V_DrawThinString(
x + V_ThinStringWidth("Track ", V_ALLOWLOWERCASE|V_6WIDTHSPACE),
y,
V_6WIDTHSPACE,
va("%04X - %s", cv_soundtest.value, sfxstr)
);
}
titletext = va("%s - ", titletext);
titlewidth = V_LSTitleHighStringWidth(titletext, 0);
titleoffset = (-soundtest.menutick) % titlewidth;
while (titleoffset < 272)
{
V_DrawLSTitleHighString(x + titleoffset, 18+1, 0, titletext);
titleoffset += titlewidth;
}
V_DrawRightAlignedString(x + 272-1, 18+32, 0,
va("%02u:%02u",
G_TicsToMinutes(soundtest.currenttime, true),
G_TicsToSeconds(soundtest.currenttime)
)
);
if ((soundtest.playing && soundtest.current)
&& (soundtest.current->basenoloop[soundtest.currenttrack] == true
|| soundtest.autosequence == true))
{
UINT32 exittime = soundtest.sequencemaxtime;
if (soundtest.dosequencefadeout == true)
{
exittime += 3*TICRATE;
}
V_DrawRightAlignedString(x + 272-1, 18+32+10, 0,
va("%02u:%02u",
G_TicsToMinutes(exittime, true),
G_TicsToSeconds(exittime)
)
);
}
V_ClearClipRect();
x = currentMenu->x;
for (i = 0; i < currentMenu->numitems; i++)
{
if (currentMenu->menuitems[i].status == IT_SPACE)
{
if (currentMenu->menuitems[i].mvar2 != 0)
{
x = currentMenu->menuitems[i].mvar2;
}
x += currentMenu->menuitems[i].mvar1;
continue;
}
y = currentMenu->y;
if (i == itemOn)
{
cursorx = x + 13;
}
if (currentMenu->menuitems[i].tooltip)
{
V_SetClipRect(
x << FRACBITS, y << FRACBITS,
27 << FRACBITS, 22 << FRACBITS,
0
);
// Special cases
if (currentMenu->menuitems[i].mvar2 == stereospecial_back) // back
{
if (!soundtest.justopened && M_MenuBackHeld(pid))
{
y = currentMenu->y + 7;
}
}
// The following are springlocks.
else if (currentMenu->menuitems[i].mvar2 == stereospecial_pause) // pause
{
if (soundtest.paused == true)
y = currentMenu->y + 6;
}
else if (currentMenu->menuitems[i].mvar2 == stereospecial_play) // play
{
if (soundtest.playing == true && soundtest.paused == false)
y = currentMenu->y + 6;
}
else if (currentMenu->menuitems[i].mvar2 == stereospecial_seq) // seq
{
if (soundtest.autosequence == true)
y = currentMenu->y + 6;
}
// Button is being pressed
if (i == itemOn && !soundtest.justopened && M_MenuConfirmHeld(pid))
{
y = currentMenu->y + 7;
}
// Button itself
V_DrawFixedPatch(x << FRACBITS, y << FRACBITS, FRACUNIT, 0, btn, NULL);
// Icon
V_DrawFixedPatch(x << FRACBITS, y << FRACBITS,
FRACUNIT, 0,
W_CachePatchName(currentMenu->menuitems[i].tooltip, PU_CACHE),
NULL
);
// Text
V_DrawCenteredThinString(x + 13, y + 1, V_6WIDTHSPACE, currentMenu->menuitems[i].text);
V_ClearClipRect();
V_DrawFill(x+2, currentMenu->y + 22, 23, 1, 30);
}
else if (currentMenu->menuitems[i].mvar2 == stereospecial_vol) // Vol
{
consvar_t *voltoadjust = M_GetSoundTestVolumeCvar();
INT32 j, vol = 0;
const INT32 barheight = 22;
V_DrawFixedPatch((x+1) << FRACBITS, y << FRACBITS,
FRACUNIT, 0,
W_CachePatchName("STER_KNB", PU_CACHE),
NULL
);
V_DrawFill(x+1+24, y+1, 5, barheight, 30);
if (voltoadjust != NULL)
{
vol = (barheight*voltoadjust->value)/(MAX_SOUND_VOLUME*3);
}
for (j = 0; j <= barheight/3; j++)
{
UINT8 col = 130;
if (j == 0)
{
continue;
}
if (j > vol)
{
col = 20;
}
else if (j > (barheight/3)-2)
{
col = 34;
}
V_DrawFill(x+1+24+2, y+1 + (barheight-(j*3)), 1, 2, col);
}
x += 5;
}
else if (currentMenu->menuitems[i].mvar2 == stereospecial_track) // Track
{
if (i == itemOn)
{
if (menucmd[pid].dpad_ud < 0 || M_MenuConfirmHeld(pid))
{
y--;
}
else if (menucmd[pid].dpad_ud > 0)
{
y++;
}
}
V_DrawFixedPatch(x << FRACBITS, (y-1) << FRACBITS,
FRACUNIT, 0,
W_CachePatchName("STER_WH0", PU_CACHE),
NULL
);
}
else
{
V_DrawCenteredThinString(x + 13, y + 1, V_6WIDTHSPACE, currentMenu->menuitems[i].text);
}
x += 27;
}
V_DrawCharacter(cursorx - 4, currentMenu->y - 8 - (skullAnimCounter/5),
'\x1B' | V_SNAPTOTOP|highlightflags, false); // up arrow
}

View file

@ -382,7 +382,7 @@ void M_PlayMenuJam(void)
return;
}
if (Playing())
if (Playing() || soundtest.playing)
return;
if (refMenu != NULL && refMenu->music != NULL)
@ -799,10 +799,10 @@ boolean M_MenuConfirmPressed(UINT8 pid)
return M_MenuButtonPressed(pid, MBT_A);
}
/*static boolean M_MenuConfirmHeld(UINT8 pid)
boolean M_MenuConfirmHeld(UINT8 pid)
{
return M_MenuButtonHeld(pid, MBT_A);
}*/
}
// Returns true if we press the Cancel button
boolean M_MenuBackPressed(UINT8 pid)
@ -810,10 +810,10 @@ boolean M_MenuBackPressed(UINT8 pid)
return (M_MenuButtonPressed(pid, MBT_B) || M_MenuButtonPressed(pid, MBT_X));
}
/*static boolean M_MenuBackHeld(UINT8 pid)
boolean M_MenuBackHeld(UINT8 pid)
{
return (M_MenuButtonHeld(pid, MBT_B) || M_MenuButtonHeld(pid, MBT_X));
}*/
}
// Retrurns true if we press the tertiary option button (C)
boolean M_MenuExtraPressed(UINT8 pid)
@ -902,8 +902,7 @@ static void M_HandleMenuInput(void)
lr = menucmd[pid].dpad_lr;
ud = menucmd[pid].dpad_ud;
// If we ever add a second horizontal menu, make it a menu_t property, not an extra check.
if (currentMenu == &PAUSE_PlaybackMenuDef)
if (currentMenu->behaviourflags & MBF_UD_LR_FLIPPED)
{
ud = menucmd[pid].dpad_lr;
lr = -menucmd[pid].dpad_ud;
@ -916,14 +915,14 @@ static void M_HandleMenuInput(void)
// Keys usable within menu
if (ud > 0)
{
if (M_NextOpt())
if (M_NextOpt() && !(currentMenu->behaviourflags & MBF_SOUNDLESS))
S_StartSound(NULL, sfx_s3k5b);
M_SetMenuDelay(pid);
return;
}
else if (ud < 0)
{
if (M_PrevOpt())
if (M_PrevOpt() && !(currentMenu->behaviourflags & MBF_SOUNDLESS))
S_StartSound(NULL, sfx_s3k5b);
M_SetMenuDelay(pid);
return;
@ -933,7 +932,8 @@ static void M_HandleMenuInput(void)
if (routine && ((currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_ARROWS
|| (currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_CVAR))
{
S_StartSound(NULL, sfx_s3k5b);
if (!(currentMenu->behaviourflags & MBF_SOUNDLESS))
S_StartSound(NULL, sfx_s3k5b);
routine(0);
M_SetMenuDelay(pid);
}
@ -945,7 +945,8 @@ static void M_HandleMenuInput(void)
if (routine && ((currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_ARROWS
|| (currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_CVAR))
{
S_StartSound(NULL, sfx_s3k5b);
if (!(currentMenu->behaviourflags & MBF_SOUNDLESS))
S_StartSound(NULL, sfx_s3k5b);
routine(1);
M_SetMenuDelay(pid);
}
@ -959,7 +960,8 @@ static void M_HandleMenuInput(void)
if (routine)
{
S_StartSound(NULL, sfx_s3k5b);
if (!(currentMenu->behaviourflags & MBF_SOUNDLESS))
S_StartSound(NULL, sfx_s3k5b);
if (((currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_CALL
|| (currentMenu->menuitems[itemOn].status & IT_TYPE) == IT_SUBMENU)
@ -1014,7 +1016,8 @@ static void M_HandleMenuInput(void)
return;
}*/
S_StartSound(NULL, sfx_s3k5b);
if (!(currentMenu->behaviourflags & MBF_SOUNDLESS))
S_StartSound(NULL, sfx_s3k5b);
routine(-1);
M_SetMenuDelay(pid);

View file

@ -22,6 +22,9 @@ menuitem_t EXTRAS_Main[] =
{IT_STRING | IT_CALL, NULL, NULL,
NULL, {.routine = M_ReplayHut}, 0, 0},
{IT_STRING | IT_CALL, NULL, NULL,
NULL, {.routine = M_SoundTest}, 0, 0},
};
// the extras menu essentially reuses the options menu stuff
@ -32,8 +35,9 @@ menu_t EXTRAS_MainDef = {
EXTRAS_Main,
0, 0,
0, 0,
0,
"EXTRAS",
2, 5,
28, 5,
M_DrawExtras,
M_ExtrasTick,
NULL,
@ -61,35 +65,44 @@ void M_InitExtras(INT32 choice)
// Addons
if (M_SecretUnlocked(SECRET_ADDONS, true))
{
EXTRAS_Main[0].status = IT_STRING | IT_CALL;
EXTRAS_Main[0].text = "Addons";
EXTRAS_Main[0].tooltip = "Add files to customize your experience.";
EXTRAS_Main[extras_addons].status = IT_STRING | IT_CALL;
EXTRAS_Main[extras_addons].text = "Addons";
EXTRAS_Main[extras_addons].tooltip = "Add files to customize your experience.";
}
else
{
EXTRAS_Main[0].status = IT_STRING | IT_TRANSTEXT;
EXTRAS_Main[0].text = EXTRAS_Main[0].tooltip = "???";
if (EXTRAS_MainDef.lastOn == 0)
EXTRAS_Main[extras_addons].status = IT_STRING | IT_TRANSTEXT;
EXTRAS_Main[extras_addons].text = EXTRAS_Main[extras_addons].tooltip = "???";
if (EXTRAS_MainDef.lastOn == extras_addons)
{
EXTRAS_MainDef.lastOn = 1;
EXTRAS_MainDef.lastOn = extras_challenges;
}
}
// Egg TV
if (M_SecretUnlocked(SECRET_EGGTV, true))
{
EXTRAS_Main[3].status = IT_STRING | IT_CALL;
EXTRAS_Main[3].text = "Egg TV";
EXTRAS_Main[3].tooltip = "Watch the replays you've saved throughout your many races & battles!";
EXTRAS_Main[extras_eggtv].status = IT_STRING | IT_CALL;
EXTRAS_Main[extras_eggtv].text = "Egg TV";
EXTRAS_Main[extras_eggtv].tooltip = "Watch the replays you've saved throughout your many races & battles!";
}
else
{
EXTRAS_Main[3].status = IT_STRING | IT_TRANSTEXT;
EXTRAS_Main[3].text = EXTRAS_Main[3].tooltip = "???";
if (EXTRAS_MainDef.lastOn == 3)
{
EXTRAS_MainDef.lastOn = 2;
}
EXTRAS_Main[extras_eggtv].status = IT_STRING | IT_TRANSTEXT;
EXTRAS_Main[extras_eggtv].text = EXTRAS_Main[extras_eggtv].tooltip = "???";
}
// Stereo Mode
if (M_SecretUnlocked(SECRET_SOUNDTEST, true))
{
EXTRAS_Main[extras_stereo].status = IT_STRING | IT_CALL;
EXTRAS_Main[extras_stereo].text = "Stereo Mode";
EXTRAS_Main[extras_stereo].tooltip = "You can listen to your favourite tunes here!";
}
else
{
EXTRAS_Main[extras_stereo].status = IT_STRING | IT_TRANSTEXT;
EXTRAS_Main[extras_stereo].text = EXTRAS_Main[extras_stereo].tooltip = "???";
}
M_SetupNextMenu(&EXTRAS_MainDef, false);

View file

@ -23,6 +23,7 @@ menu_t MISC_AddonsDef = {
MISC_AddonsMenu,
50, 28,
0, 0,
0,
"EXTRAS",
0, 0,
M_DrawAddons,

View file

@ -20,6 +20,7 @@ menu_t MISC_ChallengesDef = {
MISC_ChallengesStatsDummyMenu,
BASEVIDWIDTH/2, 30,
0, 0,
0,
"EXTRAS",
98, 0,
M_DrawChallenges,
@ -38,6 +39,7 @@ menu_t MISC_StatisticsDef = {
MISC_ChallengesStatsDummyMenu,
280, 185,
0, 0,
0,
"EXTRAS",
98, 0,
M_DrawStatistics,

View file

@ -26,6 +26,7 @@ menu_t EXTRAS_ReplayHutDef =
EXTRAS_ReplayHut,
30, 80,
0, 0,
0,
"REPLAY",
41, 1,
M_DrawReplayHut,
@ -59,6 +60,7 @@ menu_t EXTRAS_ReplayStartDef =
EXTRAS_ReplayStart,
27, 80,
0, 0,
0,
"REPLAY",
41, 1,
M_DrawReplayStartMenu,

View file

@ -15,6 +15,7 @@ menu_t MAIN_ProfilesDef = {
MAIN_Profiles,
32, 80,
SKINCOLOR_ULTRAMARINE, 0,
0,
NULL,
2, 5,
M_DrawProfileSelect,

View file

@ -43,6 +43,7 @@ menu_t OPTIONS_MainDef = {
OPTIONS_Main,
0, 0,
SKINCOLOR_SLATE, 0,
0,
NULL,
2, 5,
M_DrawOptions,

View file

@ -36,6 +36,7 @@ menu_t OPTIONS_DataDef = {
OPTIONS_Data,
48, 80,
SKINCOLOR_BLUEBERRY, 0,
0,
NULL,
2, 5,
M_DrawGenericOptions,

View file

@ -37,6 +37,7 @@ menu_t OPTIONS_DataAddonDef = {
OPTIONS_DataAddon,
48, 80,
SKINCOLOR_BLUEBERRY, 0,
0,
NULL,
2, 5,
M_DrawGenericOptions,

View file

@ -33,6 +33,7 @@ menu_t OPTIONS_DataDiscordDef = {
OPTIONS_DataDiscord,
48, 80,
SKINCOLOR_BLUEBERRY, 0,
0,
NULL,
2, 5,
M_DrawGenericOptions,

View file

@ -40,6 +40,7 @@ menu_t OPTIONS_DataEraseDef = {
OPTIONS_DataErase,
48, 80,
SKINCOLOR_BLACK, 0,
0,
"SHWDN2", // Danger.
2, 5,
M_DrawGenericOptions,

View file

@ -17,6 +17,7 @@ menu_t OPTIONS_DataProfileEraseDef = {
OPTIONS_DataProfileErase,
48, 80,
SKINCOLOR_BLACK, 0,
0,
"SHWDN2", // Danger.
2, 5,
M_DrawProfileErase,

View file

@ -19,6 +19,7 @@ menu_t OPTIONS_DataReplayDef = {
OPTIONS_DataReplay,
48, 80,
SKINCOLOR_BLUEBERRY, 0,
0,
NULL,
2, 5,
M_DrawGenericOptions,

View file

@ -35,6 +35,7 @@ menu_t OPTIONS_DataScreenshotDef = {
OPTIONS_DataScreenshot,
48, 80,
SKINCOLOR_BLUEBERRY, 0,
0,
NULL,
2, 5,
M_DrawGenericOptions,

View file

@ -51,6 +51,7 @@ menu_t OPTIONS_GameplayDef = {
OPTIONS_Gameplay,
48, 80,
SKINCOLOR_SCARLET, 0,
0,
NULL,
2, 5,
M_DrawGenericOptions,

View file

@ -55,6 +55,7 @@ menu_t OPTIONS_GameplayItemsDef = {
OPTIONS_GameplayItems,
14, 40,
SKINCOLOR_SCARLET, 0,
0,
NULL,
2, 5,
M_DrawItemToggles,

View file

@ -48,6 +48,7 @@ menu_t OPTIONS_HUDDef = {
OPTIONS_HUD,
48, 80,
SKINCOLOR_SUNSLAM, 0,
0,
NULL,
2, 5,
M_DrawGenericOptions,

View file

@ -45,6 +45,7 @@ menu_t OPTIONS_HUDOnlineDef = {
OPTIONS_HUDOnline,
48, 80,
SKINCOLOR_SUNSLAM, 0,
0,
NULL,
2, 5,
M_DrawGenericOptions,

View file

@ -17,6 +17,7 @@ menu_t OPTIONS_ProfilesDef = {
OPTIONS_Profiles,
32, 80,
SKINCOLOR_ULTRAMARINE, 0,
0,
NULL,
2, 5,
M_DrawProfileSelect,

View file

@ -29,6 +29,7 @@ menu_t OPTIONS_EditProfileDef = {
OPTIONS_EditProfile,
32, 80,
SKINCOLOR_ULTRAMARINE, 0,
0,
NULL,
2, 5,
M_DrawEditProfile,

View file

@ -103,6 +103,7 @@ menu_t OPTIONS_ProfileControlsDef = {
OPTIONS_ProfileControls,
32, 80,
SKINCOLOR_ULTRAMARINE, 0,
0,
NULL,
3, 5,
M_DrawProfileControls,

View file

@ -55,6 +55,7 @@ menu_t OPTIONS_ServerDef = {
OPTIONS_Server,
48, 70, // This menu here is slightly higher because there's a lot of options...
SKINCOLOR_VIOLET, 0,
0,
NULL,
2, 5,
M_DrawGenericOptions,

View file

@ -53,6 +53,7 @@ menu_t OPTIONS_ServerAdvancedDef = {
OPTIONS_ServerAdvanced,
48, 70, // This menu here is slightly higher because there's a lot of options...
SKINCOLOR_VIOLET, 0,
0,
NULL,
2, 5,
M_DrawGenericOptions,

View file

@ -57,6 +57,7 @@ menu_t OPTIONS_SoundDef = {
OPTIONS_Sound,
48, 80,
SKINCOLOR_THUNDER, 0,
0,
NULL,
2, 5,
M_DrawGenericOptions,

View file

@ -59,6 +59,7 @@ menu_t OPTIONS_VideoDef = {
OPTIONS_Video,
32, 80,
SKINCOLOR_PLAGUE, 0,
0,
NULL,
2, 5,
M_DrawGenericOptions,

View file

@ -51,6 +51,7 @@ menu_t OPTIONS_VideoOGLDef = {
OPTIONS_VideoOGL,
32, 80,
SKINCOLOR_PLAGUE, 0,
0,
NULL,
2, 5,
M_DrawGenericOptions,

View file

@ -19,6 +19,7 @@ menu_t OPTIONS_VideoModesDef = {
OPTIONS_VideoModes,
48, 80,
SKINCOLOR_PLAGUE, 0,
0,
NULL,
2, 5,
M_DrawVideoModes,

View file

@ -19,6 +19,7 @@ menu_t PLAY_CharSelectDef = {
PLAY_CharSelect,
0, 0,
0, 0,
0,
NULL,
0, 0,
M_DrawCharacterSelect,

View file

@ -39,6 +39,7 @@ menu_t PLAY_RaceDifficultyDef = {
PLAY_RaceDifficulty,
0, 0,
0, 0,
0,
NULL,
1, 5,
M_DrawRaceDifficulty,

View file

@ -73,6 +73,7 @@ menu_t PLAY_TimeAttackDef = {
PLAY_TimeAttack,
0, 0,
0, 0,
0,
NULL,
2, 5,
M_DrawTimeAttack,
@ -115,6 +116,7 @@ menu_t PLAY_TAReplayDef = {
PLAY_TAReplay,
0, 0,
0, 0,
0,
NULL,
2, 5,
M_DrawTimeAttack,
@ -159,6 +161,7 @@ menu_t PLAY_TAReplayGuestDef = {
PLAY_TAReplayGuest,
0, 0,
0, 0,
0,
NULL,
2, 5,
M_DrawTimeAttack,
@ -198,6 +201,7 @@ menu_t PLAY_TAGhostsDef = {
PLAY_TAGhosts,
0, 0,
0, 0,
0,
NULL,
2, 5,
M_DrawTimeAttack,

View file

@ -37,6 +37,7 @@ menu_t PLAY_MP_OptSelectDef = {
PLAY_MP_OptSelect,
0, 0,
0, 0,
0,
"NETMD2",
-1, 1,
M_DrawMPOptSelect,

View file

@ -33,6 +33,7 @@ menu_t PLAY_MP_HostDef = {
PLAY_MP_Host,
0, 0,
0, 0,
0,
"NETMD2",
-1, 1, // 1 frame transition.... This is really just because I don't want the black fade when we press esc, hehe
M_DrawMPHost,

View file

@ -38,6 +38,7 @@ menu_t PLAY_MP_JoinIPDef = {
PLAY_MP_JoinIP,
0, 0,
0, 0,
0,
"NETMD2",
-1, 1, // 1 frame transition.... This is really just because I don't want the black fade when we press esc, hehe
M_DrawMPJoinIP,

View file

@ -17,6 +17,7 @@ menu_t PLAY_MP_RoomSelectDef = {
PLAY_MP_RoomSelect,
0, 0,
0, 0,
0,
"NETMD2",
0, 0,
M_DrawMPRoomSelect,

View file

@ -29,6 +29,7 @@ menu_t PLAY_MP_ServerBrowserDef = {
PLAY_MP_ServerBrowser,
32, 36,
0, 0,
0,
"NETMD2",
0, 0,
M_DrawMPServerBrowser,

View file

@ -4,6 +4,7 @@ target_sources(SRB2SDL2 PRIVATE
level-select.c
gametype.c
manual.c
sound-test.c
message-box.c
pause-game.c
pause-replay.c

View file

@ -20,6 +20,7 @@ menu_t PLAY_CupSelectDef = {
PLAY_CupSelect,
0, 0,
0, 0,
0,
NULL,
2, 5,
M_DrawCupSelect,

View file

@ -23,6 +23,7 @@ menu_t PLAY_LevelSelectDef = {
PLAY_LevelSelect,
0, 0,
0, 0,
0,
NULL,
2, 5,
M_DrawLevelSelect,

View file

@ -15,6 +15,9 @@ menuitem_t PAUSE_Main[] =
{IT_STRING | IT_CALL, "ADDONS", "M_ICOADD",
NULL, {.routine = M_Addons}, 0, 0},
{IT_STRING | IT_CALL, "STEREO MODE", "M_ICOSTM",
NULL, {.routine = M_SoundTest}, 0, 0},
{IT_STRING | IT_KEYHANDLER, "GAMETYPE", "M_ICOGAM",
NULL, {.routine = M_HandlePauseMenuGametype}, 0, 0},
@ -64,6 +67,7 @@ menu_t PAUSE_MainDef = {
PAUSE_Main,
0, 0,
0, 0,
0,
NULL,
1, 10, // For transition with some menus!
M_DrawPause,
@ -110,6 +114,7 @@ void M_OpenPauseMenu(void)
// By default, disable anything sensitive:
PAUSE_Main[mpause_addons].status = IT_DISABLED;
PAUSE_Main[mpause_stereo].status = IT_DISABLED;
PAUSE_Main[mpause_changegametype].status = IT_DISABLED;
PAUSE_Main[mpause_switchmap].status = IT_DISABLED;
PAUSE_Main[mpause_restartmap].status = IT_DISABLED;
@ -126,6 +131,11 @@ void M_OpenPauseMenu(void)
Dummymenuplayer_OnChange(); // Make sure the consvar is within bounds of the amount of splitscreen players we have.
if (M_SecretUnlocked(SECRET_SOUNDTEST, true))
{
PAUSE_Main[mpause_stereo].status = IT_STRING | IT_CALL;
}
if (K_CanChangeRules(false))
{
PAUSE_Main[mpause_psetup].status = IT_STRING | IT_CALL;

View file

@ -39,6 +39,7 @@ menu_t PAUSE_PlaybackMenuDef = {
PAUSE_PlaybackMenu,
BASEVIDWIDTH/2 - 88, 2,
0, 0,
MBF_UD_LR_FLIPPED,
NULL,
0, 0,
M_DrawPlaybackMenu,

View file

@ -0,0 +1,204 @@
/// \file menus/transient/sound-test.c
/// \brief Stereo Mode menu
#include "../../k_menu.h"
#include "../../s_sound.h"
static void M_SoundTestMainControl(INT32 choice)
{
(void)choice;
// Sound test exception
if (soundtest.current == NULL || soundtest.current->numtracks == 0)
{
if (cv_soundtest.value != 0)
{
S_StopSounds();
if (currentMenu->menuitems[itemOn].mvar1 == 0) // Stop
{
CV_SetValue(&cv_soundtest, 0);
}
else if (currentMenu->menuitems[itemOn].mvar1 == 1) // Play
{
S_StartSound(NULL, cv_soundtest.value);
}
}
else if (currentMenu->menuitems[itemOn].mvar1 == 1) // Play
{
soundtest.playing = true;
soundtest.autosequence = true;
S_UpdateSoundTestDef(false, false, false);
}
return;
}
if (currentMenu->menuitems[itemOn].mvar1 == 1) // Play
{
if (soundtest.paused == true)
{
S_SoundTestTogglePause();
}
else if (soundtest.playing == false)
{
S_SoundTestPlay();
}
}
else if (soundtest.playing == true)
{
if (currentMenu->menuitems[itemOn].mvar1 == 2) // Pause
{
if (soundtest.paused == false)
{
S_SoundTestTogglePause();
}
}
else // Stop
{
S_SoundTestStop();
}
}
else if (currentMenu->menuitems[itemOn].mvar1 == 0) // Stop while stopped?
{
soundtest.current = NULL;
soundtest.currenttrack = 0;
CV_SetValue(&cv_soundtest, 0);
}
}
static void M_SoundTestNextPrev(INT32 choice)
{
(void)choice;
S_UpdateSoundTestDef((currentMenu->menuitems[itemOn].mvar1 < 0), true, false);
}
static void M_SoundTestSeq(INT32 choice)
{
(void)choice;
soundtest.autosequence ^= true;
}
consvar_t *M_GetSoundTestVolumeCvar(void)
{
if (soundtest.current == NULL)
{
if (cv_soundtest.value == 0)
return NULL;
return &cv_soundvolume;
}
return &cv_digmusicvolume;
}
static void M_SoundTestVol(INT32 choice)
{
consvar_t *voltoadjust = M_GetSoundTestVolumeCvar();
if (!voltoadjust)
return;
M_ChangeCvarDirect(choice, voltoadjust);
}
static void M_SoundTestTrack(INT32 choice)
{
const UINT8 numtracks = (soundtest.current != NULL) ? soundtest.current->numtracks : 0;
if (numtracks == 1 // No cycling
|| choice == -1) // Extra
{
return;
}
// Confirm is generally treated as Up.
// Soundtest exception
if (numtracks == 0)
{
S_StopSounds();
CV_AddValue(&cv_soundtest, ((choice == 0) ? -1 : 1));
return;
}
if (choice == 0) // Down
{
soundtest.currenttrack--;
if (soundtest.currenttrack < 0)
soundtest.currenttrack = numtracks-1;
}
else //if (choice == 1) -- Up
{
soundtest.currenttrack++;
if (soundtest.currenttrack >= numtracks)
soundtest.currenttrack = 0;
}
if (soundtest.playing)
{
S_SoundTestPlay();
}
}
static boolean M_SoundTestInputs(INT32 ch)
{
(void)ch;
soundtest.justopened = false;
return false;
}
static void M_SoundTestTick(void)
{
soundtest.menutick++;
}
menuitem_t MISC_SoundTest[] =
{
{IT_STRING | IT_CALL, "Back", "STER_IC0", NULL, {.routine = M_GoBack}, 0, stereospecial_back},
{IT_SPACE, NULL, NULL, NULL, {NULL}, 11, 0},
{IT_STRING | IT_CALL, "Stop", "STER_IC1", NULL, {.routine = M_SoundTestMainControl}, 0, 0},
{IT_SPACE, NULL, NULL, NULL, {NULL}, 8, 0},
{IT_STRING | IT_CALL, "Pause", "STER_IC2", NULL, {.routine = M_SoundTestMainControl}, 2, stereospecial_pause},
{IT_STRING | IT_CALL, "Play", "STER_IC3", NULL, {.routine = M_SoundTestMainControl}, 1, stereospecial_play},
{IT_SPACE, NULL, NULL, NULL, {NULL}, 8, 0},
{IT_STRING | IT_CALL, "Prev", "STER_IC4", NULL, {.routine = M_SoundTestNextPrev}, -1, 0},
{IT_STRING | IT_CALL, "Next", "STER_IC5", NULL, {.routine = M_SoundTestNextPrev}, 1, 0},
{IT_SPACE, NULL, NULL, NULL, {NULL}, 8, 0},
{IT_STRING | IT_ARROWS, "Seq", "STER_IC6", NULL, {.routine = M_SoundTestSeq}, 0, stereospecial_seq},
{IT_SPACE, NULL, NULL, NULL, {NULL}, 0, 244},
{IT_STRING | IT_ARROWS, "Vol", NULL, NULL, {.routine = M_SoundTestVol}, 0, stereospecial_vol},
{IT_STRING | IT_ARROWS, "Track", NULL, NULL, {.routine = M_SoundTestTrack}, 0, stereospecial_track},
};
menu_t MISC_SoundTestDef = {
sizeof (MISC_SoundTest)/sizeof (menuitem_t),
&MainDef,
0,
MISC_SoundTest,
19, 140,
0, 0,
MBF_UD_LR_FLIPPED|MBF_SOUNDLESS,
".",
98, 0,
M_DrawSoundTest,
M_SoundTestTick,
NULL,
NULL,
M_SoundTestInputs,
};
void M_SoundTest(INT32 choice)
{
(void)choice;
// I reserve the right to add some sort of setup here -- toast 250323
soundtest.menutick = 0;
soundtest.justopened = true;
MISC_SoundTestDef.prevMenu = currentMenu;
M_SetupNextMenu(&MISC_SoundTestDef, false);
}

View file

@ -382,8 +382,6 @@ void P_DeleteFlickies(INT16 i)
*/
static void P_ClearSingleMapHeaderInfo(INT16 num)
{
UINT8 i = 0;
mapheaderinfo[num]->lvlttl[0] = '\0';
mapheaderinfo[num]->subttl[0] = '\0';
mapheaderinfo[num]->zonttl[0] = '\0';
@ -391,11 +389,12 @@ static void P_ClearSingleMapHeaderInfo(INT16 num)
mapheaderinfo[num]->typeoflevel = 0;
mapheaderinfo[num]->gravity = DEFAULT_GRAVITY;
mapheaderinfo[num]->keywords[0] = '\0';
for (i = 0; i < MAXMUSNAMES; i++)
mapheaderinfo[num]->musname[i][0] = 0;
mapheaderinfo[num]->musname[0][0] = 0;
mapheaderinfo[num]->musname_size = 0;
mapheaderinfo[num]->associatedmus[0][0] = 0;
mapheaderinfo[num]->associatedmus_size = 0;
mapheaderinfo[num]->mustrack = 0;
mapheaderinfo[num]->muspos = 0;
mapheaderinfo[num]->musname_size = 0;
mapheaderinfo[num]->weather = PRECIP_NONE;
snprintf(mapheaderinfo[num]->skytexture, 5, "SKY1");
mapheaderinfo[num]->skytexture[4] = 0;
@ -8599,6 +8598,9 @@ boolean P_MultiSetupWadFiles(boolean fullsetup)
if (partadd_stage < 0)
{
// possible future work: only do this if musicdefs/map headers changed
S_PopulateSoundTestSequence();
partadd_important = false;
partadd_earliestfile = UINT16_MAX;
return true;

View file

@ -803,7 +803,11 @@ void P_Ticker(boolean run)
{
// Plays the POSITION music after the camera spin
if (leveltime == introtime)
S_ChangeMusicInternal("postn", true);
S_ChangeMusicInternal(
(mapheaderinfo[gamemap-1]->positionmus[0]
? mapheaderinfo[gamemap-1]->positionmus
: "postn"
), true);
}
}

View file

@ -33,6 +33,7 @@
#include "byteptr.h"
#include "k_menu.h" // M_PlayMenuJam
#include "m_random.h" // P_RandomKey
#include "i_time.h"
#ifdef HW3SOUND
// 3D Sound Interface
@ -1356,12 +1357,415 @@ static UINT32 queue_fadeinms;
static tic_t pause_starttic;
static void S_AttemptToRestoreMusic(void)
{
switch (gamestate)
{
case GS_LEVEL:
P_RestoreMusic(&players[consoleplayer]);
break;
case GS_TITLESCREEN:
S_ChangeMusicInternal("_title", looptitle);
break;
case GS_MENU:
M_PlayMenuJam();
break;
default:
break;
}
}
/// ------------------------
/// Music Definitions
/// ------------------------
musicdef_t *musicdefstart = NULL;
struct cursongcredit cursongcredit; // Currently displayed song credit info
struct soundtest soundtest; // Sound Test (sound test)
static void S_InsertMusicAtSoundTestSequenceTail(const char *musname, UINT16 map, musicdef_t ***tail)
{
UINT8 i = 0;
musicdef_t *def = S_FindMusicDef(musname, &i);
if (def == NULL)
return;
if (def->sequence.id == soundtest.sequence.id)
return;
def->sequence.id = soundtest.sequence.id;
def->sequence.map = map;
// So what we're doing here is to avoid iterating
// for every insertion, we dereference the pointer
// to get **tail from S_PopulateSoundTestSequence,
// then dereference that to get the musicdef_t *.
// We do it this way so that soundtest.sequence.next
// can be handled natively without special cases.
// I have officially lost my MIND. ~toast 270323
*(*tail) = def;
*tail = &def->sequence.next;
}
static void S_InsertMapIntoSoundTestSequence(UINT16 map, musicdef_t ***tail)
{
UINT8 i;
if (mapheaderinfo[map]->positionmus[0])
{
S_InsertMusicAtSoundTestSequenceTail(mapheaderinfo[map]->positionmus, map, tail);
}
for (i = 0; i < mapheaderinfo[map]->musname_size; i++)
{
S_InsertMusicAtSoundTestSequenceTail(mapheaderinfo[map]->musname[i], map, tail);
}
for (i = 0; i < mapheaderinfo[map]->associatedmus_size; i++)
{
S_InsertMusicAtSoundTestSequenceTail(mapheaderinfo[map]->associatedmus[i], map, tail);
}
}
void S_PopulateSoundTestSequence(void)
{
UINT16 i;
musicdef_t **tail;
// First, increment the sequence and wipe the HEAD.
// This invalidates all existing musicdefs without us
// having to iterate through everything all the time,
// and offers a very convenient checking mechanism.
// ...preventing id 0 protects against inconsistencies
// caused by newly Calloc'd music definitions.
soundtest.sequence.id = (soundtest.sequence.id + 1) & 255;
if (soundtest.sequence.id == 0)
soundtest.sequence.id = 1;
soundtest.sequence.next = NULL;
tail = &soundtest.sequence.next;
// We iterate over all cups.
{
cupheader_t *cup;
for (cup = kartcupheaders; cup; cup = cup->next)
{
for (i = 0; i < CUPCACHE_MAX; i++)
{
if (cup->cachedlevels[i] >= nummapheaders)
continue;
if (!mapheaderinfo[cup->cachedlevels[i]])
continue;
if (mapheaderinfo[cup->cachedlevels[i]]->cup != cup)
continue;
S_InsertMapIntoSoundTestSequence(cup->cachedlevels[i], &tail);
}
}
}
// Then, we iterate over all non-cupped maps.
for (i = 0; i < nummapheaders; i++)
{
if (!mapheaderinfo[i])
continue;
if (mapheaderinfo[i]->cup != NULL)
continue;
S_InsertMapIntoSoundTestSequence(i, &tail);
}
// Finally, we insert all other musicdefstart at the head.
// It's being added to the sequence in reverse order...
// but because musicdefstart is ALSO populated in reverse,
// the reverse of the reverse is the right way around!
{
musicdef_t *def;
for (def = musicdefstart; def; def = def->next)
{
if (def->sequence.id == soundtest.sequence.id)
continue;
def->sequence.id = soundtest.sequence.id;
def->sequence.map = NEXTMAP_INVALID;
def->sequence.next = soundtest.sequence.next;
soundtest.sequence.next = def;
}
}
}
static boolean S_SoundTestDefLocked(musicdef_t *def)
{
// temporary - i'd like to find a way to conditionally hide
// specific musicdefs that don't have any map associated.
if (def->sequence.map >= nummapheaders)
return false;
// Is the level tied to SP progression?
if ((mapheaderinfo[def->sequence.map]->menuflags & LF2_FINISHNEEDED)
&& !(mapheaderinfo[def->sequence.map]->mapvisited & MV_BEATEN))
return true;
// Finally, do a full-fat map check.
return M_MapLocked(def->sequence.map+1);
}
void S_UpdateSoundTestDef(boolean reverse, boolean dotracks, boolean skipnull)
{
musicdef_t *newdef;
newdef = NULL;
if (reverse == false)
{
if (dotracks == true && soundtest.current != NULL
&& soundtest.currenttrack < soundtest.current->numtracks-1)
{
soundtest.currenttrack++;
goto updatetrackonly;
}
newdef = (soundtest.current != NULL)
? soundtest.current->sequence.next
: soundtest.sequence.next;
while (newdef != NULL && S_SoundTestDefLocked(newdef))
newdef = newdef->sequence.next;
if (newdef == NULL && skipnull == true)
{
newdef = soundtest.sequence.next;
while (newdef != NULL && S_SoundTestDefLocked(newdef))
newdef = newdef->sequence.next;
}
}
else
{
musicdef_t *def, *lastdef = NULL;
if (dotracks == true && soundtest.current != NULL
&& soundtest.currenttrack > 0)
{
soundtest.currenttrack--;
goto updatetrackonly;
}
if (soundtest.current == soundtest.sequence.next
&& skipnull == false)
{
goto updatecurrent;
}
for (def = soundtest.sequence.next; def; def = def->sequence.next)
{
if (!S_SoundTestDefLocked(def))
{
lastdef = def;
}
if (def->sequence.next != soundtest.current)
{
continue;
}
newdef = lastdef;
break;
}
}
updatecurrent:
soundtest.current = newdef;
soundtest.currenttrack =
(reverse == true && dotracks == true && newdef != NULL)
? newdef->numtracks-1
: 0;
if (newdef == NULL)
{
CV_SetValue(&cv_soundtest, 0);
}
updatetrackonly:
if (soundtest.playing == true)
{
S_SoundTestPlay();
}
}
void S_SoundTestPlay(void)
{
if (soundtest.current == NULL)
{
S_SoundTestStop();
return;
}
soundtest.privilegedrequest = true;
S_StopMusic();
soundtest.playing = true;
if (soundtest.paused == true)
{
S_SoundTestTogglePause();
}
S_ChangeMusicInternal(soundtest.current->name[soundtest.currenttrack],
!soundtest.current->basenoloop[soundtest.currenttrack]);
S_ShowMusicCredit();
soundtest.currenttime = 0;
soundtest.sequencemaxtime = S_GetMusicLength();
soundtest.sequencefadeout = 0;
if (soundtest.sequencemaxtime)
{
// Does song have default loop?
if (soundtest.current->basenoloop[soundtest.currenttrack] == false)
{
soundtest.dosequencefadeout = (soundtest.currenttrack == soundtest.current->numtracks-1);
soundtest.sequencemaxtime *= 2; // Two loops by default.
soundtest.sequencemaxtime -= S_GetMusicLoopPoint(); // Otherwise the intro is counted twice.
}
else
{
soundtest.dosequencefadeout = false;
}
// ms to TICRATE conversion
soundtest.sequencemaxtime = (TICRATE*soundtest.sequencemaxtime)/1000;
}
soundtest.privilegedrequest = false;
}
void S_SoundTestStop(void)
{
if (soundtest.playing == false)
{
return;
}
soundtest.privilegedrequest = true;
soundtest.playing = false;
soundtest.paused = false;
soundtest.autosequence = false;
S_StopMusic();
cursongcredit.def = NULL;
soundtest.currenttime = 0;
soundtest.sequencemaxtime = 0;
soundtest.sequencefadeout = 0;
soundtest.dosequencefadeout = false;
S_AttemptToRestoreMusic();
soundtest.privilegedrequest = false;
}
void S_SoundTestTogglePause(void)
{
if (soundtest.playing == false)
{
return;
}
if (soundtest.paused == true)
{
soundtest.paused = false;
S_ResumeAudio();
}
else
{
soundtest.paused = true;
S_PauseAudio();
}
}
void S_TickSoundTest(void)
{
static UINT32 storetime = 0;
UINT32 lasttime = storetime;
boolean donext = false;
storetime = I_GetTime();
if (soundtest.playing == false || soundtest.current == NULL)
{
return;
}
if (I_SongPlaying() == false)
{
S_SoundTestStop();
return;
}
if (I_SongPaused() == false)
{
soundtest.currenttime += (storetime - lasttime);
}
if (soundtest.sequencefadeout > 0)
{
if (soundtest.currenttime >= soundtest.sequencefadeout)
{
donext = true;
}
}
else if (soundtest.currenttime >= soundtest.sequencemaxtime)
{
if (soundtest.autosequence == false)
{
if (soundtest.current->basenoloop[soundtest.currenttrack] == true)
{
S_SoundTestStop();
}
return;
}
else if (soundtest.dosequencefadeout == false)
{
donext = true;
}
else
{
if (soundtest.sequencemaxtime > 0)
{
soundtest.privilegedrequest = true;
S_FadeMusic(0, 3000);
soundtest.privilegedrequest = false;
}
soundtest.sequencefadeout = soundtest.currenttime + 3*TICRATE;
}
}
if (donext == false)
{
return;
}
S_UpdateSoundTestDef(false, true, true);
}
boolean S_PlaysimMusicDisabled(void)
{
if (soundtest.privilegedrequest)
return false;
return (soundtest.playing // Ring Racers: Stereo Mode
|| demo.rewinding // Don't mess with music while rewinding!
|| demo.title); // SRB2Kart: Demos don't interrupt title screen music
}
//
// S_FindMusicDef
@ -1370,9 +1774,14 @@ struct cursongcredit cursongcredit; // Currently displayed song credit info
//
musicdef_t *S_FindMusicDef(const char *name, UINT8 *i)
{
UINT32 hash = quickncasehash (name, 6);
UINT32 hash;
musicdef_t *def;
if (!name || !name[0])
return NULL;
hash = quickncasehash (name, 6);
for (def = musicdefstart; def; def = def->next)
{
for (*i = 0; *i < def->numtracks; (*i)++)
@ -1450,6 +1859,11 @@ ReadMusicDefFields
do {
if (i >= MAXDEFTRACKS)
break;
if (value[0] == '\\')
{
def->basenoloop[i] = true;
value++;
}
STRBUFCPY(def->name[i], value);
strlwr(def->name[i]);
def->hash[i] = quickncasehash (def->name[i], 6);
@ -1635,6 +2049,7 @@ void S_InitMusicDefs(void)
UINT16 i;
for (i = 0; i < numwadfiles; i++)
S_LoadMusicDefs(i);
S_PopulateSoundTestSequence();
}
//
@ -1651,7 +2066,7 @@ void S_ShowMusicCredit(void)
char *work = NULL;
size_t len = 128, worklen;
if (!cv_songcredits.value || demo.rewinding)
if (!cv_songcredits.value || S_PlaysimMusicDisabled())
return;
if (!def) // No definitions
@ -1798,8 +2213,7 @@ UINT32 S_GetMusicLoopPoint(void)
boolean S_SetMusicPosition(UINT32 position)
{
if (demo.rewinding // Don't mess with music while rewinding!
|| demo.title) // SRB2Kart: Demos don't interrupt title screen music
if (S_PlaysimMusicDisabled())
return false;
return I_SetSongPosition(position);
@ -2005,8 +2419,7 @@ boolean S_RecallMusic(UINT16 status, boolean fromfirst)
musicstack_t *result;
musicstack_t *entry;
if (demo.rewinding // Don't mess with music while rewinding!
|| demo.title) // SRB2Kart: Demos don't interrupt title screen music
if (S_PlaysimMusicDisabled())
return false;
entry = Z_Calloc(sizeof (*result), PU_MUSIC, NULL);
@ -2243,9 +2656,7 @@ void S_ChangeMusicEx(const char *mmusic, UINT16 mflags, boolean looping, UINT32
&fadeinms
};
if (S_MusicDisabled()
|| demo.rewinding // Don't mess with music while rewinding!
|| demo.title) // SRB2Kart: Demos don't interrupt title screen music
if (S_MusicDisabled() || S_PlaysimMusicDisabled())
return;
strncpy(newmusic, mmusic, 7);
@ -2325,9 +2736,7 @@ void S_ChangeMusicSpecial (const char *mmusic)
void S_StopMusic(void)
{
if (!I_SongPlaying()
|| demo.rewinding // Don't mess with music while rewinding!
|| demo.title) // SRB2Kart: Demos don't interrupt title screen music
if (!I_SongPlaying() || S_PlaysimMusicDisabled())
return;
if (strcasecmp(music_name, mapmusname) == 0)
@ -2373,6 +2782,9 @@ void S_ResumeAudio(void)
if (S_MusicNotInFocus())
return;
if (soundtest.paused == true)
return;
if (I_SongPlaying() && I_SongPaused())
I_ResumeSong();
@ -2433,8 +2845,7 @@ void S_StopFadingMusic(void)
boolean S_FadeMusicFromVolume(UINT8 target_volume, INT16 source_volume, UINT32 ms)
{
if (demo.rewinding // Don't mess with music while rewinding!
|| demo.title) // SRB2Kart: Demos don't interrupt title screen music
if (S_PlaysimMusicDisabled())
return false;
if (source_volume < 0)
@ -2445,8 +2856,7 @@ boolean S_FadeMusicFromVolume(UINT8 target_volume, INT16 source_volume, UINT32 m
boolean S_FadeOutStopMusic(UINT32 ms)
{
if (demo.rewinding // Don't mess with music while rewinding!
|| demo.title) // SRB2Kart: Demos don't interrupt title screen music
if (S_PlaysimMusicDisabled())
return false;
return I_FadeSong(0, ms, &S_StopMusic);
@ -2628,10 +3038,7 @@ static void Command_RestartAudio_f(void)
S_StartSound(NULL, sfx_strpst);
if (Playing()) // Gotta make sure the player is in a level
P_RestoreMusic(&players[consoleplayer]);
else
S_ChangeMusicInternal("titles", looptitle);
S_AttemptToRestoreMusic();
}
static void Command_PlaySound(void)
@ -2821,18 +3228,7 @@ void GameDigiMusic_OnChange(void)
I_StartupSound(); // will return early if initialised
I_InitMusic();
if (Playing())
{
P_RestoreMusic(&players[consoleplayer]);
}
else if (gamestate == GS_TITLESCREEN)
{
S_ChangeMusicInternal("_title", looptitle);
}
else
{
M_PlayMenuJam();
}
S_AttemptToRestoreMusic();
}
else
{

View file

@ -176,11 +176,19 @@ boolean S_SpeedMusic(float speed);
#define MAXDEFTRACKS 3
struct soundtestsequence_t
{
UINT8 id;
UINT16 map;
musicdef_t *next;
};
// Music credits
struct musicdef_t
{
char name[MAXDEFTRACKS][7];
UINT32 hash[MAXDEFTRACKS];
boolean basenoloop[MAXDEFTRACKS];
UINT8 numtracks;
char *title;
char *author;
@ -189,6 +197,7 @@ struct musicdef_t
int volume;
int debug_volume;
musicdef_t *next;
soundtestsequence_t sequence;
};
extern struct cursongcredit
@ -201,6 +210,36 @@ extern struct cursongcredit
fixed_t old_x;
} cursongcredit;
extern struct soundtest
{
boolean playing; // Music is playing?
boolean paused; // System paused?
boolean justopened; // Menu visual assist
boolean privilegedrequest; // Overrides S_PlaysimMusicDisabled w/o changing every function signature
INT32 menutick; // Menu visual timer
musicdef_t *current; // Current selected music definition
SINT8 currenttrack; // Current selected music track for definition
UINT32 currenttime; // Current music playing time
soundtestsequence_t sequence; // Sequence head
boolean autosequence; // In auto sequence mode?
boolean dosequencefadeout; // Fade out when reaching the end?
UINT32 sequencemaxtime; // Maximum playing time for current music
UINT32 sequencefadeout; // auto sequence fadeout
} soundtest;
void S_PopulateSoundTestSequence(void);
void S_UpdateSoundTestDef(boolean reverse, boolean dotracks, boolean skipnull);
void S_SoundTestPlay(void);
void S_SoundTestStop(void);
void S_SoundTestTogglePause(void);
void S_TickSoundTest(void);
boolean S_PlaysimMusicDisabled(void);
extern musicdef_t *musicdefstart;
void S_LoadMusicDefs(UINT16 wadnum);

View file

@ -388,6 +388,7 @@ TYPEDEF (listener_t);
TYPEDEF (channel_t);
TYPEDEF (caption_t);
TYPEDEF (musicdef_t);
TYPEDEF (soundtestsequence_t);
TYPEDEF (musicstack_t);
// screen.h