diff --git a/data/tr1/ship/cfg/TR1X_strings.json5 b/data/tr1/ship/cfg/TR1X_strings.json5 index b8ea28438..fe26d2eaa 100644 --- a/data/tr1/ship/cfg/TR1X_strings.json5 +++ b/data/tr1/ship/cfg/TR1X_strings.json5 @@ -531,7 +531,9 @@ "PHOTO_MODE_ROTATE_PROMPT": "Rotate camera", "PHOTO_MODE_SNAP_PROMPT": "Take picture", "PHOTO_MODE_TITLE": "Photo Mode", - "SOUND_SET_VOLUMES": "Set Volumes", + "SOUND_DIALOG_MUSIC": "\\{icon sound} Sound", + "SOUND_DIALOG_SOUND": "\\{icon music} Music", + "SOUND_DIALOG_TITLE": "Set Volumes", "STATS_AMMO": "AMMO HITS/USED", "STATS_BASIC_FMT": "%d", "STATS_BONUS_STATISTICS": "Bonus Statistics", diff --git a/data/tr2/ship/cfg/TR2X_strings.json5 b/data/tr2/ship/cfg/TR2X_strings.json5 index abc97764d..e2d2e8c0c 100644 --- a/data/tr2/ship/cfg/TR2X_strings.json5 +++ b/data/tr2/ship/cfg/TR2X_strings.json5 @@ -655,7 +655,9 @@ "PHOTO_MODE_ROTATE_PROMPT": "Rotate camera", "PHOTO_MODE_SNAP_PROMPT": "Take picture", "PHOTO_MODE_TITLE": "Photo Mode", - "SOUND_SET_VOLUMES": "Set Volumes", + "SOUND_DIALOG_MUSIC": "\\{icon sound} Sound", + "SOUND_DIALOG_SOUND": "\\{icon music} Music", + "SOUND_DIALOG_TITLE": "Set Volumes", "STATS_AMMO_HITS": "Hits", "STATS_AMMO_USED": "Ammo Used", "STATS_ASSAULT_FINISH": "Finish", diff --git a/docs/tr1/CHANGELOG.md b/docs/tr1/CHANGELOG.md index 818130279..c5fde4bd5 100644 --- a/docs/tr1/CHANGELOG.md +++ b/docs/tr1/CHANGELOG.md @@ -11,6 +11,7 @@ - changed the "enable EIDOS logo" option to disable the Core Design and Bink Video Codec FMVs as well; renamed to "enable legal" (#2741) - changed sprite pickups to respect the water tint if placed underwater (#2673) - changed save to take priority over load when both inputs are held on the same frame, in line with OG (#2833) +- changed the sound dialog appearance (repositioned and added text labels) - fixed the bilinear filter to not readjust the UVs (#2258) - fixed disabling the cutscenes causing the game to exit (#2743, regression from 4.8) - fixed anisotropy filter causing black lines on certain GPUs (#902) diff --git a/docs/tr2/CHANGELOG.md b/docs/tr2/CHANGELOG.md index 1577ff805..06e4e9d5b 100644 --- a/docs/tr2/CHANGELOG.md +++ b/docs/tr2/CHANGELOG.md @@ -3,6 +3,7 @@ ## [1.0.1](https://github.com/LostArtefacts/TRX/compare/tr2-1.0...tr2-1.0.1) - 2025-04-24 - added an option to wraparound when scrolling UI dialogs, such as save/load (#2834) - changed save to take priority over load when both inputs are held on the same frame, in line with OG (#2833) +- changed the sound dialog appearance (repositioned, added text labels and arrows) - fixed the selected keyboard/controller layout not being saved (#2830, regression from 1.0) - fixed toggling the PSX FOV option not having an immediate effect (#2831, regression from 1.0) - fixed changing the aspect ratio not updating the current background image (#2832, regression from 1.0) diff --git a/src/libtrx/game/music.c b/src/libtrx/game/music.c index c3e60a6e6..19d259fdb 100644 --- a/src/libtrx/game/music.c +++ b/src/libtrx/game/music.c @@ -2,6 +2,16 @@ static uint16_t m_MusicTrackFlags[MAX_MUSIC_TRACKS] = {}; +int32_t Music_GetMinVolume(void) +{ + return 0; +} + +int32_t Music_GetMaxVolume(void) +{ + return 10; +} + void Music_ResetTrackFlags(void) { for (int32_t i = 0; i < MAX_MUSIC_TRACKS; i++) { diff --git a/src/libtrx/game/ui/dialogs/sound_settings.c b/src/libtrx/game/ui/dialogs/sound_settings.c new file mode 100644 index 000000000..b5f382308 --- /dev/null +++ b/src/libtrx/game/ui/dialogs/sound_settings.c @@ -0,0 +1,176 @@ +#include "game/ui/dialogs/sound_settings.h" + +#include "config.h" +#include "game/game_string.h" +#include "game/input.h" +#include "game/music.h" +#include "game/sound.h" +#include "game/ui/elements/anchor.h" +#include "game/ui/elements/hide.h" +#include "game/ui/elements/label.h" +#include "game/ui/elements/modal.h" +#include "game/ui/elements/requester.h" +#include "game/ui/elements/resize.h" +#include "game/ui/elements/spacer.h" +#include "game/ui/elements/stack.h" +#include "memory.h" +#include "strings.h" +#include "utils.h" + +typedef struct UI_SOUND_SETTINGS_STATE { + UI_REQUESTER_STATE req; +} UI_SOUND_SETTINGS_STATE; + +typedef enum { + M_ROW_MUSIC = 0, + M_ROW_SOUND = 1, + M_ROW_COUNT = 2, +} M_ROW; + +static const GAME_STRING_ID m_Labels[M_ROW_COUNT] = { + GS_ID(SOUND_DIALOG_SOUND), + GS_ID(SOUND_DIALOG_MUSIC), +}; + +static char *M_FormatRowValue(int32_t row); +static bool M_CanChange(int32_t row, int32_t dir); +static bool M_RequestChange(int32_t row, int32_t dir); + +static char *M_FormatRowValue(const int32_t row) +{ + switch (row) { + case M_ROW_MUSIC: + return String_Format("%2d", g_Config.audio.music_volume); + case M_ROW_SOUND: + return String_Format("%2d", g_Config.audio.sound_volume); + default: + return nullptr; + } +} + +static bool M_CanChange(const int32_t row, const int32_t dir) +{ + switch (row) { + case M_ROW_MUSIC: + if (dir < 0) { + return g_Config.audio.music_volume > Music_GetMinVolume(); + } else if (dir > 0) { + return g_Config.audio.music_volume < Music_GetMaxVolume(); + } + break; + case M_ROW_SOUND: + if (dir < 0) { + return g_Config.audio.sound_volume > Sound_GetMinVolume(); + } else if (dir > 0) { + return g_Config.audio.sound_volume < Sound_GetMaxVolume(); + } + break; + } + return false; +} + +static bool M_RequestChange(const int32_t row, const int32_t dir) +{ + if (!M_CanChange(row, dir)) { + return false; + } + switch (row) { + case M_ROW_MUSIC: + g_Config.audio.music_volume += dir; + Music_SetVolume(g_Config.audio.music_volume); + break; + case M_ROW_SOUND: + g_Config.audio.sound_volume += dir; + Sound_SetMasterVolume(g_Config.audio.sound_volume); + break; + default: + return false; + } + Config_Write(); + Sound_Effect(SFX_MENU_PASSPORT, nullptr, SPM_ALWAYS); + return true; +} + +UI_SOUND_SETTINGS_STATE *UI_SoundSettings_Init(void) +{ + UI_SOUND_SETTINGS_STATE *s = Memory_Alloc(sizeof(UI_SOUND_SETTINGS_STATE)); + UI_Requester_Init(&s->req, M_ROW_COUNT, M_ROW_COUNT, true); + s->req.row_pad = 2.0f; + return s; +} + +void UI_SoundSettings_Free(UI_SOUND_SETTINGS_STATE *const s) +{ + UI_Requester_Free(&s->req); + Memory_Free(s); +} + +bool UI_SoundSettings_Control(UI_SOUND_SETTINGS_STATE *const s) +{ + const int32_t choice = UI_Requester_Control(&s->req); + if (choice == UI_REQUESTER_CANCEL) { + return true; + } + const int32_t sel = UI_Requester_GetCurrentRow(&s->req); + if (g_InputDB.menu_left && sel >= 0) { + M_RequestChange(sel, -1); + } else if (g_InputDB.menu_right && sel >= 0) { + M_RequestChange(sel, +1); + } + return false; +} + +void UI_SoundSettings(UI_SOUND_SETTINGS_STATE *const s) +{ + const int32_t sel = UI_Requester_GetCurrentRow(&s->req); + UI_BeginModal(0.5f, 0.6f); + UI_BeginRequester(&s->req, GS(SOUND_DIALOG_TITLE)); + + // Measure the maximum width of the value label to prevent the entire + // dialog from changing its size as the player changes the sound levels. + float value_w = -1.0f; + UI_Label_Measure("10", &value_w, nullptr); + + for (int32_t i = 0; i < s->req.max_rows; ++i) { + if (!UI_Requester_IsRowVisible(&s->req, i)) { + UI_BeginResize(-1.0f, 0.0f); + } else { + UI_BeginResize(-1.0f, -1.0f); + } + UI_BeginRequesterRow(&s->req, i); + + UI_BeginStackEx((UI_STACK_SETTINGS) { + .orientation = UI_STACK_HORIZONTAL, + .align = { .h = UI_STACK_H_ALIGN_DISTRIBUTE }, + }); + UI_Label(GameString_Get(m_Labels[i])); + UI_Spacer(20.0f, 0.0f); + + UI_BeginStackEx((UI_STACK_SETTINGS) { + .orientation = UI_STACK_HORIZONTAL, + .align = { .h = UI_STACK_H_ALIGN_DISTRIBUTE }, + .spacing = { .h = 5.0f }, + }); + UI_BeginHide(i != sel || !M_CanChange(i, -1)); + UI_Label("\\{button left}"); + UI_EndHide(); + + UI_BeginResize(value_w, -1.0f); + UI_BeginAnchor(0.5f, 0.5f); + UI_Label(M_FormatRowValue(i)); + UI_EndAnchor(); + UI_EndResize(); + + UI_BeginHide(i != sel || !M_CanChange(i, +1)); + UI_Label("\\{button right}"); + UI_EndHide(); + UI_EndStack(); + UI_EndStack(); + + UI_EndRequesterRow(&s->req, i); + UI_EndResize(); + } + + UI_EndRequester(&s->req); + UI_EndModal(); +} diff --git a/src/libtrx/game/ui/elements/stack.c b/src/libtrx/game/ui/elements/stack.c index d8a460a33..6638b775b 100644 --- a/src/libtrx/game/ui/elements/stack.c +++ b/src/libtrx/game/ui/elements/stack.c @@ -114,7 +114,7 @@ static void M_Layout( int32_t child_count = 0; float total_child_main_size = 0.0f; UI_NODE *child = node->first_child; - while (child != NULL) { + while (child != nullptr) { switch (data->settings.orientation) { case UI_STACK_HORIZONTAL: total_child_main_size += child->measure_w; diff --git a/src/libtrx/include/libtrx/game/game_string.def b/src/libtrx/include/libtrx/game/game_string.def index 63a70fe0d..b1cadca94 100644 --- a/src/libtrx/include/libtrx/game/game_string.def +++ b/src/libtrx/include/libtrx/game/game_string.def @@ -132,7 +132,9 @@ GS_DEFINE(PASSPORT_MODE_NEW_GAME_JP_PLUS, "Japanese NG+") GS_DEFINE(PASSPORT_STORY_SO_FAR, "Story so far...") GS_DEFINE(PASSPORT_LEGACY_SELECT_LEVEL_1, "Legacy saves do not") GS_DEFINE(PASSPORT_LEGACY_SELECT_LEVEL_2, "support this feature.") -GS_DEFINE(SOUND_SET_VOLUMES, "Set Volumes") +GS_DEFINE(SOUND_DIALOG_TITLE, "Set Volumes") +GS_DEFINE(SOUND_DIALOG_SOUND, "\\{icon music} Music") +GS_DEFINE(SOUND_DIALOG_MUSIC, "\\{icon sound} Sound") GS_DEFINE(OSD_TRAPEZOID_FILTER_ON, "Trapezoid filter enabled") GS_DEFINE(OSD_TRAPEZOID_FILTER_OFF, "Trapezoid filter disabled") GS_DEFINE(DETAIL_INTEGER_FMT, "%d") diff --git a/src/libtrx/include/libtrx/game/music/common.h b/src/libtrx/include/libtrx/game/music/common.h index 68c3c3838..1e6ee1f85 100644 --- a/src/libtrx/include/libtrx/game/music/common.h +++ b/src/libtrx/include/libtrx/game/music/common.h @@ -31,3 +31,15 @@ extern void Music_Unpause(void); void Music_ResetTrackFlags(void); uint16_t Music_GetTrackFlags(int32_t track_idx); void Music_SetTrackFlags(int32_t track, uint16_t flags); + +// Gets the minimum possible game volume. +extern int32_t Music_GetMinVolume(void); + +// Gets the maximum possible game volume. +extern int32_t Music_GetMaxVolume(void); + +// Gets the game volume. +extern int32_t Music_GetVolume(void); + +// Sets the game volume. +extern void Music_SetVolume(int32_t volume); diff --git a/src/libtrx/include/libtrx/game/sound/common.h b/src/libtrx/include/libtrx/game/sound/common.h index 374320fe5..144a322d8 100644 --- a/src/libtrx/include/libtrx/game/sound/common.h +++ b/src/libtrx/include/libtrx/game/sound/common.h @@ -14,6 +14,11 @@ int16_t *Sound_GetSampleLUT(void); SAMPLE_INFO *Sound_GetSampleInfo(SOUND_EFFECT_ID sfx_num); SAMPLE_INFO *Sound_GetSampleInfoByIdx(int32_t info_idx); +extern int32_t Sound_GetMinVolume(void); +extern int32_t Sound_GetMaxVolume(void); +extern int32_t Sound_GetMasterVolume(void); +extern void Sound_SetMasterVolume(int32_t volume); + void Sound_ResetSources(void); void Sound_PauseAll(void); void Sound_UnpauseAll(void); diff --git a/src/libtrx/include/libtrx/game/ui.h b/src/libtrx/include/libtrx/game/ui.h index 811c320db..fd8a7a341 100644 --- a/src/libtrx/include/libtrx/game/ui.h +++ b/src/libtrx/include/libtrx/game/ui.h @@ -10,6 +10,7 @@ #include "./ui/dialogs/play_any_level.h" #include "./ui/dialogs/save_slot.h" #include "./ui/dialogs/select_level.h" +#include "./ui/dialogs/sound_settings.h" #include "./ui/dialogs/stats.h" #include "./ui/elements/anchor.h" #include "./ui/elements/fade.h" diff --git a/src/libtrx/include/libtrx/game/ui/dialogs/sound_settings.h b/src/libtrx/include/libtrx/game/ui/dialogs/sound_settings.h new file mode 100644 index 000000000..d3bbd128d --- /dev/null +++ b/src/libtrx/include/libtrx/game/ui/dialogs/sound_settings.h @@ -0,0 +1,21 @@ +// UI dialog for adjusting music and sound volumes +#pragma once + +#include "../common.h" + +typedef struct UI_SOUND_SETTINGS_STATE UI_SOUND_SETTINGS_STATE; + +// state functions +// Initialize the sound settings dialog state +UI_SOUND_SETTINGS_STATE *UI_SoundSettings_Init(void); + +// Free resources used by the sound settings dialog +void UI_SoundSettings_Free(UI_SOUND_SETTINGS_STATE *s); + +// Handle input/control for the sound settings dialog +// Returns true if the dialog should be closed +bool UI_SoundSettings_Control(UI_SOUND_SETTINGS_STATE *s); + +// draw functions +// Render the sound settings dialog +void UI_SoundSettings(UI_SOUND_SETTINGS_STATE *s); diff --git a/src/libtrx/meson.build b/src/libtrx/meson.build index d3866bca2..98396cb73 100644 --- a/src/libtrx/meson.build +++ b/src/libtrx/meson.build @@ -216,6 +216,7 @@ sources = [ 'game/ui/dialogs/play_any_level.c', 'game/ui/dialogs/save_slot.c', 'game/ui/dialogs/select_level.c', + 'game/ui/dialogs/sound_settings.c', 'game/ui/dialogs/stats.c', 'game/ui/elements/anchor.c', 'game/ui/elements/fade.c', diff --git a/src/tr1/game/music.c b/src/tr1/game/music.c index c4700d9f1..6a0467c8a 100644 --- a/src/tr1/game/music.c +++ b/src/tr1/game/music.c @@ -182,12 +182,12 @@ void Music_Unmute(void) M_SyncVolume(m_AudioStreamID); } -int16_t Music_GetVolume(void) +int32_t Music_GetVolume(void) { return m_Volume; } -void Music_SetVolume(int16_t volume) +void Music_SetVolume(int32_t volume) { if (volume != m_Volume) { m_Volume = volume; @@ -195,16 +195,6 @@ void Music_SetVolume(int16_t volume) } } -int16_t Music_GetMinVolume(void) -{ - return 0; -} - -int16_t Music_GetMaxVolume(void) -{ - return 10; -} - void Music_Pause(void) { if (m_AudioStreamID < 0) { diff --git a/src/tr1/game/music.h b/src/tr1/game/music.h index 97de0c9ad..32957af65 100644 --- a/src/tr1/game/music.h +++ b/src/tr1/game/music.h @@ -19,18 +19,6 @@ void Music_Mute(void); // Unmutes the game music. Doesn't change the music volume. void Music_Unmute(void); -// Gets the game volume. -int16_t Music_GetVolume(void); - -// Sets the game volume. Value can be 0-10. -void Music_SetVolume(int16_t volume); - -// Gets the minimum possible game volume. -int16_t Music_GetMinVolume(void); - -// Gets the maximum possible game volume. -int16_t Music_GetMaxVolume(void); - // Returns the currently playing track. Includes looped music. MUSIC_TRACK_ID Music_GetCurrentPlayingTrack(void); diff --git a/src/tr1/game/option/option.c b/src/tr1/game/option/option.c index 957cc80d6..ca778692f 100644 --- a/src/tr1/game/option/option.c +++ b/src/tr1/game/option/option.c @@ -168,6 +168,9 @@ void Option_Draw(INVENTORY_ITEM *const inv_item) case O_COMPASS_OPTION: Option_Compass_Draw(); break; + case O_SOUND_OPTION: + Option_Sound_Draw(inv_item); + break; case O_PICKUP_OPTION_1: case O_PICKUP_OPTION_2: diff --git a/src/tr1/game/option/option_sound.c b/src/tr1/game/option/option_sound.c index 0af6b0a3c..0777a6d6f 100644 --- a/src/tr1/game/option/option_sound.c +++ b/src/tr1/game/option/option_sound.c @@ -1,170 +1,48 @@ #include "game/option/option_sound.h" -#include "game/game_string.h" -#include "game/input.h" -#include "game/music.h" -#include "game/sound.h" -#include "game/text.h" -#include "global/vars.h" - #include +#include -#include +typedef struct { + UI_SOUND_SETTINGS_STATE *ui; +} M_PRIV; -typedef enum { - TEXT_MUSIC_VOLUME = 0, - TEXT_SOUND_VOLUME = 1, - TEXT_TITLE = 2, - TEXT_TITLE_BORDER = 3, - TEXT_LEFT_ARROW = 4, - TEXT_RIGHT_ARROW = 5, - TEXT_NUMBER_OF = 6, - TEXT_OPTION_MIN = TEXT_MUSIC_VOLUME, - TEXT_OPTION_MAX = TEXT_SOUND_VOLUME, -} SOUND_TEXT; +static M_PRIV m_Priv = {}; -static TEXTSTRING *m_Text[TEXT_NUMBER_OF] = {}; - -static void M_InitText(void); - -static void M_InitText(void) +static void M_Init(M_PRIV *const p) { - char buf[20]; + p->ui = UI_SoundSettings_Init(); +} - m_Text[TEXT_LEFT_ARROW] = Text_Create(-45, 0, "\\{button left}"); - m_Text[TEXT_RIGHT_ARROW] = Text_Create(40, 0, "\\{button right}"); - - m_Text[TEXT_TITLE_BORDER] = Text_Create(0, -32, " "); - m_Text[TEXT_TITLE] = Text_Create(0, -30, GS(SOUND_SET_VOLUMES)); - - if (g_Config.audio.music_volume > 10) { - g_Config.audio.music_volume = 10; - } - sprintf(buf, "\\{icon music} %2d", g_Config.audio.music_volume); - m_Text[TEXT_MUSIC_VOLUME] = Text_Create(0, 0, buf); - - if (g_Config.audio.sound_volume > 10) { - g_Config.audio.sound_volume = 10; - } - sprintf(buf, "\\{icon sound} %2d", g_Config.audio.sound_volume); - m_Text[TEXT_SOUND_VOLUME] = Text_Create(0, 25, buf); - - Text_AddBackground(m_Text[g_OptionSelected], 128, 0, 0, 0, TS_REQUESTED); - Text_AddOutline(m_Text[g_OptionSelected], TS_REQUESTED); - Text_AddBackground(m_Text[TEXT_TITLE], 136, 0, 0, 0, TS_HEADING); - Text_AddOutline(m_Text[TEXT_TITLE], TS_HEADING); - Text_AddBackground(m_Text[TEXT_TITLE_BORDER], 140, 85, 0, 0, TS_BACKGROUND); - Text_AddOutline(m_Text[TEXT_TITLE_BORDER], TS_BACKGROUND); - - for (int i = 0; i < TEXT_NUMBER_OF; i++) { - Text_CentreH(m_Text[i], 1); - Text_CentreV(m_Text[i], 1); +static void M_Shutdown(M_PRIV *const p) +{ + if (p->ui != nullptr) { + UI_SoundSettings_Free(p->ui); + p->ui = nullptr; } } -void Option_Sound_Control(INVENTORY_ITEM *inv_item, const bool is_busy) +void Option_Sound_Control(INVENTORY_ITEM *const inv_item, const bool is_busy) { + M_PRIV *const p = &m_Priv; if (is_busy) { return; } - - char buf[20]; - - if (!m_Text[TEXT_MUSIC_VOLUME]) { - M_InitText(); + if (p->ui == nullptr) { + M_Init(p); } + UI_SoundSettings_Control(p->ui); +} - if (g_InputDB.menu_up && g_OptionSelected > TEXT_OPTION_MIN) { - Text_RemoveOutline(m_Text[g_OptionSelected]); - Text_RemoveBackground(m_Text[g_OptionSelected]); - --g_OptionSelected; - Text_AddBackground( - m_Text[g_OptionSelected], 128, 0, 0, 0, TS_REQUESTED); - Text_AddOutline(m_Text[g_OptionSelected], TS_REQUESTED); - Text_SetPos(m_Text[TEXT_LEFT_ARROW], -45, 0); - Text_SetPos(m_Text[TEXT_RIGHT_ARROW], 40, 0); - } - - if (g_InputDB.menu_down && g_OptionSelected < TEXT_OPTION_MAX) { - Text_RemoveOutline(m_Text[g_OptionSelected]); - Text_RemoveBackground(m_Text[g_OptionSelected]); - ++g_OptionSelected; - Text_AddBackground( - m_Text[g_OptionSelected], 128, 0, 0, 0, TS_REQUESTED); - Text_AddOutline(m_Text[g_OptionSelected], TS_REQUESTED); - Text_SetPos(m_Text[TEXT_LEFT_ARROW], -45, 25); - Text_SetPos(m_Text[TEXT_RIGHT_ARROW], 40, 25); - } - - switch (g_OptionSelected) { - case TEXT_MUSIC_VOLUME: - if (g_InputDB.menu_left - && g_Config.audio.music_volume > Music_GetMinVolume()) { - g_Config.audio.music_volume--; - Config_Write(); - Music_SetVolume(g_Config.audio.music_volume); - Sound_Effect(SFX_MENU_PASSPORT, nullptr, SPM_ALWAYS); - sprintf(buf, "\\{icon music} %2d", g_Config.audio.music_volume); - Text_ChangeText(m_Text[TEXT_MUSIC_VOLUME], buf); - } else if ( - g_InputDB.menu_right - && g_Config.audio.music_volume < Music_GetMaxVolume()) { - g_Config.audio.music_volume++; - Config_Write(); - Music_SetVolume(g_Config.audio.music_volume); - Sound_Effect(SFX_MENU_PASSPORT, nullptr, SPM_ALWAYS); - sprintf(buf, "\\{icon music} %2d", g_Config.audio.music_volume); - Text_ChangeText(m_Text[TEXT_MUSIC_VOLUME], buf); - } - - Text_Hide( - m_Text[TEXT_LEFT_ARROW], - g_Config.audio.music_volume == Music_GetMinVolume()); - Text_Hide( - m_Text[TEXT_RIGHT_ARROW], - g_Config.audio.music_volume == Music_GetMaxVolume()); - - break; - - case TEXT_SOUND_VOLUME: - if (g_InputDB.menu_left - && g_Config.audio.sound_volume > Sound_GetMinVolume()) { - g_Config.audio.sound_volume--; - Config_Write(); - Sound_SetMasterVolume(g_Config.audio.sound_volume); - Sound_Effect(SFX_MENU_PASSPORT, nullptr, SPM_ALWAYS); - sprintf(buf, "\\{icon sound} %2d", g_Config.audio.sound_volume); - Text_ChangeText(m_Text[TEXT_SOUND_VOLUME], buf); - } else if ( - g_InputDB.menu_right - && g_Config.audio.sound_volume < Sound_GetMaxVolume()) { - g_Config.audio.sound_volume++; - Config_Write(); - Sound_SetMasterVolume(g_Config.audio.sound_volume); - Sound_Effect(SFX_MENU_PASSPORT, nullptr, SPM_ALWAYS); - sprintf(buf, "\\{icon sound} %2d", g_Config.audio.sound_volume); - Text_ChangeText(m_Text[TEXT_SOUND_VOLUME], buf); - } - - Text_Hide( - m_Text[TEXT_LEFT_ARROW], - g_Config.audio.sound_volume == Sound_GetMinVolume()); - Text_Hide( - m_Text[TEXT_RIGHT_ARROW], - g_Config.audio.sound_volume == Sound_GetMaxVolume()); - - break; - } - - if (g_InputDB.menu_confirm || g_InputDB.menu_back) { - Option_Sound_Shutdown(); +void Option_Sound_Draw(INVENTORY_ITEM *const inv_item) +{ + M_PRIV *const p = &m_Priv; + if (p->ui != nullptr) { + UI_SoundSettings(p->ui); } } void Option_Sound_Shutdown(void) { - for (int i = 0; i < TEXT_NUMBER_OF; i++) { - Text_Remove(m_Text[i]); - m_Text[i] = nullptr; - } + M_Shutdown(&m_Priv); } diff --git a/src/tr1/game/option/option_sound.h b/src/tr1/game/option/option_sound.h index 9128617d5..ee5f63ba7 100644 --- a/src/tr1/game/option/option_sound.h +++ b/src/tr1/game/option/option_sound.h @@ -3,4 +3,5 @@ #include void Option_Sound_Control(INVENTORY_ITEM *inv_item, bool is_busy); +void Option_Sound_Draw(INVENTORY_ITEM *inv_item); void Option_Sound_Shutdown(void); diff --git a/src/tr1/game/sound.c b/src/tr1/game/sound.c index 3f479d368..7728f2465 100644 --- a/src/tr1/game/sound.c +++ b/src/tr1/game/sound.c @@ -528,18 +528,6 @@ void Sound_StopAll(void) Audio_Sample_CloseAll(); } -void Sound_SetMasterVolume(int8_t volume) -{ - int8_t raw_volume = volume ? 6 * volume + 3 : 0; - m_MasterVolumeDefault = raw_volume & 0x3F; - m_MasterVolume = raw_volume & 0x3F; -} - -int8_t Sound_GetMasterVolume(void) -{ - return (m_MasterVolume - 3) / 6; -} - int32_t Sound_GetMinVolume(void) { return 0; @@ -550,6 +538,18 @@ int32_t Sound_GetMaxVolume(void) return 10; } +void Sound_SetMasterVolume(int32_t volume) +{ + int8_t raw_volume = volume ? 6 * volume + 3 : 0; + m_MasterVolumeDefault = raw_volume & 0x3F; + m_MasterVolume = raw_volume & 0x3F; +} + +int32_t Sound_GetMasterVolume(void) +{ + return (m_MasterVolume - 3) / 6; +} + void Sound_ResetAmbient(void) { M_ResetAmbientLoudness(); diff --git a/src/tr1/game/sound.h b/src/tr1/game/sound.h index 4cd892222..9a403a6c6 100644 --- a/src/tr1/game/sound.h +++ b/src/tr1/game/sound.h @@ -13,10 +13,6 @@ bool Sound_StopEffect(SOUND_EFFECT_ID sfx_num, const XYZ_32 *pos); void Sound_UpdateEffects(void); void Sound_ResetEffects(void); void Sound_StopAmbientSounds(void); -int8_t Sound_GetMasterVolume(void); -void Sound_SetMasterVolume(int8_t volume); -int32_t Sound_GetMinVolume(void); -int32_t Sound_GetMaxVolume(void); void Sound_LoadSamples( size_t num_samples, const char **sample_pointers, size_t *sizes); int32_t Sound_GetMaxSamples(void); diff --git a/src/tr2/game/option/option_sound.c b/src/tr2/game/option/option_sound.c index f6cfab736..f5dec720f 100644 --- a/src/tr2/game/option/option_sound.c +++ b/src/tr2/game/option/option_sound.c @@ -1,132 +1,48 @@ -#include "game/game_string.h" -#include "game/input.h" -#include "game/inventory_ring.h" -#include "game/music.h" #include "game/option/option.h" -#include "game/sound.h" -#include "game/text.h" -#include "global/vars.h" #include -#include +#include -#include +typedef struct { + UI_SOUND_SETTINGS_STATE *ui; +} M_PRIV; -static TEXTSTRING *m_SoundText[4]; +static M_PRIV m_Priv = {}; -static void M_InitText(void); -static void M_ShutdownText(void); - -static void M_InitText(void) +static void M_Init(M_PRIV *const p) { - CLAMPG(g_Config.audio.music_volume, 10); - CLAMPG(g_Config.audio.sound_volume, 10); + p->ui = UI_SoundSettings_Init(); +} - char text[32]; - sprintf(text, "\\{icon music} %2d", g_Config.audio.music_volume); - m_SoundText[0] = Text_Create(0, 0, text); - Text_AddBackground(m_SoundText[0], 128, 0, 0, 0, TS_REQUESTED); - Text_AddOutline(m_SoundText[0], TS_REQUESTED); - - sprintf(text, "\\{icon sound} %2d", g_Config.audio.sound_volume); - m_SoundText[1] = Text_Create(0, 25, text); - - m_SoundText[2] = Text_Create(0, -32, " "); - Text_AddBackground(m_SoundText[2], 140, 85, 0, 0, TS_BACKGROUND); - Text_AddOutline(m_SoundText[2], TS_BACKGROUND); - - m_SoundText[3] = Text_Create(0, -30, GS(SOUND_SET_VOLUMES)); - Text_AddBackground(m_SoundText[3], 136, 0, 0, 0, TS_HEADING); - Text_AddOutline(m_SoundText[3], TS_HEADING); - - for (int32_t i = 0; i < 4; i++) { - Text_CentreH(m_SoundText[i], true); - Text_CentreV(m_SoundText[i], true); +static void M_Shutdown(M_PRIV *const p) +{ + if (p->ui != nullptr) { + UI_SoundSettings_Free(p->ui); + p->ui = nullptr; } } -static void M_ShutdownText(void) +void Option_Sound_Control(INVENTORY_ITEM *const inv_item, const bool is_busy) { - for (int32_t i = 0; i < 4; i++) { - Text_Remove(m_SoundText[i]); - m_SoundText[i] = nullptr; + M_PRIV *const p = &m_Priv; + if (is_busy) { + return; + } + if (p->ui == nullptr) { + M_Init(p); + } + UI_SoundSettings_Control(p->ui); +} + +void Option_Sound_Draw(INVENTORY_ITEM *const inv_item) +{ + M_PRIV *const p = &m_Priv; + if (p->ui != nullptr) { + UI_SoundSettings(p->ui); } } void Option_Sound_Shutdown(void) { - M_ShutdownText(); -} - -void Option_Sound_Control(INVENTORY_ITEM *const item, const bool is_busy) -{ - if (is_busy) { - return; - } - - char text[32]; - - if (m_SoundText[0] == nullptr) { - M_InitText(); - } - - if (g_InputDB.menu_up && g_SoundOptionLine > 0) { - Text_RemoveOutline(m_SoundText[g_SoundOptionLine]); - Text_RemoveBackground(m_SoundText[g_SoundOptionLine]); - g_SoundOptionLine--; - Text_AddBackground( - m_SoundText[g_SoundOptionLine], 128, 0, 0, 0, TS_REQUESTED); - Text_AddOutline(m_SoundText[g_SoundOptionLine], TS_REQUESTED); - } - - if (g_InputDB.menu_down && g_SoundOptionLine < 1) { - Text_RemoveOutline(m_SoundText[g_SoundOptionLine]); - Text_RemoveBackground(m_SoundText[g_SoundOptionLine]); - g_SoundOptionLine++; - Text_AddBackground( - m_SoundText[g_SoundOptionLine], 128, 0, 0, 0, TS_REQUESTED); - Text_AddOutline(m_SoundText[g_SoundOptionLine], TS_REQUESTED); - } - - if (g_SoundOptionLine) { - bool changed = false; - if (g_InputDB.menu_left && g_Config.audio.sound_volume > 0) { - g_Config.audio.sound_volume--; - changed = true; - } else if (g_InputDB.menu_right && g_Config.audio.sound_volume < 10) { - g_Config.audio.sound_volume++; - changed = true; - } - - if (changed) { - sprintf(text, "\\{icon sound} %2d", g_Config.audio.sound_volume); - Text_ChangeText(m_SoundText[1], text); - Sound_SetMasterVolume(g_Config.audio.sound_volume); - Sound_Effect(SFX_MENU_PASSPORT, nullptr, SPM_ALWAYS); - } - } else { - bool changed = false; - if (g_InputDB.menu_left && g_Config.audio.music_volume > 0) { - g_Config.audio.music_volume--; - changed = true; - } else if (g_InputDB.menu_right && g_Config.audio.music_volume < 10) { - g_Config.audio.music_volume++; - changed = true; - } - - if (changed) { - sprintf(text, "\\{icon music} %2d", g_Config.audio.music_volume); - Text_ChangeText(m_SoundText[0], text); - Music_SetVolume(g_Config.audio.music_volume); - Sound_Effect(SFX_MENU_PASSPORT, nullptr, SPM_ALWAYS); - } - } - - if (g_InputDB.menu_confirm || g_InputDB.menu_back) { - Option_Sound_Shutdown(); - } -} - -void Option_Sound_Draw(INVENTORY_ITEM *const item) -{ + M_Shutdown(&m_Priv); } diff --git a/src/tr2/game/sound.h b/src/tr2/game/sound.h index 8b0fc32ad..53b5e88ca 100644 --- a/src/tr2/game/sound.h +++ b/src/tr2/game/sound.h @@ -9,9 +9,6 @@ void Sound_Init(void); void Sound_Shutdown(void); -void Sound_SetMasterVolume(int32_t volume); void Sound_UpdateEffects(void); void Sound_StopEffect(SOUND_EFFECT_ID sample_id); void Sound_EndScene(void); -int32_t Sound_GetMinVolume(void); -int32_t Sound_GetMaxVolume(void);