From a0fa45bcec8626d9b71555df5860ec488b065b8c Mon Sep 17 00:00:00 2001 From: toaster Date: Sat, 25 Mar 2023 22:16:58 +0000 Subject: [PATCH 01/29] S_PlaysimMusicDisabled Simplifies/unifies conditions that except regular music play other sections of the game can modify --- src/s_sound.c | 27 ++++++++++++--------------- src/s_sound.h | 2 ++ 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/src/s_sound.c b/src/s_sound.c index 1fa8b1c45..79dba06dc 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -1360,6 +1360,11 @@ static tic_t pause_starttic; musicdef_t *musicdefstart = NULL; struct cursongcredit cursongcredit; // Currently displayed song credit info +boolean S_PlaysimMusicDisabled(void) +{ + return (demo.rewinding // Don't mess with music while rewinding! + || demo.title); // SRB2Kart: Demos don't interrupt title screen music +} // // S_FindMusicDef @@ -1649,7 +1654,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 @@ -1796,8 +1801,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); @@ -2003,8 +2007,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); @@ -2241,9 +2244,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); @@ -2323,9 +2324,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) @@ -2431,8 +2430,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) @@ -2443,8 +2441,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); diff --git a/src/s_sound.h b/src/s_sound.h index c9a02f4df..6a02053f4 100644 --- a/src/s_sound.h +++ b/src/s_sound.h @@ -200,6 +200,8 @@ extern struct cursongcredit fixed_t old_x; } cursongcredit; +boolean S_PlaysimMusicDisabled(void); + extern musicdef_t *musicdefstart; void S_LoadMusicDefs(UINT16 wadnum); From 42cc95f6edcf7d10573945f177337005dcc2288a Mon Sep 17 00:00:00 2001 From: toaster Date: Sat, 25 Mar 2023 22:39:07 +0000 Subject: [PATCH 02/29] menubehaviourflags_t / (menu_t).behaviourflags - MBF_UD_LR_FLIPPED - Genericisation of the control flip for PAUSE_PlaybackMenuDef - MBF_SOUNDLESS - Do not create sound for default menu actions --- src/k_menu.h | 11 +++++++++++ src/k_menufunc.c | 19 +++++++++++-------- src/menus/extras-1.c | 1 + src/menus/extras-addons.c | 1 + src/menus/extras-challenges.c | 2 ++ src/menus/extras-replay-hut.c | 2 ++ src/menus/main-profile-select.c | 1 + src/menus/options-1.c | 1 + src/menus/options-data-1.c | 1 + src/menus/options-data-addons.c | 1 + src/menus/options-data-discord.c | 1 + src/menus/options-data-erase-1.c | 1 + src/menus/options-data-erase-profile.c | 1 + src/menus/options-data-replays.c | 1 + src/menus/options-data-screenshots.c | 1 + src/menus/options-gameplay-1.c | 1 + src/menus/options-gameplay-item-toggles.c | 1 + src/menus/options-hud-1.c | 1 + src/menus/options-hud-online.c | 1 + src/menus/options-profiles-1.c | 1 + src/menus/options-profiles-edit-1.c | 1 + src/menus/options-profiles-edit-controls.c | 1 + src/menus/options-server-1.c | 1 + src/menus/options-server-advanced.c | 1 + src/menus/options-sound.c | 1 + src/menus/options-video-1.c | 1 + src/menus/options-video-gl.c | 1 + src/menus/options-video-modes.c | 1 + src/menus/play-char-select.c | 1 + src/menus/play-local-race-difficulty.c | 1 + src/menus/play-local-race-time-attack.c | 4 ++++ src/menus/play-online-1.c | 1 + src/menus/play-online-host.c | 1 + src/menus/play-online-join-ip.c | 1 + src/menus/play-online-room-select.c | 1 + src/menus/play-online-server-browser.c | 1 + src/menus/transient/cup-select.c | 1 + src/menus/transient/level-select.c | 1 + src/menus/transient/pause-game.c | 1 + src/menus/transient/pause-replay.c | 1 + 40 files changed, 65 insertions(+), 8 deletions(-) diff --git a/src/k_menu.h b/src/k_menu.h index cff331600..bbde63198 100644 --- a/src/k_menu.h +++ b/src/k_menu.h @@ -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 @@ -1204,6 +1211,8 @@ boolean M_StatisticsInputs(INT32 ch); 0,\ source,\ x, y,\ + 0, 0,\ + 0,\ NULL,\ 0, 0,\ M_DrawGenericMenu,\ @@ -1222,6 +1231,7 @@ boolean M_StatisticsInputs(INT32 ch); source,\ 0, 0,\ 0, 0,\ + 0,\ NULL,\ 1, 5,\ M_DrawKartGamemodeMenu,\ @@ -1239,6 +1249,7 @@ boolean M_StatisticsInputs(INT32 ch); source,\ 0, 0,\ 0, 0,\ + 0,\ "EXTRAS",\ 1, 5,\ M_DrawImageDef,\ diff --git a/src/k_menufunc.c b/src/k_menufunc.c index 2ed924289..608cf8a08 100644 --- a/src/k_menufunc.c +++ b/src/k_menufunc.c @@ -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); diff --git a/src/menus/extras-1.c b/src/menus/extras-1.c index 2ed90301a..fe6f9e750 100644 --- a/src/menus/extras-1.c +++ b/src/menus/extras-1.c @@ -32,6 +32,7 @@ menu_t EXTRAS_MainDef = { EXTRAS_Main, 0, 0, 0, 0, + 0, "EXTRAS", 2, 5, M_DrawExtras, diff --git a/src/menus/extras-addons.c b/src/menus/extras-addons.c index a63c35e7f..868ba4cd4 100644 --- a/src/menus/extras-addons.c +++ b/src/menus/extras-addons.c @@ -23,6 +23,7 @@ menu_t MISC_AddonsDef = { MISC_AddonsMenu, 50, 28, 0, 0, + 0, "EXTRAS", 0, 0, M_DrawAddons, diff --git a/src/menus/extras-challenges.c b/src/menus/extras-challenges.c index c5cda4bc8..642067e83 100644 --- a/src/menus/extras-challenges.c +++ b/src/menus/extras-challenges.c @@ -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, diff --git a/src/menus/extras-replay-hut.c b/src/menus/extras-replay-hut.c index 2dbf2c86a..881304719 100644 --- a/src/menus/extras-replay-hut.c +++ b/src/menus/extras-replay-hut.c @@ -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, diff --git a/src/menus/main-profile-select.c b/src/menus/main-profile-select.c index e070e2b5b..13b840f9a 100644 --- a/src/menus/main-profile-select.c +++ b/src/menus/main-profile-select.c @@ -15,6 +15,7 @@ menu_t MAIN_ProfilesDef = { MAIN_Profiles, 32, 80, SKINCOLOR_ULTRAMARINE, 0, + 0, NULL, 2, 5, M_DrawProfileSelect, diff --git a/src/menus/options-1.c b/src/menus/options-1.c index bc55f41e6..6d91ab224 100644 --- a/src/menus/options-1.c +++ b/src/menus/options-1.c @@ -43,6 +43,7 @@ menu_t OPTIONS_MainDef = { OPTIONS_Main, 0, 0, SKINCOLOR_SLATE, 0, + 0, NULL, 2, 5, M_DrawOptions, diff --git a/src/menus/options-data-1.c b/src/menus/options-data-1.c index 632da7977..c0bc72468 100644 --- a/src/menus/options-data-1.c +++ b/src/menus/options-data-1.c @@ -36,6 +36,7 @@ menu_t OPTIONS_DataDef = { OPTIONS_Data, 48, 80, SKINCOLOR_BLUEBERRY, 0, + 0, NULL, 2, 5, M_DrawGenericOptions, diff --git a/src/menus/options-data-addons.c b/src/menus/options-data-addons.c index a8ea39ecb..4d7a35e14 100644 --- a/src/menus/options-data-addons.c +++ b/src/menus/options-data-addons.c @@ -37,6 +37,7 @@ menu_t OPTIONS_DataAddonDef = { OPTIONS_DataAddon, 48, 80, SKINCOLOR_BLUEBERRY, 0, + 0, NULL, 2, 5, M_DrawGenericOptions, diff --git a/src/menus/options-data-discord.c b/src/menus/options-data-discord.c index 5e5518c51..45cb9846d 100644 --- a/src/menus/options-data-discord.c +++ b/src/menus/options-data-discord.c @@ -33,6 +33,7 @@ menu_t OPTIONS_DataDiscordDef = { OPTIONS_DataDiscord, 48, 80, SKINCOLOR_BLUEBERRY, 0, + 0, NULL, 2, 5, M_DrawGenericOptions, diff --git a/src/menus/options-data-erase-1.c b/src/menus/options-data-erase-1.c index faf893d32..57869c561 100644 --- a/src/menus/options-data-erase-1.c +++ b/src/menus/options-data-erase-1.c @@ -40,6 +40,7 @@ menu_t OPTIONS_DataEraseDef = { OPTIONS_DataErase, 48, 80, SKINCOLOR_BLACK, 0, + 0, "SHWDN2", // Danger. 2, 5, M_DrawGenericOptions, diff --git a/src/menus/options-data-erase-profile.c b/src/menus/options-data-erase-profile.c index 378a3471d..090f2d60e 100644 --- a/src/menus/options-data-erase-profile.c +++ b/src/menus/options-data-erase-profile.c @@ -17,6 +17,7 @@ menu_t OPTIONS_DataProfileEraseDef = { OPTIONS_DataProfileErase, 48, 80, SKINCOLOR_BLACK, 0, + 0, "SHWDN2", // Danger. 2, 5, M_DrawProfileErase, diff --git a/src/menus/options-data-replays.c b/src/menus/options-data-replays.c index 20e3aa8a3..13e95779c 100644 --- a/src/menus/options-data-replays.c +++ b/src/menus/options-data-replays.c @@ -19,6 +19,7 @@ menu_t OPTIONS_DataReplayDef = { OPTIONS_DataReplay, 48, 80, SKINCOLOR_BLUEBERRY, 0, + 0, NULL, 2, 5, M_DrawGenericOptions, diff --git a/src/menus/options-data-screenshots.c b/src/menus/options-data-screenshots.c index d67c2dc5e..0d24e9662 100644 --- a/src/menus/options-data-screenshots.c +++ b/src/menus/options-data-screenshots.c @@ -35,6 +35,7 @@ menu_t OPTIONS_DataScreenshotDef = { OPTIONS_DataScreenshot, 48, 80, SKINCOLOR_BLUEBERRY, 0, + 0, NULL, 2, 5, M_DrawGenericOptions, diff --git a/src/menus/options-gameplay-1.c b/src/menus/options-gameplay-1.c index fc528258b..d6207d8df 100644 --- a/src/menus/options-gameplay-1.c +++ b/src/menus/options-gameplay-1.c @@ -51,6 +51,7 @@ menu_t OPTIONS_GameplayDef = { OPTIONS_Gameplay, 48, 80, SKINCOLOR_SCARLET, 0, + 0, NULL, 2, 5, M_DrawGenericOptions, diff --git a/src/menus/options-gameplay-item-toggles.c b/src/menus/options-gameplay-item-toggles.c index 0a5cf9ba5..fd4bc5818 100644 --- a/src/menus/options-gameplay-item-toggles.c +++ b/src/menus/options-gameplay-item-toggles.c @@ -55,6 +55,7 @@ menu_t OPTIONS_GameplayItemsDef = { OPTIONS_GameplayItems, 14, 40, SKINCOLOR_SCARLET, 0, + 0, NULL, 2, 5, M_DrawItemToggles, diff --git a/src/menus/options-hud-1.c b/src/menus/options-hud-1.c index 33f660657..54bb4449c 100644 --- a/src/menus/options-hud-1.c +++ b/src/menus/options-hud-1.c @@ -48,6 +48,7 @@ menu_t OPTIONS_HUDDef = { OPTIONS_HUD, 48, 80, SKINCOLOR_SUNSLAM, 0, + 0, NULL, 2, 5, M_DrawGenericOptions, diff --git a/src/menus/options-hud-online.c b/src/menus/options-hud-online.c index 3a731883d..3b2b7defa 100644 --- a/src/menus/options-hud-online.c +++ b/src/menus/options-hud-online.c @@ -45,6 +45,7 @@ menu_t OPTIONS_HUDOnlineDef = { OPTIONS_HUDOnline, 48, 80, SKINCOLOR_SUNSLAM, 0, + 0, NULL, 2, 5, M_DrawGenericOptions, diff --git a/src/menus/options-profiles-1.c b/src/menus/options-profiles-1.c index 18a0316bc..17d4c241b 100644 --- a/src/menus/options-profiles-1.c +++ b/src/menus/options-profiles-1.c @@ -17,6 +17,7 @@ menu_t OPTIONS_ProfilesDef = { OPTIONS_Profiles, 32, 80, SKINCOLOR_ULTRAMARINE, 0, + 0, NULL, 2, 5, M_DrawProfileSelect, diff --git a/src/menus/options-profiles-edit-1.c b/src/menus/options-profiles-edit-1.c index 99caa532d..b1ed78f98 100644 --- a/src/menus/options-profiles-edit-1.c +++ b/src/menus/options-profiles-edit-1.c @@ -29,6 +29,7 @@ menu_t OPTIONS_EditProfileDef = { OPTIONS_EditProfile, 32, 80, SKINCOLOR_ULTRAMARINE, 0, + 0, NULL, 2, 5, M_DrawEditProfile, diff --git a/src/menus/options-profiles-edit-controls.c b/src/menus/options-profiles-edit-controls.c index 13633deed..779fc625c 100644 --- a/src/menus/options-profiles-edit-controls.c +++ b/src/menus/options-profiles-edit-controls.c @@ -103,6 +103,7 @@ menu_t OPTIONS_ProfileControlsDef = { OPTIONS_ProfileControls, 32, 80, SKINCOLOR_ULTRAMARINE, 0, + 0, NULL, 3, 5, M_DrawProfileControls, diff --git a/src/menus/options-server-1.c b/src/menus/options-server-1.c index 4e793d3b5..3ee92e38f 100644 --- a/src/menus/options-server-1.c +++ b/src/menus/options-server-1.c @@ -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, diff --git a/src/menus/options-server-advanced.c b/src/menus/options-server-advanced.c index 55fca8043..6af9c3cd9 100644 --- a/src/menus/options-server-advanced.c +++ b/src/menus/options-server-advanced.c @@ -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, diff --git a/src/menus/options-sound.c b/src/menus/options-sound.c index 027c8448f..21298e1ed 100644 --- a/src/menus/options-sound.c +++ b/src/menus/options-sound.c @@ -57,6 +57,7 @@ menu_t OPTIONS_SoundDef = { OPTIONS_Sound, 48, 80, SKINCOLOR_THUNDER, 0, + 0, NULL, 2, 5, M_DrawGenericOptions, diff --git a/src/menus/options-video-1.c b/src/menus/options-video-1.c index 4447531cf..35d937da8 100644 --- a/src/menus/options-video-1.c +++ b/src/menus/options-video-1.c @@ -59,6 +59,7 @@ menu_t OPTIONS_VideoDef = { OPTIONS_Video, 32, 80, SKINCOLOR_PLAGUE, 0, + 0, NULL, 2, 5, M_DrawGenericOptions, diff --git a/src/menus/options-video-gl.c b/src/menus/options-video-gl.c index 2fabeaccc..bb91244f0 100644 --- a/src/menus/options-video-gl.c +++ b/src/menus/options-video-gl.c @@ -51,6 +51,7 @@ menu_t OPTIONS_VideoOGLDef = { OPTIONS_VideoOGL, 32, 80, SKINCOLOR_PLAGUE, 0, + 0, NULL, 2, 5, M_DrawGenericOptions, diff --git a/src/menus/options-video-modes.c b/src/menus/options-video-modes.c index 872e23384..056fc2a10 100644 --- a/src/menus/options-video-modes.c +++ b/src/menus/options-video-modes.c @@ -19,6 +19,7 @@ menu_t OPTIONS_VideoModesDef = { OPTIONS_VideoModes, 48, 80, SKINCOLOR_PLAGUE, 0, + 0, NULL, 2, 5, M_DrawVideoModes, diff --git a/src/menus/play-char-select.c b/src/menus/play-char-select.c index 8c0d36601..35e918a65 100644 --- a/src/menus/play-char-select.c +++ b/src/menus/play-char-select.c @@ -19,6 +19,7 @@ menu_t PLAY_CharSelectDef = { PLAY_CharSelect, 0, 0, 0, 0, + 0, NULL, 0, 0, M_DrawCharacterSelect, diff --git a/src/menus/play-local-race-difficulty.c b/src/menus/play-local-race-difficulty.c index db9704be2..600176816 100644 --- a/src/menus/play-local-race-difficulty.c +++ b/src/menus/play-local-race-difficulty.c @@ -39,6 +39,7 @@ menu_t PLAY_RaceDifficultyDef = { PLAY_RaceDifficulty, 0, 0, 0, 0, + 0, NULL, 1, 5, M_DrawRaceDifficulty, diff --git a/src/menus/play-local-race-time-attack.c b/src/menus/play-local-race-time-attack.c index 4c51a2a6c..fac09dcc0 100644 --- a/src/menus/play-local-race-time-attack.c +++ b/src/menus/play-local-race-time-attack.c @@ -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, diff --git a/src/menus/play-online-1.c b/src/menus/play-online-1.c index e146926b1..ed4ef704f 100644 --- a/src/menus/play-online-1.c +++ b/src/menus/play-online-1.c @@ -37,6 +37,7 @@ menu_t PLAY_MP_OptSelectDef = { PLAY_MP_OptSelect, 0, 0, 0, 0, + 0, "NETMD2", -1, 1, M_DrawMPOptSelect, diff --git a/src/menus/play-online-host.c b/src/menus/play-online-host.c index 319cda9e3..95ce0660e 100644 --- a/src/menus/play-online-host.c +++ b/src/menus/play-online-host.c @@ -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, diff --git a/src/menus/play-online-join-ip.c b/src/menus/play-online-join-ip.c index bd72a1ffb..6d26b85cb 100644 --- a/src/menus/play-online-join-ip.c +++ b/src/menus/play-online-join-ip.c @@ -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, diff --git a/src/menus/play-online-room-select.c b/src/menus/play-online-room-select.c index b1364f020..666b7c987 100644 --- a/src/menus/play-online-room-select.c +++ b/src/menus/play-online-room-select.c @@ -17,6 +17,7 @@ menu_t PLAY_MP_RoomSelectDef = { PLAY_MP_RoomSelect, 0, 0, 0, 0, + 0, "NETMD2", 0, 0, M_DrawMPRoomSelect, diff --git a/src/menus/play-online-server-browser.c b/src/menus/play-online-server-browser.c index 393a2ae28..795febc0b 100644 --- a/src/menus/play-online-server-browser.c +++ b/src/menus/play-online-server-browser.c @@ -29,6 +29,7 @@ menu_t PLAY_MP_ServerBrowserDef = { PLAY_MP_ServerBrowser, 32, 36, 0, 0, + 0, "NETMD2", 0, 0, M_DrawMPServerBrowser, diff --git a/src/menus/transient/cup-select.c b/src/menus/transient/cup-select.c index cca546f9e..f4f97ed29 100644 --- a/src/menus/transient/cup-select.c +++ b/src/menus/transient/cup-select.c @@ -20,6 +20,7 @@ menu_t PLAY_CupSelectDef = { PLAY_CupSelect, 0, 0, 0, 0, + 0, NULL, 2, 5, M_DrawCupSelect, diff --git a/src/menus/transient/level-select.c b/src/menus/transient/level-select.c index 11a62e944..234d6d539 100644 --- a/src/menus/transient/level-select.c +++ b/src/menus/transient/level-select.c @@ -23,6 +23,7 @@ menu_t PLAY_LevelSelectDef = { PLAY_LevelSelect, 0, 0, 0, 0, + 0, NULL, 2, 5, M_DrawLevelSelect, diff --git a/src/menus/transient/pause-game.c b/src/menus/transient/pause-game.c index ff6c5c3b4..941673ad4 100644 --- a/src/menus/transient/pause-game.c +++ b/src/menus/transient/pause-game.c @@ -64,6 +64,7 @@ menu_t PAUSE_MainDef = { PAUSE_Main, 0, 0, 0, 0, + 0, NULL, 1, 10, // For transition with some menus! M_DrawPause, diff --git a/src/menus/transient/pause-replay.c b/src/menus/transient/pause-replay.c index 5a7c45826..b1a1353a3 100644 --- a/src/menus/transient/pause-replay.c +++ b/src/menus/transient/pause-replay.c @@ -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, From afff038e34173dae5aba8a99730540a7ec13f534 Mon Sep 17 00:00:00 2001 From: toaster Date: Sat, 25 Mar 2023 22:43:54 +0000 Subject: [PATCH 03/29] s_sound.c: Only call P_RestoreMusic in GS_LEVEL This function isn't supposed to be called outside of it --- src/s_sound.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/s_sound.c b/src/s_sound.c index 79dba06dc..91718ad91 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -2623,10 +2623,18 @@ static void Command_RestartAudio_f(void) S_StartSound(NULL, sfx_strpst); - if (Playing()) // Gotta make sure the player is in a level + if (gamestate == GS_LEVEL) // Gotta make sure the player is in a level + { P_RestoreMusic(&players[consoleplayer]); + } + else if (gamestate == GS_TITLESCREEN) + { + S_ChangeMusicInternal("_title", looptitle); + } else - S_ChangeMusicInternal("titles", looptitle); + { + M_PlayMenuJam(); + } } static void Command_PlaySound(void) @@ -2726,7 +2734,7 @@ void GameDigiMusic_OnChange(void) I_StartupSound(); // will return early if initialised I_InitMusic(); - if (Playing()) + if (gamestate == GS_LEVEL) { P_RestoreMusic(&players[consoleplayer]); } From 8f592c196fb334e7fa05d7f71c0fa64caada7bee Mon Sep 17 00:00:00 2001 From: toaster Date: Sat, 25 Mar 2023 23:37:07 +0000 Subject: [PATCH 04/29] Stereo mode - Minimum viable implementation - New horizontal menu - FUTURE WORK: visuals are extremely basic - Accessible from both Extras and in-game Pause if SECRET_SOUNDTEST is unlocked - Rather than the Shadow-the-Hedgehog style free select of SRB2's Sound Test, it's a Best Of The Hacks And Fan Music Sega CD player. - Back - Exit menu - Stop - Stops Stereo music entirely - Pause - Pauses Stereo music without losing place in sequence - FUTURE WORK: This should probably just pause the actual player ala minimised viewport - Play - Begins Stereo music on non-NULL musicdef entry - Track - For NULL soundtest entry: - Switches between sfx - For musicdefs with multiple tracks: - Switches between them - Prev and Next - Changes musicdef entry - FUTURE WORK: This is extremely naive and doesn't respect the following - Cup order - Unlocks - Overrides all game-requested music changes when in Play or Pause mode - This makes it an actual fun in-game feature as a menuification of the `tunes` command, not just a pure novelty. --- src/k_menu.h | 7 ++ src/k_menudraw.c | 51 ++++++++++ src/k_menufunc.c | 2 +- src/menus/extras-1.c | 26 +++++- src/menus/transient/CMakeLists.txt | 1 + src/menus/transient/pause-game.c | 9 ++ src/menus/transient/sound-test.c | 145 +++++++++++++++++++++++++++++ src/s_sound.c | 101 +++++++++++++++++++- src/s_sound.h | 12 +++ 9 files changed, 351 insertions(+), 3 deletions(-) create mode 100644 src/menus/transient/sound-test.c diff --git a/src/k_menu.h b/src/k_menu.h index bbde63198..55394c5d3 100644 --- a/src/k_menu.h +++ b/src/k_menu.h @@ -426,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, @@ -1203,6 +1207,9 @@ void M_Statistics(INT32 choice); void M_DrawStatistics(void); boolean M_StatisticsInputs(INT32 ch); +void M_SoundTest(INT32 choice); +void M_DrawSoundTest(void); + // These defines make it a little easier to make menus #define DEFAULTMENUSTYLE(source, prev, x, y)\ {\ diff --git a/src/k_menudraw.c b/src/k_menudraw.c index 39144a6d8..2be547a62 100644 --- a/src/k_menudraw.c +++ b/src/k_menudraw.c @@ -5925,3 +5925,54 @@ void M_DrawStatistics(void) } #undef STATSSTEP + +void M_DrawSoundTest(void) +{ + INT32 x = currentMenu->x - menutransition.tics*48, y, i, w, cursorx = 0; + + if (gamestate == GS_MENU) + { + patch_t *bg = W_CachePatchName("M_XTRABG", PU_CACHE); + V_DrawFixedPatch(0, 0, FRACUNIT, 0, bg, NULL); + } + + y = 50; + + if (soundtest.current != NULL) + { + V_DrawThinString(x, y, (soundtest.playing ? highlightflags : 0)|V_ALLOWLOWERCASE|V_6WIDTHSPACE, soundtest.current->title); + V_DrawThinString(x, (y += 10), V_ALLOWLOWERCASE|V_6WIDTHSPACE, va("%d", 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"; + V_DrawThinString(x, y, V_ALLOWLOWERCASE|V_6WIDTHSPACE, sfxstr); + V_DrawThinString(x, (y += 10), V_ALLOWLOWERCASE|V_6WIDTHSPACE, va("%d", cv_soundtest.value)); + } + + y = currentMenu->y; + + for (i = 0; i < currentMenu->numitems; i++) + { + w = V_ThinStringWidth(currentMenu->menuitems[i].text, V_6WIDTHSPACE); + if (i == itemOn) + { + cursorx = x + w/2; + V_DrawThinString(x, y, V_6WIDTHSPACE|highlightflags, currentMenu->menuitems[i].text); + } + else + { + V_DrawThinString(x, y, V_6WIDTHSPACE, currentMenu->menuitems[i].text); + } + x += w + 8; + } + + V_DrawCharacter(cursorx - 4, currentMenu->y - 8 - (skullAnimCounter/5), + '\x1B' | V_SNAPTOTOP|highlightflags, false); // up arrow +} diff --git a/src/k_menufunc.c b/src/k_menufunc.c index 608cf8a08..1915dfa5b 100644 --- a/src/k_menufunc.c +++ b/src/k_menufunc.c @@ -382,7 +382,7 @@ void M_PlayMenuJam(void) return; } - if (Playing()) + if (Playing() || soundtest.playing) return; if (refMenu != NULL && refMenu->music != NULL) diff --git a/src/menus/extras-1.c b/src/menus/extras-1.c index fe6f9e750..e8ef11896 100644 --- a/src/menus/extras-1.c +++ b/src/menus/extras-1.c @@ -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 @@ -49,6 +52,8 @@ struct extrasmenu_s extrasmenu; void M_InitExtras(INT32 choice) { + UINT32 maxvalid = 2; + (void)choice; extrasmenu.ticker = 0; @@ -82,6 +87,7 @@ void M_InitExtras(INT32 choice) 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!"; + maxvalid = 3; } else { @@ -89,7 +95,25 @@ void M_InitExtras(INT32 choice) EXTRAS_Main[3].text = EXTRAS_Main[3].tooltip = "???"; if (EXTRAS_MainDef.lastOn == 3) { - EXTRAS_MainDef.lastOn = 2; + EXTRAS_MainDef.lastOn = maxvalid; + } + } + + // Stereo Mode + if (M_SecretUnlocked(SECRET_SOUNDTEST, true)) + { + EXTRAS_Main[4].status = IT_STRING | IT_CALL; + EXTRAS_Main[4].text = "Stereo Mode"; + EXTRAS_Main[4].tooltip = "You can listen to your favourite tunes here!"; + maxvalid = 4; + } + else + { + EXTRAS_Main[4].status = IT_STRING | IT_TRANSTEXT; + EXTRAS_Main[4].text = EXTRAS_Main[4].tooltip = "???"; + if (EXTRAS_MainDef.lastOn == 4) + { + EXTRAS_MainDef.lastOn = maxvalid; } } diff --git a/src/menus/transient/CMakeLists.txt b/src/menus/transient/CMakeLists.txt index bea478d5f..a1d0cd1c6 100644 --- a/src/menus/transient/CMakeLists.txt +++ b/src/menus/transient/CMakeLists.txt @@ -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 diff --git a/src/menus/transient/pause-game.c b/src/menus/transient/pause-game.c index 941673ad4..f6ad377e0 100644 --- a/src/menus/transient/pause-game.c +++ b/src/menus/transient/pause-game.c @@ -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}, @@ -111,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; @@ -127,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; diff --git a/src/menus/transient/sound-test.c b/src/menus/transient/sound-test.c new file mode 100644 index 000000000..946ac6aaf --- /dev/null +++ b/src/menus/transient/sound-test.c @@ -0,0 +1,145 @@ +/// \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 (currentMenu->menuitems[itemOn].mvar1 == 1) // Play + { + soundtest.playing = true; + //soundtest.sequence = true; + S_UpdateSoundTestDef(false, false); + } + else if (cv_soundtest.value != 0) + { + S_StopSounds(); + + if (currentMenu->menuitems[itemOn].mvar1 == 0) // Stop + { + CV_SetValue(&cv_soundtest, 0); + } + } + + return; + } + + if (currentMenu->menuitems[itemOn].mvar1 == 1) // Play + { + S_SoundTestPlay(); + } + else if (soundtest.playing == true) + { + S_SoundTestStop((currentMenu->menuitems[itemOn].mvar1 == 2)); + } +} + +static void M_SoundTestNextPrev(INT32 choice) +{ + (void)choice; + + S_UpdateSoundTestDef((currentMenu->menuitems[itemOn].mvar1 < 0), false); +} + +static void M_SoundTestTrack(INT32 choice) +{ + const UINT8 numtracks = (soundtest.current != NULL) ? soundtest.current->numtracks : 0; + + if (numtracks == 1) + { + return; + } + + // Soundtest exception + if (numtracks == 0) + { + S_StopSounds(); + + if (choice == -1) // Extra + { + if (cv_soundtest.value != 0) + CV_SetValue(&cv_soundtest, 0); + } + else if (choice == 2) // Confirm + { + if (cv_soundtest.value != 0) + S_StartSound(NULL, cv_soundtest.value); + } + else // Up or Down + { + CV_AddValue(&cv_soundtest, ((choice == 0) ? -1 : 1)); + } + + return; + } + + if (choice == -1) // Extra + { + soundtest.currenttrack = 0; + } + else + { + // Confirm resets the current instance + 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(); + } +} + +menuitem_t MISC_SoundTest[] = +{ + {IT_STRING | IT_CALL, "Back", NULL, NULL, {.routine = M_GoBack}, 0, 0}, + {IT_STRING | IT_CALL, "Stop", NULL, NULL, {.routine = M_SoundTestMainControl}, 0, 0}, + {IT_STRING | IT_CALL, "Pause", NULL, NULL, {.routine = M_SoundTestMainControl}, 2, 0}, + {IT_STRING | IT_CALL, "Play", NULL, NULL, {.routine = M_SoundTestMainControl}, 1, 0}, + {IT_STRING | IT_ARROWS, "Track", NULL, NULL, {.routine = M_SoundTestTrack}, 0, 0}, + {IT_STRING | IT_CALL, "Prev", NULL, NULL, {.routine = M_SoundTestNextPrev}, -1, 0}, + {IT_STRING | IT_CALL, "Next", NULL, NULL, {.routine = M_SoundTestNextPrev}, 1, 0}, +}; + +menu_t MISC_SoundTestDef = { + sizeof (MISC_SoundTest)/sizeof (menuitem_t), + &MainDef, + 0, + MISC_SoundTest, + 42, BASEVIDHEIGHT/2, + 0, 0, + MBF_UD_LR_FLIPPED|MBF_SOUNDLESS, + ".", + 98, 0, + M_DrawSoundTest, + NULL, + NULL, + NULL, + NULL, +}; + +void M_SoundTest(INT32 choice) +{ + (void)choice; + + // I reserve the right to add some sort of setup here -- toast 250323 + + MISC_SoundTestDef.prevMenu = currentMenu; + M_SetupNextMenu(&MISC_SoundTestDef, false); +} diff --git a/src/s_sound.c b/src/s_sound.c index 91718ad91..5c5483b01 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -1360,9 +1360,108 @@ static tic_t pause_starttic; musicdef_t *musicdefstart = NULL; struct cursongcredit cursongcredit; // Currently displayed song credit info +struct soundtest soundtest; // Sound Test (sound test) + +void S_UpdateSoundTestDef(boolean reverse, boolean skipnull) +{ + musicdef_t *newdef; + + // Naive implementation for now. + + newdef = (soundtest.current != NULL + && (skipnull == false || soundtest.current->next != NULL)) + ? soundtest.current->next + : musicdefstart; + + if (reverse == false) + { + // Due to how musicdefs are populated, we have to traverse backwards when attempting forwards. + musicdef_t *def; + + if (soundtest.current == musicdefstart) + { + newdef = NULL; + if (skipnull == false) + { + goto conclusion; + } + } + + for (def = musicdefstart; def; def = def->next) + { + if (def->next != soundtest.current) + continue; + + newdef = def; + break; + } + } + +conclusion: + soundtest.current = newdef; + soundtest.currenttrack = 0; + + if (soundtest.playing == true) + { + if (newdef == NULL) + { + S_SoundTestStop(false); + } + else + { + S_SoundTestPlay(); + } + } +} + +void S_SoundTestPlay(void) +{ + soundtest.privilegedrequest = true; + + S_StopMusic(); + + soundtest.playing = true; + + S_ChangeMusicInternal(soundtest.current->name[soundtest.currenttrack], true); + S_ShowMusicCredit(); + + soundtest.privilegedrequest = false; +} + +void S_SoundTestStop(boolean pause) +{ + if (soundtest.playing == false) + { + return; + } + + soundtest.privilegedrequest = true; + + S_StopMusic(); + cursongcredit.def = NULL; + + if (pause == false) + { + soundtest.playing = false; + soundtest.current = NULL; + soundtest.currenttrack = 0; + + if (gamestate == GS_LEVEL) + { + P_RestoreMusic(&players[consoleplayer]); + } + } + + soundtest.privilegedrequest = false; +} + boolean S_PlaysimMusicDisabled(void) { - return (demo.rewinding // Don't mess with music while rewinding! + 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 } diff --git a/src/s_sound.h b/src/s_sound.h index 6a02053f4..3936e83ae 100644 --- a/src/s_sound.h +++ b/src/s_sound.h @@ -200,6 +200,18 @@ extern struct cursongcredit fixed_t old_x; } cursongcredit; +extern struct soundtest +{ + boolean playing; // Music is playing? + boolean privilegedrequest; // Overrides S_PlaysimMusicDisabled w/o changing every function signature + musicdef_t *current; // Current selected music definition + SINT8 currenttrack; // Current selected music track for definition +} soundtest; + +void S_UpdateSoundTestDef(boolean reverse, boolean skipnull); +void S_SoundTestPlay(void); +void S_SoundTestStop(boolean pause); + boolean S_PlaysimMusicDisabled(void); extern musicdef_t *musicdefstart; From 6e48a671ee2d156dabad19aeba6cef466356e13e Mon Sep 17 00:00:00 2001 From: toaster Date: Sun, 26 Mar 2023 21:54:33 +0100 Subject: [PATCH 05/29] extras-1.c - convert magic numbers for Extras menu listings to enums Makes this code much less fragile to changing entries. --- src/k_menu.h | 10 +++++++++ src/menus/extras-1.c | 48 +++++++++++++++++--------------------------- 2 files changed, 28 insertions(+), 30 deletions(-) diff --git a/src/k_menu.h b/src/k_menu.h index 55394c5d3..569762464 100644 --- a/src/k_menu.h +++ b/src/k_menu.h @@ -1011,6 +1011,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); diff --git a/src/menus/extras-1.c b/src/menus/extras-1.c index e8ef11896..771f70036 100644 --- a/src/menus/extras-1.c +++ b/src/menus/extras-1.c @@ -37,7 +37,7 @@ menu_t EXTRAS_MainDef = { 0, 0, 0, "EXTRAS", - 2, 5, + 28, 5, M_DrawExtras, M_ExtrasTick, NULL, @@ -52,8 +52,6 @@ struct extrasmenu_s extrasmenu; void M_InitExtras(INT32 choice) { - UINT32 maxvalid = 2; - (void)choice; extrasmenu.ticker = 0; @@ -67,54 +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!"; - maxvalid = 3; + 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 = maxvalid; - } + 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[4].status = IT_STRING | IT_CALL; - EXTRAS_Main[4].text = "Stereo Mode"; - EXTRAS_Main[4].tooltip = "You can listen to your favourite tunes here!"; - maxvalid = 4; + 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[4].status = IT_STRING | IT_TRANSTEXT; - EXTRAS_Main[4].text = EXTRAS_Main[4].tooltip = "???"; - if (EXTRAS_MainDef.lastOn == 4) - { - EXTRAS_MainDef.lastOn = maxvalid; - } + EXTRAS_Main[extras_stereo].status = IT_STRING | IT_TRANSTEXT; + EXTRAS_Main[extras_stereo].text = EXTRAS_Main[extras_stereo].tooltip = "???"; } M_SetupNextMenu(&EXTRAS_MainDef, false); From 53b24067eea3bfc40ed8a903df61335b4c92fd6f Mon Sep 17 00:00:00 2001 From: toaster Date: Tue, 28 Mar 2023 00:43:37 +0100 Subject: [PATCH 06/29] Accidentially committed extras_tutorial to this branch --- src/k_menu.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/k_menu.h b/src/k_menu.h index 569762464..71b3bb298 100644 --- a/src/k_menu.h +++ b/src/k_menu.h @@ -1015,7 +1015,7 @@ typedef enum { extras_addons = 0, extras_challenges, - extras_tutorial, + //extras_tutorial, extras_statistics, extras_eggtv, extras_stereo, From 3d40e83700bd2ad8f945364e52f33432c4180542 Mon Sep 17 00:00:00 2001 From: toaster Date: Tue, 28 Mar 2023 01:31:39 +0100 Subject: [PATCH 07/29] S_SoundTestPlay: Exit early into S_SoundTestStop if current entry is NULL --- src/s_sound.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/s_sound.c b/src/s_sound.c index 5c5483b01..fa6bf53be 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -1403,19 +1403,18 @@ conclusion: if (soundtest.playing == true) { - if (newdef == NULL) - { - S_SoundTestStop(false); - } - else - { - S_SoundTestPlay(); - } + S_SoundTestPlay(); } } void S_SoundTestPlay(void) { + if (soundtest.current == NULL) + { + S_SoundTestStop(false); + return; + } + soundtest.privilegedrequest = true; S_StopMusic(); From 90d5cb3752ad1e0ae72602ac02afc66e773305d4 Mon Sep 17 00:00:00 2001 From: toaster Date: Tue, 28 Mar 2023 01:41:53 +0100 Subject: [PATCH 08/29] S_PopulateSoundTestSequence: Sound Test sequence system - Called on game start and file add - Creates a seperate linked list sequence for map-related order - All tracks without associated map in level order - All tracks with maps in a cup in cup order - All tracks with maps in Lost and Found --- src/p_setup.c | 3 + src/s_sound.c | 162 ++++++++++++++++++++++++++++++++++++++++++++------ src/s_sound.h | 18 ++++-- src/typedef.h | 1 + 4 files changed, 163 insertions(+), 21 deletions(-) diff --git a/src/p_setup.c b/src/p_setup.c index 40a68144a..8da76e19e 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -8564,6 +8564,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; diff --git a/src/s_sound.c b/src/s_sound.c index fa6bf53be..8792f25a4 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -1362,37 +1362,164 @@ musicdef_t *musicdefstart = NULL; struct cursongcredit cursongcredit; // Currently displayed song credit info struct soundtest soundtest; // Sound Test (sound test) +static void S_InsertMapIntoSoundTestSequence(UINT16 map, musicdef_t ***tail) +{ + UINT8 i, j; + (void)tail; + + for (i = 0; i < mapheaderinfo[map]->musname_size; i++) + { + musicdef_t *def = S_FindMusicDef(mapheaderinfo[map]->musname[i], &j); + + if (def == NULL) + continue; + + if (def->sequence.id == soundtest.sequence.id) + continue; + + 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; + } +} + +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; + + return M_MapLocked(def->sequence.map+1); +} + void S_UpdateSoundTestDef(boolean reverse, boolean skipnull) { musicdef_t *newdef; // Naive implementation for now. - newdef = (soundtest.current != NULL - && (skipnull == false || soundtest.current->next != NULL)) - ? soundtest.current->next - : musicdefstart; + newdef = NULL; if (reverse == false) { - // Due to how musicdefs are populated, we have to traverse backwards when attempting forwards. - musicdef_t *def; - - if (soundtest.current == musicdefstart) + 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 == false) { - newdef = NULL; - if (skipnull == false) - { - goto conclusion; - } + newdef = soundtest.sequence.next; + while (newdef != NULL && S_SoundTestDefLocked(newdef)) + newdef = newdef->sequence.next; + } + } + else + { + musicdef_t *def, *lastdef = NULL; + + if (soundtest.current == soundtest.sequence.next + && skipnull == false) + { + goto conclusion; } - for (def = musicdefstart; def; def = def->next) + for (def = soundtest.sequence.next; def; def = def->sequence.next) { - if (def->next != soundtest.current) - continue; + if (!S_SoundTestDefLocked(def)) + { + lastdef = def; + } - newdef = def; + if (def->sequence.next != soundtest.current) + { + continue; + } + + newdef = lastdef; break; } } @@ -1736,6 +1863,7 @@ void S_InitMusicDefs(void) UINT16 i; for (i = 0; i < numwadfiles; i++) S_LoadMusicDefs(i); + S_PopulateSoundTestSequence(); } // diff --git a/src/s_sound.h b/src/s_sound.h index 3936e83ae..b8a20ced3 100644 --- a/src/s_sound.h +++ b/src/s_sound.h @@ -176,6 +176,13 @@ boolean S_SpeedMusic(float speed); #define MAXDEFTRACKS 3 +struct soundtestsequence_t +{ + UINT8 id; + UINT16 map; + musicdef_t *next; +}; + // Music credits struct musicdef_t { @@ -188,6 +195,7 @@ struct musicdef_t char *composers; int volume; musicdef_t *next; + soundtestsequence_t sequence; }; extern struct cursongcredit @@ -202,12 +210,14 @@ extern struct cursongcredit extern struct soundtest { - boolean playing; // Music is playing? - boolean privilegedrequest; // Overrides S_PlaysimMusicDisabled w/o changing every function signature - musicdef_t *current; // Current selected music definition - SINT8 currenttrack; // Current selected music track for definition + boolean playing; // Music is playing? + boolean privilegedrequest; // Overrides S_PlaysimMusicDisabled w/o changing every function signature + musicdef_t *current; // Current selected music definition + SINT8 currenttrack; // Current selected music track for definition + soundtestsequence_t sequence; // Sequence head } soundtest; +void S_PopulateSoundTestSequence(void); void S_UpdateSoundTestDef(boolean reverse, boolean skipnull); void S_SoundTestPlay(void); void S_SoundTestStop(boolean pause); diff --git a/src/typedef.h b/src/typedef.h index 0615e7034..04298277c 100644 --- a/src/typedef.h +++ b/src/typedef.h @@ -388,6 +388,7 @@ TYPEDEF (listener_t); TYPEDEF (channel_t); TYPEDEF (caption_t); TYPEDEF (musicdef_t); +TYPEDEF (soundtestsequence_t); TYPEDEF (musicstack_t); // screen.h From 4f4976024c11442b8d814f7e09cbe8975eb54039 Mon Sep 17 00:00:00 2001 From: toaster Date: Tue, 28 Mar 2023 12:42:07 +0100 Subject: [PATCH 09/29] S_UpdateSoundTest: Corrections - Fix inverted skipnull condition for forward sequence traversal - Remove comment stating we used a naive implementation. The author of this commit used a triple pointer in the last one, this is anything but naive --- src/s_sound.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/s_sound.c b/src/s_sound.c index 8792f25a4..a837cbf33 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -1479,8 +1479,6 @@ void S_UpdateSoundTestDef(boolean reverse, boolean skipnull) { musicdef_t *newdef; - // Naive implementation for now. - newdef = NULL; if (reverse == false) @@ -1490,7 +1488,7 @@ void S_UpdateSoundTestDef(boolean reverse, boolean skipnull) : soundtest.sequence.next; while (newdef != NULL && S_SoundTestDefLocked(newdef)) newdef = newdef->sequence.next; - if (newdef == NULL && skipnull == false) + if (newdef == NULL && skipnull == true) { newdef = soundtest.sequence.next; while (newdef != NULL && S_SoundTestDefLocked(newdef)) From 8bd3786895199413d09f206a5e824755a93a739a Mon Sep 17 00:00:00 2001 From: toaster Date: Tue, 28 Mar 2023 13:06:39 +0100 Subject: [PATCH 10/29] S_UpdateSoundTest: Add a "dotracks" parameter - Integrates the maps with multiple tracks into the Next/Prev sequence, if true. - For testing, currently active - but I may add features later that would be more fitting. --- src/menus/transient/sound-test.c | 4 ++-- src/s_sound.c | 26 ++++++++++++++++++++++---- src/s_sound.h | 2 +- 3 files changed, 25 insertions(+), 7 deletions(-) diff --git a/src/menus/transient/sound-test.c b/src/menus/transient/sound-test.c index 946ac6aaf..78322d791 100644 --- a/src/menus/transient/sound-test.c +++ b/src/menus/transient/sound-test.c @@ -15,7 +15,7 @@ static void M_SoundTestMainControl(INT32 choice) { soundtest.playing = true; //soundtest.sequence = true; - S_UpdateSoundTestDef(false, false); + S_UpdateSoundTestDef(false, false, false); } else if (cv_soundtest.value != 0) { @@ -44,7 +44,7 @@ static void M_SoundTestNextPrev(INT32 choice) { (void)choice; - S_UpdateSoundTestDef((currentMenu->menuitems[itemOn].mvar1 < 0), false); + S_UpdateSoundTestDef((currentMenu->menuitems[itemOn].mvar1 < 0), true, false); } static void M_SoundTestTrack(INT32 choice) diff --git a/src/s_sound.c b/src/s_sound.c index a837cbf33..6f9fea5fd 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -1475,7 +1475,7 @@ static boolean S_SoundTestDefLocked(musicdef_t *def) return M_MapLocked(def->sequence.map+1); } -void S_UpdateSoundTestDef(boolean reverse, boolean skipnull) +void S_UpdateSoundTestDef(boolean reverse, boolean dotracks, boolean skipnull) { musicdef_t *newdef; @@ -1483,6 +1483,13 @@ void S_UpdateSoundTestDef(boolean reverse, boolean skipnull) 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; @@ -1499,10 +1506,17 @@ void S_UpdateSoundTestDef(boolean reverse, boolean skipnull) { 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 conclusion; + goto updatecurrent; } for (def = soundtest.sequence.next; def; def = def->sequence.next) @@ -1522,10 +1536,14 @@ void S_UpdateSoundTestDef(boolean reverse, boolean skipnull) } } -conclusion: +updatecurrent: soundtest.current = newdef; - soundtest.currenttrack = 0; + soundtest.currenttrack = + (reverse == true && dotracks == true && newdef != NULL) + ? newdef->numtracks-1 + : 0; +updatetrackonly: if (soundtest.playing == true) { S_SoundTestPlay(); diff --git a/src/s_sound.h b/src/s_sound.h index b8a20ced3..06286a1b0 100644 --- a/src/s_sound.h +++ b/src/s_sound.h @@ -218,7 +218,7 @@ extern struct soundtest } soundtest; void S_PopulateSoundTestSequence(void); -void S_UpdateSoundTestDef(boolean reverse, boolean skipnull); +void S_UpdateSoundTestDef(boolean reverse, boolean dotracks, boolean skipnull); void S_SoundTestPlay(void); void S_SoundTestStop(boolean pause); From 1f82285c39650779dc9a61cd95112078c5cbc499 Mon Sep 17 00:00:00 2001 From: toaster Date: Tue, 28 Mar 2023 13:13:22 +0100 Subject: [PATCH 11/29] S_SoundTestDefLocked: Account for Sealed Stars-style LF2_FINISHNEEDED completion lock. --- src/s_sound.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/s_sound.c b/src/s_sound.c index 6f9fea5fd..554a03ed4 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -1472,6 +1472,12 @@ static boolean S_SoundTestDefLocked(musicdef_t *def) 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); } From 8e8c2273e973dc4f2ac1ac720086b7634e23ce1c Mon Sep 17 00:00:00 2001 From: toaster Date: Tue, 28 Mar 2023 13:47:25 +0100 Subject: [PATCH 12/29] S_FindMusicDef: Handle NULL/empty string explicitly --- src/s_sound.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/s_sound.c b/src/s_sound.c index 554a03ed4..f0c18cbd4 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -1620,9 +1620,14 @@ boolean S_PlaysimMusicDisabled(void) // 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)++) From 3e476568eaa649c1fa77295f8762618fbf8baa94 Mon Sep 17 00:00:00 2001 From: toaster Date: Tue, 28 Mar 2023 13:50:05 +0100 Subject: [PATCH 13/29] mapheader_t: AssociatedMusic property Enables things like the Goin' Down!? segment in Speed Highway to be connected directly to access to that map. --- src/deh_soc.c | 26 +++++++++++++++++++++++-- src/doomstat.h | 4 +++- src/p_setup.c | 9 ++++----- src/s_sound.c | 52 ++++++++++++++++++++++++++++++-------------------- 4 files changed, 62 insertions(+), 29 deletions(-) diff --git a/src/deh_soc.c b/src/deh_soc.c index f286a7ce1..f2c5315a6 100644 --- a/src/deh_soc.c +++ b/src/deh_soc.c @@ -1187,8 +1187,30 @@ 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: 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, "MUSICTRACK")) mapheaderinfo[num]->mustrack = ((UINT16)i - 1); else if (fastcmp(word, "MUSICPOS")) diff --git a/src/doomstat.h b/src/doomstat.h index 2bf01f261..5a8f40814 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -445,9 +445,11 @@ 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. + UINT8 musname_size; ///< Number of music tracks defined + char associatedmus[MAXMUSNAMES][7]; ///< Associated music tracks for sound test unlock. + 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 diff --git a/src/p_setup.c b/src/p_setup.c index 8da76e19e..9511bb542 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -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; diff --git a/src/s_sound.c b/src/s_sound.c index f0c18cbd4..8e6977eb7 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -1362,33 +1362,43 @@ 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, j; - (void)tail; + UINT8 i; for (i = 0; i < mapheaderinfo[map]->musname_size; i++) { - musicdef_t *def = S_FindMusicDef(mapheaderinfo[map]->musname[i], &j); + S_InsertMusicAtSoundTestSequenceTail(mapheaderinfo[map]->musname[i], map, tail); + } - if (def == NULL) - continue; - - if (def->sequence.id == soundtest.sequence.id) - continue; - - 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; + for (i = 0; i < mapheaderinfo[map]->associatedmus_size; i++) + { + S_InsertMusicAtSoundTestSequenceTail(mapheaderinfo[map]->associatedmus[i], map, tail); } } From 48eca2d8cf896aeb23d176a81aeece0ae7ef96ec Mon Sep 17 00:00:00 2001 From: toaster Date: Tue, 28 Mar 2023 13:56:55 +0100 Subject: [PATCH 14/29] readlevelheader: Correct incorrect associated music debug message --- src/deh_soc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/deh_soc.c b/src/deh_soc.c index f2c5315a6..dbbfc7178 100644 --- a/src/deh_soc.c +++ b/src/deh_soc.c @@ -1202,7 +1202,7 @@ void readlevelheader(MYFILE *f, char * name) if (j >= MAXMUSNAMES) break; deh_strlcpy(mapheaderinfo[num]->associatedmus[j], tmp, - sizeof(mapheaderinfo[num]->associatedmus[j]), va("Level header %d: music", num)); + sizeof(mapheaderinfo[num]->associatedmus[j]), va("Level header %d: associated music", num)); j++; } while ((tmp = strtok(NULL,",")) != NULL); From 9a343bd465c9714788b30d10f02acd5a8f7e660c Mon Sep 17 00:00:00 2001 From: toaster Date: Tue, 28 Mar 2023 15:14:09 +0100 Subject: [PATCH 15/29] mapheader_t: PositionMusic property A little off-piste, but a trivial addition since I'm changing this part of the code. - Plays in Position outside of Encore - Shows up first in the Sound Test sequence for that map --- src/deh_soc.c | 12 ++++++++++++ src/doomstat.h | 3 ++- src/p_tick.c | 6 +++++- src/s_sound.c | 5 +++++ 4 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/deh_soc.c b/src/deh_soc.c index dbbfc7178..a23ba330b 100644 --- a/src/deh_soc.c +++ b/src/deh_soc.c @@ -1211,6 +1211,18 @@ void readlevelheader(MYFILE *f, char * name) 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")) diff --git a/src/doomstat.h b/src/doomstat.h index 5a8f40814..a0f28098f 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -445,8 +445,9 @@ 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. - UINT8 musname_size; ///< Number of music tracks defined 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. diff --git a/src/p_tick.c b/src/p_tick.c index 32881d68e..7865aeacb 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -801,7 +801,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); } } diff --git a/src/s_sound.c b/src/s_sound.c index 8e6977eb7..738c901c5 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -1391,6 +1391,11 @@ 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); From b1b6756e6a0d180459a43df754154223c49afd62 Mon Sep 17 00:00:00 2001 From: toaster Date: Wed, 29 Mar 2023 12:56:28 +0100 Subject: [PATCH 16/29] S_AttemptToRestoreMusic Per review, combine all spots where s_sound.c attempts to restore music into one gamestate-specific switch case system. --- src/s_sound.c | 49 +++++++++++++++++++++---------------------------- 1 file changed, 21 insertions(+), 28 deletions(-) diff --git a/src/s_sound.c b/src/s_sound.c index 738c901c5..b83fa1110 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -1354,6 +1354,24 @@ 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 /// ------------------------ @@ -1609,10 +1627,7 @@ void S_SoundTestStop(boolean pause) soundtest.current = NULL; soundtest.currenttrack = 0; - if (gamestate == GS_LEVEL) - { - P_RestoreMusic(&players[consoleplayer]); - } + S_AttemptToRestoreMusic(); } soundtest.privilegedrequest = false; @@ -2891,18 +2906,7 @@ static void Command_RestartAudio_f(void) S_StartSound(NULL, sfx_strpst); - if (gamestate == GS_LEVEL) // Gotta make sure the player is in a level - { - P_RestoreMusic(&players[consoleplayer]); - } - else if (gamestate == GS_TITLESCREEN) - { - S_ChangeMusicInternal("_title", looptitle); - } - else - { - M_PlayMenuJam(); - } + S_AttemptToRestoreMusic(); } static void Command_PlaySound(void) @@ -3002,18 +3006,7 @@ void GameDigiMusic_OnChange(void) I_StartupSound(); // will return early if initialised I_InitMusic(); - if (gamestate == GS_LEVEL) - { - P_RestoreMusic(&players[consoleplayer]); - } - else if (gamestate == GS_TITLESCREEN) - { - S_ChangeMusicInternal("_title", looptitle); - } - else - { - M_PlayMenuJam(); - } + S_AttemptToRestoreMusic(); } else { From bc07cfa94bdb23dbb3e4e35b33be5d1235f04273 Mon Sep 17 00:00:00 2001 From: toaster Date: Wed, 29 Mar 2023 13:39:40 +0100 Subject: [PATCH 17/29] S_SoundTestTogglePause Instead of a fake S_StopMusic-based Pause, make it use the S_PauseAudio/S_ResumeAudio system. --- src/menus/transient/sound-test.c | 9 ++++++- src/s_sound.c | 43 +++++++++++++++++++++++++------- src/s_sound.h | 4 ++- 3 files changed, 45 insertions(+), 11 deletions(-) diff --git a/src/menus/transient/sound-test.c b/src/menus/transient/sound-test.c index 78322d791..2ea8880a4 100644 --- a/src/menus/transient/sound-test.c +++ b/src/menus/transient/sound-test.c @@ -36,7 +36,14 @@ static void M_SoundTestMainControl(INT32 choice) } else if (soundtest.playing == true) { - S_SoundTestStop((currentMenu->menuitems[itemOn].mvar1 == 2)); + if (currentMenu->menuitems[itemOn].mvar1 == 2) + { + S_SoundTestTogglePause(); + } + else + { + S_SoundTestStop(); + } } } diff --git a/src/s_sound.c b/src/s_sound.c index b83fa1110..918a21c08 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -1593,7 +1593,7 @@ void S_SoundTestPlay(void) { if (soundtest.current == NULL) { - S_SoundTestStop(false); + S_SoundTestStop(); return; } @@ -1603,13 +1603,18 @@ void S_SoundTestPlay(void) soundtest.playing = true; + if (soundtest.paused == true) + { + S_SoundTestTogglePause(); + } + S_ChangeMusicInternal(soundtest.current->name[soundtest.currenttrack], true); S_ShowMusicCredit(); soundtest.privilegedrequest = false; } -void S_SoundTestStop(boolean pause) +void S_SoundTestStop(void) { if (soundtest.playing == false) { @@ -1621,18 +1626,35 @@ void S_SoundTestStop(boolean pause) S_StopMusic(); cursongcredit.def = NULL; - if (pause == false) - { - soundtest.playing = false; - soundtest.current = NULL; - soundtest.currenttrack = 0; + soundtest.playing = false; + soundtest.paused = false; + soundtest.current = NULL; + soundtest.currenttrack = 0; - S_AttemptToRestoreMusic(); - } + 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(); + } +} + boolean S_PlaysimMusicDisabled(void) { if (soundtest.privilegedrequest) @@ -2653,6 +2675,9 @@ void S_ResumeAudio(void) if (S_MusicNotInFocus()) return; + if (soundtest.paused == true) + return; + if (I_SongPlaying() && I_SongPaused()) I_ResumeSong(); diff --git a/src/s_sound.h b/src/s_sound.h index 06286a1b0..d39735f97 100644 --- a/src/s_sound.h +++ b/src/s_sound.h @@ -211,6 +211,7 @@ extern struct cursongcredit extern struct soundtest { boolean playing; // Music is playing? + boolean paused; // System paused? boolean privilegedrequest; // Overrides S_PlaysimMusicDisabled w/o changing every function signature musicdef_t *current; // Current selected music definition SINT8 currenttrack; // Current selected music track for definition @@ -220,7 +221,8 @@ extern struct soundtest void S_PopulateSoundTestSequence(void); void S_UpdateSoundTestDef(boolean reverse, boolean dotracks, boolean skipnull); void S_SoundTestPlay(void); -void S_SoundTestStop(boolean pause); +void S_SoundTestStop(void); +void S_SoundTestTogglePause(void); boolean S_PlaysimMusicDisabled(void); From 53fc4aec0a4691835025812f0104edc96e8a7038 Mon Sep 17 00:00:00 2001 From: toaster Date: Wed, 29 Mar 2023 15:08:01 +0100 Subject: [PATCH 18/29] Adjustments to user handling of Stereo Per VC discussion: - Pressing STOP does not NULL your selected song - ...unless you press it a second time while already stopped - Pressing PLAY should de-activate pause if active, not restart the track - Pressing PAUSE while paused should not de-activate pause - Removed the Extra functionality from TRACK. --- src/menus/transient/sound-test.c | 90 ++++++++++++++++---------------- src/s_sound.c | 2 - 2 files changed, 45 insertions(+), 47 deletions(-) diff --git a/src/menus/transient/sound-test.c b/src/menus/transient/sound-test.c index 2ea8880a4..045cdc246 100644 --- a/src/menus/transient/sound-test.c +++ b/src/menus/transient/sound-test.c @@ -11,13 +11,7 @@ static void M_SoundTestMainControl(INT32 choice) // Sound test exception if (soundtest.current == NULL || soundtest.current->numtracks == 0) { - if (currentMenu->menuitems[itemOn].mvar1 == 1) // Play - { - soundtest.playing = true; - //soundtest.sequence = true; - S_UpdateSoundTestDef(false, false, false); - } - else if (cv_soundtest.value != 0) + if (cv_soundtest.value != 0) { S_StopSounds(); @@ -25,6 +19,16 @@ static void M_SoundTestMainControl(INT32 choice) { 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.sequence = true; + S_UpdateSoundTestDef(false, false, false); } return; @@ -32,19 +36,34 @@ static void M_SoundTestMainControl(INT32 choice) if (currentMenu->menuitems[itemOn].mvar1 == 1) // Play { - S_SoundTestPlay(); - } - else if (soundtest.playing == true) - { - if (currentMenu->menuitems[itemOn].mvar1 == 2) + if (soundtest.paused == true) { S_SoundTestTogglePause(); } - else + 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; + } } static void M_SoundTestNextPrev(INT32 choice) @@ -58,53 +77,34 @@ static void M_SoundTestTrack(INT32 choice) { const UINT8 numtracks = (soundtest.current != NULL) ? soundtest.current->numtracks : 0; - if (numtracks == 1) + if (numtracks == 1 // No cycling + || choice == -1) // Extra { return; } + // Confirm is generally treated as Up. + // Soundtest exception if (numtracks == 0) { S_StopSounds(); - - if (choice == -1) // Extra - { - if (cv_soundtest.value != 0) - CV_SetValue(&cv_soundtest, 0); - } - else if (choice == 2) // Confirm - { - if (cv_soundtest.value != 0) - S_StartSound(NULL, cv_soundtest.value); - } - else // Up or Down - { - CV_AddValue(&cv_soundtest, ((choice == 0) ? -1 : 1)); - } + CV_AddValue(&cv_soundtest, ((choice == 0) ? -1 : 1)); return; } - if (choice == -1) // Extra + if (choice == 0) // Down { - soundtest.currenttrack = 0; + soundtest.currenttrack--; + if (soundtest.currenttrack < 0) + soundtest.currenttrack = numtracks-1; } - else + else //if (choice == 1) -- Up { - // Confirm resets the current instance - 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; - } + soundtest.currenttrack++; + if (soundtest.currenttrack >= numtracks) + soundtest.currenttrack = 0; } if (soundtest.playing) diff --git a/src/s_sound.c b/src/s_sound.c index 918a21c08..cc7ec287d 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -1628,8 +1628,6 @@ void S_SoundTestStop(void) soundtest.playing = false; soundtest.paused = false; - soundtest.current = NULL; - soundtest.currenttrack = 0; S_AttemptToRestoreMusic(); From d19a7d9a57ed26a7cce2c24f4dd3e561e22c5053 Mon Sep 17 00:00:00 2001 From: toaster Date: Wed, 29 Mar 2023 16:04:48 +0100 Subject: [PATCH 19/29] Add M_MenuConfirmHeld and M_MenuBackHeld, to go with M_MenuExtraHeld. --- src/k_menu.h | 2 ++ src/k_menufunc.c | 8 ++++---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/k_menu.h b/src/k_menu.h index 71b3bb298..1f53233eb 100644 --- a/src/k_menu.h +++ b/src/k_menu.h @@ -585,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); diff --git a/src/k_menufunc.c b/src/k_menufunc.c index 1915dfa5b..4727f2fbe 100644 --- a/src/k_menufunc.c +++ b/src/k_menufunc.c @@ -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) From 2446e53ff9f24a68bc8bb534132e6981baad78b4 Mon Sep 17 00:00:00 2001 From: toaster Date: Wed, 29 Mar 2023 16:14:38 +0100 Subject: [PATCH 20/29] Start on Stereo Mode visuals - Buttons have been implemented. - They push down when you press an input. - FUTURE WORK: Back doesn't get the opportunity to do so. Delay the exit of this menu? - Certain ones have special properties. - PLAY locks down when playing and not paused - PAUSE locks down when playing and paused - TRACK is a wheel/slidery thing - BACK should get pressed when you're exiting (see previous FUTURE WORK) - FUTURE WORK: The detection of these currently uses magic numbers. - The Stereo itself is now drawn. - FUTURE WORK: The screen's contents are still the testing visuals. --- src/k_menudraw.c | 114 ++++++++++++++++++++++++++++--- src/menus/transient/sound-test.c | 30 +++++--- src/s_sound.h | 1 + 3 files changed, 128 insertions(+), 17 deletions(-) diff --git a/src/k_menudraw.c b/src/k_menudraw.c index 2be547a62..44d06ac5c 100644 --- a/src/k_menudraw.c +++ b/src/k_menudraw.c @@ -5928,7 +5928,10 @@ void M_DrawStatistics(void) void M_DrawSoundTest(void) { - INT32 x = currentMenu->x - menutransition.tics*48, y, i, w, cursorx = 0; + UINT8 pid = 0; // todo: Add ability for any splitscreen player to bring up the menu. + + INT32 x, y, i, cursorx = 0; + patch_t *btn = W_CachePatchName("STER_BTN", PU_CACHE); if (gamestate == GS_MENU) { @@ -5936,10 +5939,20 @@ void M_DrawSoundTest(void) V_DrawFixedPatch(0, 0, FRACUNIT, 0, bg, NULL); } - y = 50; + V_DrawFixedPatch(0, 0, FRACUNIT, 0, W_CachePatchName("STER_BG", PU_CACHE), NULL); + + x = 24; + y = 18; if (soundtest.current != NULL) { + K_DrawMapThumbnail( + x<sequence.map, + NULL); + V_DrawThinString(x, y, (soundtest.playing ? highlightflags : 0)|V_ALLOWLOWERCASE|V_6WIDTHSPACE, soundtest.current->title); V_DrawThinString(x, (y += 10), V_ALLOWLOWERCASE|V_6WIDTHSPACE, va("%d", soundtest.currenttrack)); if (soundtest.current->author) @@ -5956,21 +5969,106 @@ void M_DrawSoundTest(void) V_DrawThinString(x, (y += 10), V_ALLOWLOWERCASE|V_6WIDTHSPACE, va("%d", cv_soundtest.value)); } - y = currentMenu->y; + x = currentMenu->x; for (i = 0; i < currentMenu->numitems; i++) { - w = V_ThinStringWidth(currentMenu->menuitems[i].text, V_6WIDTHSPACE); + 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 + w/2; - V_DrawThinString(x, y, V_6WIDTHSPACE|highlightflags, currentMenu->menuitems[i].text); + 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 == 1) // back + { + if (!soundtest.justopened && M_MenuBackHeld(pid)) + { + y = currentMenu->y + 7; + } + } + // The following are springlocks. + else if (currentMenu->menuitems[i].mvar2 == 2) // pause + { + if (soundtest.paused == true) + y = currentMenu->y + 6; + } + else if (currentMenu->menuitems[i].mvar2 == 3) // play + { + if (soundtest.playing == true && soundtest.paused == false) + 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 == 4) // 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_DrawThinString(x, y, V_6WIDTHSPACE, currentMenu->menuitems[i].text); + V_DrawCenteredThinString(x + 13, y + 1, V_6WIDTHSPACE, currentMenu->menuitems[i].text); } - x += w + 8; + + x += 27; } V_DrawCharacter(cursorx - 4, currentMenu->y - 8 - (skullAnimCounter/5), diff --git a/src/menus/transient/sound-test.c b/src/menus/transient/sound-test.c index 045cdc246..0ef34f6ed 100644 --- a/src/menus/transient/sound-test.c +++ b/src/menus/transient/sound-test.c @@ -113,15 +113,26 @@ static void M_SoundTestTrack(INT32 choice) } } +static boolean M_SoundTestInputs(INT32 ch) +{ + (void)ch; + soundtest.justopened = false; + return false; +} + menuitem_t MISC_SoundTest[] = { - {IT_STRING | IT_CALL, "Back", NULL, NULL, {.routine = M_GoBack}, 0, 0}, - {IT_STRING | IT_CALL, "Stop", NULL, NULL, {.routine = M_SoundTestMainControl}, 0, 0}, - {IT_STRING | IT_CALL, "Pause", NULL, NULL, {.routine = M_SoundTestMainControl}, 2, 0}, - {IT_STRING | IT_CALL, "Play", NULL, NULL, {.routine = M_SoundTestMainControl}, 1, 0}, - {IT_STRING | IT_ARROWS, "Track", NULL, NULL, {.routine = M_SoundTestTrack}, 0, 0}, - {IT_STRING | IT_CALL, "Prev", NULL, NULL, {.routine = M_SoundTestNextPrev}, -1, 0}, - {IT_STRING | IT_CALL, "Next", NULL, NULL, {.routine = M_SoundTestNextPrev}, 1, 0}, + {IT_STRING | IT_CALL, "Back", "STER_IC0", NULL, {.routine = M_GoBack}, 0, 1}, + {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, 2}, + {IT_STRING | IT_CALL, "Play", "STER_IC3", NULL, {.routine = M_SoundTestMainControl}, 1, 3}, + {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}, 0, 276}, + {IT_STRING | IT_ARROWS, "Track", NULL, NULL, {.routine = M_SoundTestTrack}, 0, 4}, }; menu_t MISC_SoundTestDef = { @@ -129,7 +140,7 @@ menu_t MISC_SoundTestDef = { &MainDef, 0, MISC_SoundTest, - 42, BASEVIDHEIGHT/2, + 19, 140, 0, 0, MBF_UD_LR_FLIPPED|MBF_SOUNDLESS, ".", @@ -138,7 +149,7 @@ menu_t MISC_SoundTestDef = { NULL, NULL, NULL, - NULL, + M_SoundTestInputs, }; void M_SoundTest(INT32 choice) @@ -146,6 +157,7 @@ void M_SoundTest(INT32 choice) (void)choice; // I reserve the right to add some sort of setup here -- toast 250323 + soundtest.justopened = true; MISC_SoundTestDef.prevMenu = currentMenu; M_SetupNextMenu(&MISC_SoundTestDef, false); diff --git a/src/s_sound.h b/src/s_sound.h index d39735f97..f17d5dba5 100644 --- a/src/s_sound.h +++ b/src/s_sound.h @@ -212,6 +212,7 @@ 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 musicdef_t *current; // Current selected music definition SINT8 currenttrack; // Current selected music track for definition From f9975d6a71c612cb9d17489d657f9c5da37768b0 Mon Sep 17 00:00:00 2001 From: toaster Date: Wed, 29 Mar 2023 23:23:51 +0100 Subject: [PATCH 21/29] stereospecial_e No more magic numbers for M_DrawSoundTest --- src/k_menu.h | 9 +++++++++ src/k_menudraw.c | 8 ++++---- src/menus/transient/sound-test.c | 8 ++++---- 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/k_menu.h b/src/k_menu.h index 1f53233eb..17d62d019 100644 --- a/src/k_menu.h +++ b/src/k_menu.h @@ -1219,6 +1219,15 @@ 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_track, +} stereospecial_e; + void M_SoundTest(INT32 choice); void M_DrawSoundTest(void); diff --git a/src/k_menudraw.c b/src/k_menudraw.c index 44d06ac5c..5450fc828 100644 --- a/src/k_menudraw.c +++ b/src/k_menudraw.c @@ -6001,7 +6001,7 @@ void M_DrawSoundTest(void) ); // Special cases - if (currentMenu->menuitems[i].mvar2 == 1) // back + if (currentMenu->menuitems[i].mvar2 == stereospecial_back) // back { if (!soundtest.justopened && M_MenuBackHeld(pid)) { @@ -6009,12 +6009,12 @@ void M_DrawSoundTest(void) } } // The following are springlocks. - else if (currentMenu->menuitems[i].mvar2 == 2) // pause + else if (currentMenu->menuitems[i].mvar2 == stereospecial_pause) // pause { if (soundtest.paused == true) y = currentMenu->y + 6; } - else if (currentMenu->menuitems[i].mvar2 == 3) // play + else if (currentMenu->menuitems[i].mvar2 == stereospecial_play) // play { if (soundtest.playing == true && soundtest.paused == false) y = currentMenu->y + 6; @@ -6043,7 +6043,7 @@ void M_DrawSoundTest(void) V_DrawFill(x+2, currentMenu->y + 22, 23, 1, 30); } - else if (currentMenu->menuitems[i].mvar2 == 4) // Track + else if (currentMenu->menuitems[i].mvar2 == stereospecial_track) // Track { if (i == itemOn) { diff --git a/src/menus/transient/sound-test.c b/src/menus/transient/sound-test.c index 0ef34f6ed..6273a7e68 100644 --- a/src/menus/transient/sound-test.c +++ b/src/menus/transient/sound-test.c @@ -122,17 +122,17 @@ static boolean M_SoundTestInputs(INT32 ch) menuitem_t MISC_SoundTest[] = { - {IT_STRING | IT_CALL, "Back", "STER_IC0", NULL, {.routine = M_GoBack}, 0, 1}, + {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, 2}, - {IT_STRING | IT_CALL, "Play", "STER_IC3", NULL, {.routine = M_SoundTestMainControl}, 1, 3}, + {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}, 0, 276}, - {IT_STRING | IT_ARROWS, "Track", NULL, NULL, {.routine = M_SoundTestTrack}, 0, 4}, + {IT_STRING | IT_ARROWS, "Track", NULL, NULL, {.routine = M_SoundTestTrack}, 0, stereospecial_track}, }; menu_t MISC_SoundTestDef = { From e5c3b566bf02621c666c29ff508c4730c941a53d Mon Sep 17 00:00:00 2001 From: toaster Date: Thu, 30 Mar 2023 01:01:16 +0100 Subject: [PATCH 22/29] Stereo Volume Access to soundvolume and musicvolume through the Stereo Mode menu - Draws a knob and volume bar (with loudness warning) - Changes which cvar is associated with it depending on selected song/lack of - If on any regular song, use digital music volume - If on soundtest, use sound volume - unless on entry 0 aka N/A, where no volume is visible at all --- src/k_menu.h | 2 ++ src/k_menudraw.c | 42 ++++++++++++++++++++++++++++++++ src/menus/transient/sound-test.c | 26 +++++++++++++++++++- 3 files changed, 69 insertions(+), 1 deletion(-) diff --git a/src/k_menu.h b/src/k_menu.h index 17d62d019..4b836ab98 100644 --- a/src/k_menu.h +++ b/src/k_menu.h @@ -1225,11 +1225,13 @@ typedef enum stereospecial_back, stereospecial_pause, stereospecial_play, + 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)\ diff --git a/src/k_menudraw.c b/src/k_menudraw.c index 5450fc828..31162482a 100644 --- a/src/k_menudraw.c +++ b/src/k_menudraw.c @@ -6043,6 +6043,48 @@ void M_DrawSoundTest(void) 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) diff --git a/src/menus/transient/sound-test.c b/src/menus/transient/sound-test.c index 6273a7e68..b33514e4e 100644 --- a/src/menus/transient/sound-test.c +++ b/src/menus/transient/sound-test.c @@ -73,6 +73,29 @@ static void M_SoundTestNextPrev(INT32 choice) S_UpdateSoundTestDef((currentMenu->menuitems[itemOn].mvar1 < 0), true, false); } +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; @@ -131,7 +154,8 @@ menuitem_t MISC_SoundTest[] = {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}, 0, 276}, + {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}, }; From 5a802219cec28ca7d8ce02929bcf3e39fc3b4402 Mon Sep 17 00:00:00 2001 From: toaster Date: Thu, 30 Mar 2023 01:11:22 +0100 Subject: [PATCH 23/29] M_SoundTestNextPrev: Set cv_soundtest to 0 when returning to the soundtest entry --- src/menus/transient/sound-test.c | 1 + src/s_sound.c | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/src/menus/transient/sound-test.c b/src/menus/transient/sound-test.c index b33514e4e..68ca08304 100644 --- a/src/menus/transient/sound-test.c +++ b/src/menus/transient/sound-test.c @@ -63,6 +63,7 @@ static void M_SoundTestMainControl(INT32 choice) { soundtest.current = NULL; soundtest.currenttrack = 0; + CV_SetValue(&cv_soundtest, 0); } } diff --git a/src/s_sound.c b/src/s_sound.c index cc7ec287d..5c92622da 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -1582,6 +1582,11 @@ updatecurrent: ? newdef->numtracks-1 : 0; + if (newdef == NULL) + { + CV_SetValue(&cv_soundtest, 0); + } + updatetrackonly: if (soundtest.playing == true) { From 99f4641700198882f03672fd13551de8d6e3dd7f Mon Sep 17 00:00:00 2001 From: toaster Date: Thu, 30 Mar 2023 18:31:18 +0100 Subject: [PATCH 24/29] Improve level select icon handling - Make it full base resolution... - ...but use ClipRect to make it fit inside the window of the Stereo --- src/k_menudraw.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/src/k_menudraw.c b/src/k_menudraw.c index 31162482a..f938524a9 100644 --- a/src/k_menudraw.c +++ b/src/k_menudraw.c @@ -5944,14 +5944,23 @@ void M_DrawSoundTest(void) x = 24; y = 18; + V_SetClipRect( + x << FRACBITS, y << FRACBITS, + 272 << FRACBITS, 106 << FRACBITS, + 0 + ); + if (soundtest.current != NULL) { - K_DrawMapThumbnail( - x<sequence.map, - NULL); + if (soundtest.current->sequence.map < nummapheaders) + { + K_DrawMapThumbnail( + 0, 0, + BASEVIDWIDTH<sequence.map, + NULL); + } V_DrawThinString(x, y, (soundtest.playing ? highlightflags : 0)|V_ALLOWLOWERCASE|V_6WIDTHSPACE, soundtest.current->title); V_DrawThinString(x, (y += 10), V_ALLOWLOWERCASE|V_6WIDTHSPACE, va("%d", soundtest.currenttrack)); @@ -5969,6 +5978,8 @@ void M_DrawSoundTest(void) V_DrawThinString(x, (y += 10), V_ALLOWLOWERCASE|V_6WIDTHSPACE, va("%d", cv_soundtest.value)); } + V_ClearClipRect(); + x = currentMenu->x; for (i = 0; i < currentMenu->numitems; i++) From 2c0645cba2f26fed68fe8d68af33637973dd1684 Mon Sep 17 00:00:00 2001 From: toaster Date: Thu, 30 Mar 2023 18:36:09 +0100 Subject: [PATCH 25/29] Improve Stereo text header drawing - Use LSTitleHighString at the top of the menu for the music's title/Sound Test - Only show Track for relevant entries - Show cv_soundtest.value in hex for that Classic Sonic soundtest flavour --- src/k_menudraw.c | 34 ++++++++++++++++++++++++++++---- src/menus/transient/sound-test.c | 8 +++++++- src/s_sound.h | 4 ++++ 3 files changed, 41 insertions(+), 5 deletions(-) diff --git a/src/k_menudraw.c b/src/k_menudraw.c index f938524a9..737f3b1cc 100644 --- a/src/k_menudraw.c +++ b/src/k_menudraw.c @@ -5931,6 +5931,9 @@ 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) @@ -5950,6 +5953,8 @@ void M_DrawSoundTest(void) 0 ); + y += 32; + if (soundtest.current != NULL) { if (soundtest.current->sequence.map < nummapheaders) @@ -5962,8 +5967,11 @@ void M_DrawSoundTest(void) NULL); } - V_DrawThinString(x, y, (soundtest.playing ? highlightflags : 0)|V_ALLOWLOWERCASE|V_6WIDTHSPACE, soundtest.current->title); - V_DrawThinString(x, (y += 10), V_ALLOWLOWERCASE|V_6WIDTHSPACE, va("%d", soundtest.currenttrack)); + titletext = soundtest.current->title; + + y -= 10; + 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) @@ -5974,8 +5982,26 @@ void M_DrawSoundTest(void) else { const char *sfxstr = (cv_soundtest.value) ? S_sfx[cv_soundtest.value].name : "N/A"; - V_DrawThinString(x, y, V_ALLOWLOWERCASE|V_6WIDTHSPACE, sfxstr); - V_DrawThinString(x, (y += 10), V_ALLOWLOWERCASE|V_6WIDTHSPACE, va("%d", cv_soundtest.value)); + + 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_ClearClipRect(); diff --git a/src/menus/transient/sound-test.c b/src/menus/transient/sound-test.c index 68ca08304..2ce290809 100644 --- a/src/menus/transient/sound-test.c +++ b/src/menus/transient/sound-test.c @@ -144,6 +144,11 @@ static boolean M_SoundTestInputs(INT32 ch) 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}, @@ -171,7 +176,7 @@ menu_t MISC_SoundTestDef = { ".", 98, 0, M_DrawSoundTest, - NULL, + M_SoundTestTick, NULL, NULL, M_SoundTestInputs, @@ -182,6 +187,7 @@ 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; diff --git a/src/s_sound.h b/src/s_sound.h index f17d5dba5..fb711225f 100644 --- a/src/s_sound.h +++ b/src/s_sound.h @@ -214,8 +214,12 @@ extern struct soundtest boolean paused; // System paused? boolean justopened; // Menu visual assist boolean privilegedrequest; // Overrides S_PlaysimMusicDisabled w/o changing every function signature + + INT32 menutick; + musicdef_t *current; // Current selected music definition SINT8 currenttrack; // Current selected music track for definition + soundtestsequence_t sequence; // Sequence head } soundtest; From fe8db18066e978e79b0e83c47ca2285ca43220d5 Mon Sep 17 00:00:00 2001 From: toaster Date: Thu, 30 Mar 2023 23:28:51 +0100 Subject: [PATCH 26/29] Store non-looping information in musicdef Preface with a `\` (ie `Lump VOTEEA,\VOTEEB`) to indicate the preference is not to loop. This is for special jingles that have definitive conclusions. --- src/s_sound.c | 8 +++++++- src/s_sound.h | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/s_sound.c b/src/s_sound.c index 5c92622da..38b95d3f7 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -1613,7 +1613,8 @@ void S_SoundTestPlay(void) S_SoundTestTogglePause(); } - S_ChangeMusicInternal(soundtest.current->name[soundtest.currenttrack], true); + S_ChangeMusicInternal(soundtest.current->name[soundtest.currenttrack], + !soundtest.current->basenoloop[soundtest.currenttrack]); S_ShowMusicCredit(); soundtest.privilegedrequest = false; @@ -1760,6 +1761,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); diff --git a/src/s_sound.h b/src/s_sound.h index fb711225f..1bb5e2ce3 100644 --- a/src/s_sound.h +++ b/src/s_sound.h @@ -188,6 +188,7 @@ struct musicdef_t { char name[MAXDEFTRACKS][7]; UINT32 hash[MAXDEFTRACKS]; + boolean basenoloop[MAXDEFTRACKS]; UINT8 numtracks; char *title; char *author; From 6f99a75c24f1b312183c3e7dbfd50573f26413d8 Mon Sep 17 00:00:00 2001 From: toaster Date: Thu, 30 Mar 2023 23:31:37 +0100 Subject: [PATCH 27/29] Duplicate current track title per VC discussion --- src/k_menudraw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/k_menudraw.c b/src/k_menudraw.c index 737f3b1cc..3fc84312b 100644 --- a/src/k_menudraw.c +++ b/src/k_menudraw.c @@ -5969,7 +5969,7 @@ void M_DrawSoundTest(void) titletext = soundtest.current->title; - y -= 10; + 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) From 027fd2be046ac160d16f3c6ae3bd38ef2c35963a Mon Sep 17 00:00:00 2001 From: toaster Date: Fri, 31 Mar 2023 00:11:06 +0100 Subject: [PATCH 28/29] Time elapsed functionality - Shown on the menu - soundtest.autosequence - Plays all songs in sequence, skipping over the soundtest entry. - Plays each looping song twice (and fades out if it's the last one in the musicdef's tracks) - Plays non-looping songs once with no fade ever - Disabled when S_SoundTestStop called - Songs that end outside of autosequence will now stop the visible Playing. --- src/d_main.c | 3 + src/k_menu.h | 1 + src/k_menudraw.c | 30 ++++++++++ src/menus/transient/sound-test.c | 11 +++- src/s_sound.c | 100 ++++++++++++++++++++++++++++++- src/s_sound.h | 9 ++- 6 files changed, 150 insertions(+), 4 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index 7b75ff8d0..53bba25cb 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -949,7 +949,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(); diff --git a/src/k_menu.h b/src/k_menu.h index 4b836ab98..cd7bbbe68 100644 --- a/src/k_menu.h +++ b/src/k_menu.h @@ -1225,6 +1225,7 @@ typedef enum stereospecial_back, stereospecial_pause, stereospecial_play, + stereospecial_seq, stereospecial_vol, stereospecial_track, } stereospecial_e; diff --git a/src/k_menudraw.c b/src/k_menudraw.c index 3fc84312b..e7392c51d 100644 --- a/src/k_menudraw.c +++ b/src/k_menudraw.c @@ -6004,6 +6004,31 @@ void M_DrawSoundTest(void) 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; @@ -6056,6 +6081,11 @@ void M_DrawSoundTest(void) 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)) diff --git a/src/menus/transient/sound-test.c b/src/menus/transient/sound-test.c index 2ce290809..fb16972f4 100644 --- a/src/menus/transient/sound-test.c +++ b/src/menus/transient/sound-test.c @@ -27,7 +27,7 @@ static void M_SoundTestMainControl(INT32 choice) else if (currentMenu->menuitems[itemOn].mvar1 == 1) // Play { soundtest.playing = true; - //soundtest.sequence = true; + soundtest.autosequence = true; S_UpdateSoundTestDef(false, false, false); } @@ -74,6 +74,13 @@ static void M_SoundTestNextPrev(INT32 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) @@ -160,6 +167,8 @@ menuitem_t MISC_SoundTest[] = {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}, diff --git a/src/s_sound.c b/src/s_sound.c index 38b95d3f7..41c2191d4 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -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 @@ -1617,6 +1618,28 @@ void S_SoundTestPlay(void) !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; } @@ -1629,11 +1652,17 @@ void S_SoundTestStop(void) soundtest.privilegedrequest = true; + soundtest.playing = false; + soundtest.paused = false; + soundtest.autosequence = false; + S_StopMusic(); cursongcredit.def = NULL; - soundtest.playing = false; - soundtest.paused = false; + soundtest.currenttime = 0; + soundtest.sequencemaxtime = 0; + soundtest.sequencefadeout = 0; + soundtest.dosequencefadeout = false; S_AttemptToRestoreMusic(); @@ -1659,6 +1688,73 @@ void S_SoundTestTogglePause(void) } } +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) diff --git a/src/s_sound.h b/src/s_sound.h index 1bb5e2ce3..9252ba031 100644 --- a/src/s_sound.h +++ b/src/s_sound.h @@ -216,12 +216,18 @@ extern struct soundtest boolean justopened; // Menu visual assist boolean privilegedrequest; // Overrides S_PlaysimMusicDisabled w/o changing every function signature - INT32 menutick; + 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); @@ -229,6 +235,7 @@ 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); From 5a5a607c9a7eedac7190627e8fe3f1c848dedbae Mon Sep 17 00:00:00 2001 From: toaster Date: Fri, 31 Mar 2023 00:28:15 +0100 Subject: [PATCH 29/29] M_DrawSoundTest: STER_DOT Draws a dot matrix over the background level icon --- src/k_menudraw.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/k_menudraw.c b/src/k_menudraw.c index e7392c51d..abf0f7e1f 100644 --- a/src/k_menudraw.c +++ b/src/k_menudraw.c @@ -5962,9 +5962,17 @@ void M_DrawSoundTest(void) K_DrawMapThumbnail( 0, 0, BASEVIDWIDTH<sequence.map, NULL); + + V_DrawFixedPatch( + 0, 0, + FRACUNIT, + V_60TRANS|V_SUBTRACT, + W_CachePatchName("STER_DOT", PU_CACHE), + NULL + ); } titletext = soundtest.current->title;