diff --git a/data/tr2/ship/cfg/TR2X_strings.json5 b/data/tr2/ship/cfg/TR2X_strings.json5 index 81f5f45c5..02080ac0a 100644 --- a/data/tr2/ship/cfg/TR2X_strings.json5 +++ b/data/tr2/ship/cfg/TR2X_strings.json5 @@ -471,12 +471,32 @@ "CONTROLS_CUSTOM_2": "User Keys 2", "CONTROLS_CUSTOM_3": "User Keys 3", "CONTROLS_DEFAULT_KEYS": "Default Keys", + "DETAIL_ASPECT_MODE": "Aspect mode", + "DETAIL_ASPECT_MODE_16_9": "16:9", + "DETAIL_ASPECT_MODE_4_3": "4:3", + "DETAIL_ASPECT_MODE_ANY": "Any", + "DETAIL_BILINEAR": "Bilinear", + "DETAIL_DEPTH_BUFFER": "Z-Buffer", "DETAIL_FLOAT_FMT": "%.1f", "DETAIL_FOG_END": "Fog end", "DETAIL_FOG_START": "Fog start", "DETAIL_FOV": "Field of view", + "DETAIL_FPS": "FPS", "DETAIL_INTEGER_FMT": "%d", + "DETAIL_LIGHTING_CONTRAST": "Lighting contrast", + "DETAIL_LIGHTING_CONTRAST_HIGH": "High", + "DETAIL_LIGHTING_CONTRAST_LOW": "Low", + "DETAIL_LIGHTING_CONTRAST_MEDIUM": "Medium", + "DETAIL_RENDER_MODE": "Render mode", + "DETAIL_RENDER_MODE_HARDWARE": "Hardware", + "DETAIL_RENDER_MODE_SOFTWARE": "Software", + "DETAIL_SCALER": "Scaler", + "DETAIL_SIZER": "Sizer", + "DETAIL_TEXTURE_FILTER": "Texture filter", "DETAIL_TITLE": "Graphic Options", + "DETAIL_TRAPEZOID_FILTER": "Trapezoid filter", + "DETAIL_UI_BAR_SCALE": "UI bar scale", + "DETAIL_UI_TEXT_SCALE": "UI text scale", "DETAIL_USE_PSX_FOV": "Use PSX FOV", "DETAIL_WATER_COLOR_B": "Water color (B)", "DETAIL_WATER_COLOR_G": "Water color (G)", diff --git a/docs/tr2/CHANGELOG.md b/docs/tr2/CHANGELOG.md index 4b0ceb3ca..ba60c7e14 100644 --- a/docs/tr2/CHANGELOG.md +++ b/docs/tr2/CHANGELOG.md @@ -45,6 +45,7 @@ - improved pause exit dialog - it can now be canceled with escape - removed the need to specify in the game flow levels that have no secrets (secrets will be automatically counted) (#1582) - removed the hard-coded end-level behaviour of the bird guardian for custom levels (#1583) +- removed the FPS and aspect mode options from the config tool (now available in-game in the graphics options) ## [0.10](https://github.com/LostArtefacts/TRX/compare/tr2-0.9.2...tr2-0.10) - 2025-03-18 - added support for 60 FPS rendering diff --git a/src/libtrx/include/libtrx/game/game_string.def b/src/libtrx/include/libtrx/game/game_string.def index beab0311a..c4a85dfb9 100644 --- a/src/libtrx/include/libtrx/game/game_string.def +++ b/src/libtrx/include/libtrx/game/game_string.def @@ -135,9 +135,16 @@ GS_DEFINE(OSD_TRAPEZOID_FILTER_OFF, "Trapezoid filter disabled") GS_DEFINE(DETAIL_INTEGER_FMT, "%d") GS_DEFINE(DETAIL_FLOAT_FMT, "%.1f") GS_DEFINE(DETAIL_TITLE, "Graphic Options") +GS_DEFINE(DETAIL_FPS, "FPS") GS_DEFINE(DETAIL_FOG_START, "Fog start") GS_DEFINE(DETAIL_FOG_END, "Fog end") GS_DEFINE(DETAIL_WATER_COLOR_R, "Water color (R)") GS_DEFINE(DETAIL_WATER_COLOR_G, "Water color (G)") GS_DEFINE(DETAIL_WATER_COLOR_B, "Water color (B)") +GS_DEFINE(DETAIL_TEXTURE_FILTER, "Texture filter") +GS_DEFINE(DETAIL_BILINEAR, "Bilinear") +GS_DEFINE(DETAIL_TRAPEZOID_FILTER, "Trapezoid filter") +GS_DEFINE(DETAIL_RENDER_MODE, "Render mode") +GS_DEFINE(DETAIL_UI_TEXT_SCALE, "UI text scale") +GS_DEFINE(DETAIL_UI_BAR_SCALE, "UI bar scale") GS_DEFINE(PAGINATION_NAV, "%d / %d") diff --git a/src/tr1/game/game_string.def b/src/tr1/game/game_string.def index 7b77a46a2..1f28710f0 100644 --- a/src/tr1/game/game_string.def +++ b/src/tr1/game/game_string.def @@ -2,17 +2,10 @@ GS_DEFINE(PASSPORT_RESTART_LEVEL, "Restart Level") 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(DETAIL_FPS, "FPS") -GS_DEFINE(DETAIL_TRAPEZOID_FILTER, "Trapezoid filter") GS_DEFINE(DETAIL_REFLECTIONS, "Reflections") -GS_DEFINE(DETAIL_BILINEAR, "Bilinear") -GS_DEFINE(DETAIL_TEXTURE_FILTER, "Texture filter") GS_DEFINE(DETAIL_FBO_FILTER, "FBO filter") GS_DEFINE(DETAIL_VSYNC, "VSync") GS_DEFINE(DETAIL_BRIGHTNESS, "Brightness") -GS_DEFINE(DETAIL_UI_TEXT_SCALE, "UI text scale") -GS_DEFINE(DETAIL_UI_BAR_SCALE, "UI bar scale") -GS_DEFINE(DETAIL_RENDER_MODE, "Render mode") GS_DEFINE(DETAIL_RENDER_MODE_LEGACY, "Window size") GS_DEFINE(DETAIL_RENDER_MODE_FBO, "Framebuffer") GS_DEFINE(DETAIL_RESOLUTION, "Resolution") diff --git a/src/tr2/game/game_string.def b/src/tr2/game/game_string.def index 7dee247d8..6c4ac4e2f 100644 --- a/src/tr2/game/game_string.def +++ b/src/tr2/game/game_string.def @@ -44,3 +44,16 @@ GS_DEFINE(OSD_PERSPECTIVE_FILTER_ON, "Perspective correction: on") GS_DEFINE(OSD_PERSPECTIVE_FILTER_OFF, "Perspective correction: off") GS_DEFINE(DETAIL_FOV, "Field of view") GS_DEFINE(DETAIL_USE_PSX_FOV, "Use PSX FOV") +GS_DEFINE(DETAIL_DEPTH_BUFFER, "Z-Buffer") +GS_DEFINE(DETAIL_LIGHTING_CONTRAST, "Lighting contrast") +GS_DEFINE(DETAIL_LIGHTING_CONTRAST_LOW, "Low") +GS_DEFINE(DETAIL_LIGHTING_CONTRAST_MEDIUM, "Medium") +GS_DEFINE(DETAIL_LIGHTING_CONTRAST_HIGH, "High") +GS_DEFINE(DETAIL_RENDER_MODE_SOFTWARE, "Software") +GS_DEFINE(DETAIL_RENDER_MODE_HARDWARE, "Hardware") +GS_DEFINE(DETAIL_ASPECT_MODE, "Aspect mode") +GS_DEFINE(DETAIL_ASPECT_MODE_4_3, "4:3") +GS_DEFINE(DETAIL_ASPECT_MODE_16_9, "16:9") +GS_DEFINE(DETAIL_ASPECT_MODE_ANY, "Any") +GS_DEFINE(DETAIL_SCALER, "Scaler") +GS_DEFINE(DETAIL_SIZER, "Sizer") diff --git a/src/tr2/game/ui/dialogs/graphic_settings.c b/src/tr2/game/ui/dialogs/graphic_settings.c index 025f085b3..a9f774e10 100644 --- a/src/tr2/game/ui/dialogs/graphic_settings.c +++ b/src/tr2/game/ui/dialogs/graphic_settings.c @@ -24,10 +24,65 @@ typedef struct { int32_t max_value; int32_t delta_slow; int32_t delta_fast; - int32_t misc; + const void *misc; } M_OPTION; -static M_OPTION m_Options[] = { +typedef struct { + int32_t value; + GAME_STRING_ID name; +} M_ENUM_ENTRY; + +typedef struct { + const M_ENUM_ENTRY *entry; + int32_t position; + int32_t count; +} M_ENUM_LOOKUP; + +static const M_ENUM_ENTRY m_TextureFilterOptions[] = { + // clang-format off + { GFX_TF_NN, GS_ID(MISC_OFF), }, + { GFX_TF_BILINEAR, GS_ID(DETAIL_BILINEAR), }, + { -1, nullptr, }, + // clang-format on +}; + +static const M_ENUM_ENTRY m_LightingContrastOptions[] = { + // clang-format off + { LIGHTING_CONTRAST_LOW, GS_ID(DETAIL_LIGHTING_CONTRAST_LOW), }, + { LIGHTING_CONTRAST_MEDIUM, GS_ID(DETAIL_LIGHTING_CONTRAST_MEDIUM), }, + { LIGHTING_CONTRAST_HIGH, GS_ID(DETAIL_LIGHTING_CONTRAST_HIGH), }, + { -1, nullptr, }, + // clang-format on +}; + +static const M_ENUM_ENTRY m_RenderModeOptions[] = { + // clang-format off + { RM_SOFTWARE, GS_ID(DETAIL_RENDER_MODE_SOFTWARE), }, + { RM_HARDWARE, GS_ID(DETAIL_RENDER_MODE_HARDWARE), }, + { -1, nullptr, }, + // clang-format on +}; + +static const M_ENUM_ENTRY m_AspectModeOptions[] = { + // clang-format off + { AM_4_3, GS_ID(DETAIL_ASPECT_MODE_4_3), }, + { AM_16_9, GS_ID(DETAIL_ASPECT_MODE_16_9), }, + { AM_ANY, GS_ID(DETAIL_ASPECT_MODE_ANY), }, + { -1, nullptr, }, + // clang-format on +}; + +static const M_OPTION m_Options[] = { + { + .option_type = COT_INT32, + .label_id = GS_ID(DETAIL_FPS), + .target = &g_Config.rendering.fps, + .min_value = 30, + .max_value = 60, + .delta_slow = 30, + .delta_fast = 30, + }, + { .option_type = COT_INT32, .label_id = GS_ID(DETAIL_FOG_START), @@ -52,7 +107,7 @@ static M_OPTION m_Options[] = { .max_value = 255, .delta_slow = 1, .delta_fast = 10, - .misc = 0, + .misc = (void *)(intptr_t)0, }, { @@ -63,7 +118,7 @@ static M_OPTION m_Options[] = { .max_value = 255, .delta_slow = 1, .delta_fast = 10, - .misc = 1, + .misc = (void *)(intptr_t)1, }, { @@ -74,7 +129,7 @@ static M_OPTION m_Options[] = { .max_value = 255, .delta_slow = 1, .delta_fast = 10, - .misc = 2, + .misc = (void *)(intptr_t)2, }, { @@ -93,12 +148,101 @@ static M_OPTION m_Options[] = { .target = &g_Config.visuals.use_psx_fov, }, + { + .option_type = COT_ENUM, + .label_id = GS_ID(DETAIL_TEXTURE_FILTER), + .target = &g_Config.rendering.texture_filter, + .delta_slow = 1, + .delta_fast = 1, + .misc = m_TextureFilterOptions, + }, + + { + .option_type = COT_BOOL, + .label_id = GS_ID(DETAIL_TRAPEZOID_FILTER), + .target = &g_Config.rendering.enable_trapezoid_filter, + }, + + { + .option_type = COT_BOOL, + .label_id = GS_ID(DETAIL_DEPTH_BUFFER), + .target = &g_Config.rendering.enable_zbuffer, + }, + + { + .option_type = COT_ENUM, + .label_id = GS_ID(DETAIL_LIGHTING_CONTRAST), + .target = &g_Config.rendering.lighting_contrast, + .delta_slow = 1, + .delta_fast = 1, + .misc = m_LightingContrastOptions, + }, + + { + .option_type = COT_ENUM, + .label_id = GS_ID(DETAIL_RENDER_MODE), + .target = &g_Config.rendering.render_mode, + .delta_slow = 1, + .delta_fast = 1, + .misc = m_RenderModeOptions, + }, + + { + .option_type = COT_ENUM, + .label_id = GS_ID(DETAIL_ASPECT_MODE), + .target = &g_Config.rendering.aspect_mode, + .delta_slow = 1, + .delta_fast = 1, + .misc = m_AspectModeOptions, + }, + + { + .option_type = COT_DOUBLE, + .label_id = GS_ID(DETAIL_UI_TEXT_SCALE), + .target = &g_Config.ui.text_scale, + .min_value = 50, + .max_value = 200, + .delta_slow = 10, + .delta_fast = 10, + }, + + { + .option_type = COT_DOUBLE, + .label_id = GS_ID(DETAIL_UI_BAR_SCALE), + .target = &g_Config.ui.bar_scale, + .min_value = 50, + .max_value = 200, + .delta_slow = 10, + .delta_fast = 10, + }, + + { + .option_type = COT_INT32, + .label_id = GS_ID(DETAIL_SCALER), + .target = &g_Config.rendering.scaler, + .min_value = 1, + .max_value = 4, + .delta_slow = 1, + .delta_fast = 1, + }, + + { + .option_type = COT_FLOAT, + .label_id = GS_ID(DETAIL_SIZER), + .target = &g_Config.rendering.sizer, + .min_value = 40, + .max_value = 200, + .delta_slow = 10, + .delta_fast = 10, + }, + { .target = nullptr, }, }; static uint8_t *M_GetColorComponent(const M_OPTION *option); +static M_ENUM_LOOKUP M_GetEnumEntry(const M_OPTION *option); static char *M_FormatRowValue(int32_t row_idx); static bool M_CanChangeValue(int32_t row_idx, int32_t dir); static bool M_RequestChangeValue(int32_t row_idx, int32_t dir); @@ -106,7 +250,7 @@ static bool M_RequestChangeValue(int32_t row_idx, int32_t dir); static uint8_t *M_GetColorComponent(const M_OPTION *const option) { RGB_888 *const color = option->target; - switch (option->misc) { + switch ((int32_t)(intptr_t)option->misc) { case 0: return &color->r; case 1: @@ -118,6 +262,27 @@ static uint8_t *M_GetColorComponent(const M_OPTION *const option) return nullptr; } +static M_ENUM_LOOKUP M_GetEnumEntry(const M_OPTION *const option) +{ + M_ENUM_LOOKUP result = { + .entry = nullptr, + .position = -1, + .count = 0, + }; + int32_t current_pos = 0; + const M_ENUM_ENTRY *entry = &((M_ENUM_ENTRY *)option->misc)[0]; + while (entry->value != -1) { + if (entry->value == *(int32_t *)option->target) { + result.entry = entry; + result.position = current_pos; + } + entry++; + current_pos++; + result.count++; + } + return result; +} + static char *M_FormatRowValue(const int32_t row_idx) { const M_OPTION *const option = &m_Options[row_idx]; @@ -128,10 +293,19 @@ static char *M_FormatRowValue(const int32_t row_idx) case COT_INT32: return String_Format( GS(DETAIL_INTEGER_FMT), *(int32_t *)option->target); + case COT_DOUBLE: + return String_Format(GS(DETAIL_FLOAT_FMT), *(double *)option->target); + case COT_FLOAT: + return String_Format(GS(DETAIL_FLOAT_FMT), *(float *)option->target); case COT_RGB888: { const uint8_t *const component = M_GetColorComponent(option); return String_Format("%d", *component); } + case COT_ENUM: { + const M_ENUM_LOOKUP enum_lookup = M_GetEnumEntry(option); + ASSERT(enum_lookup.entry != nullptr); + return (char *)GameString_Get(enum_lookup.entry->name); + } default: break; } @@ -151,6 +325,20 @@ static bool M_CanChangeValue(const int32_t row_idx, const int32_t dir) return *(int32_t *)option->target < option->max_value; } break; + case COT_DOUBLE: + if (dir < 0) { + return *(double *)option->target > (double)option->min_value / 100; + } else if (dir > 0) { + return *(double *)option->target < (double)option->max_value / 100; + } + break; + case COT_FLOAT: + if (dir < 0) { + return *(float *)option->target > (float)option->min_value / 100; + } else if (dir > 0) { + return *(float *)option->target < (float)option->max_value / 100; + } + break; case COT_RGB888: { const uint8_t *const component = M_GetColorComponent(option); if (dir < 0) { @@ -160,6 +348,16 @@ static bool M_CanChangeValue(const int32_t row_idx, const int32_t dir) } break; } + case COT_ENUM: { + const M_ENUM_LOOKUP enum_lookup = M_GetEnumEntry(option); + ASSERT(enum_lookup.entry != nullptr); + if (dir < 0) { + return enum_lookup.position > 0; + } else if (dir > 0) { + return enum_lookup.position < enum_lookup.count - 1; + } + break; + } default: break; } @@ -186,6 +384,12 @@ static bool M_RequestChangeValue(const int32_t row_idx, const int32_t dir) case COT_INT32: *(int32_t *)option->target += delta; break; + case COT_DOUBLE: + *(double *)option->target += (double)delta / 100; + break; + case COT_FLOAT: + *(float *)option->target += (float)delta / 100; + break; case COT_RGB888: { uint8_t *const component = M_GetColorComponent(option); int32_t component_i = *component; @@ -194,6 +398,13 @@ static bool M_RequestChangeValue(const int32_t row_idx, const int32_t dir) *component = component_i; break; } + case COT_ENUM: { + const M_ENUM_LOOKUP enum_lookup = M_GetEnumEntry(option); + const M_ENUM_ENTRY *const next_entry = + &((M_ENUM_ENTRY *)option->misc)[enum_lookup.position + delta]; + *(int32_t *)option->target = next_entry->value; + break; + } default: return false; } @@ -244,7 +455,7 @@ void UI_GraphicSettings(UI_GRAPHIC_SETTINGS_STATE *const s) UI_Label(GameString_Get(m_Options[i].label_id)); UI_Spacer(20.0f, 0.0f); - UI_BeginResize(70.0f, -1.0f); + UI_BeginResize(110.0f, -1.0f); UI_BeginStackEx((UI_STACK_SETTINGS) { .orientation = UI_STACK_HORIZONTAL, .align = { .h = UI_STACK_H_ALIGN_CENTER }, diff --git a/tools/config/TR2X_ConfigTool/Resources/Lang/en.json b/tools/config/TR2X_ConfigTool/Resources/Lang/en.json index 1b8a1e18a..f3f2e01be 100644 --- a/tools/config/TR2X_ConfigTool/Resources/Lang/en.json +++ b/tools/config/TR2X_ConfigTool/Resources/Lang/en.json @@ -6,17 +6,6 @@ "window_title_about": "About TR2X Config Tool", "label_about_details": "Visit the TR2X GitHub page for further information." }, - "Enums": { - "fps": { - "30": "30", - "60": "60" - }, - "aspect_mode": { - "any": "Any", - "16:9": "16:9", - "4:3": "4:3" - } - }, "Properties": { "enable_tr3_sidesteps": { "Title": "Enhanced sidesteps", @@ -26,10 +15,6 @@ "Title": "Enable more responsive passport", "Description": "Disables blocking user input when passport flips pages, scheduling the page flips instead." }, - "fps": { - "Title": "FPS", - "Description": "Controls the framerate at which to render the game." - }, "enable_3d_pickups": { "Title": "3D pickups", "Description": "Enables 3D models to be rendered in place of the sprites for pickup items." @@ -102,10 +87,6 @@ "Title": "Key item pre-selection", "Description": "When Lara presses action against a keyhole or puzzle slot, and she has the corresponding item in the inventory, that item will be pre-selected." }, - "aspect_mode": { - "Title": "Aspect mode", - "Description": "Set the aspect ratio of the game output." - }, "screenshot_format": { "Title": "Screenshot format", "Description": "Screenshot file format." diff --git a/tools/config/TR2X_ConfigTool/Resources/Lang/it.json b/tools/config/TR2X_ConfigTool/Resources/Lang/it.json index 15a1e7c6f..28aa606a9 100644 --- a/tools/config/TR2X_ConfigTool/Resources/Lang/it.json +++ b/tools/config/TR2X_ConfigTool/Resources/Lang/it.json @@ -6,17 +6,6 @@ "window_title_about": "Informazioni sul Programma di configurazione di TR2X", "label_about_details": "Per ulteriori informazioni, visita la pagina GitHub di TR2X." }, - "Enums": { - "fps": { - "30": "30", - "60": "60" - }, - "aspect_mode": { - "any": "Qualsiasi", - "16:9": "16:9", - "4:3": "4:3" - } - }, "Properties": { "enable_tr3_sidesteps": { "Title": "Passi laterali migliorati", @@ -26,10 +15,6 @@ "Title": "Abilita passaporto reattivo", "Description": "Disabilita il blocco dell'input dell'utente mentre scorrono le pagine del passaporto, programmando invece le pagine da sfogliare." }, - "fps": { - "Title": "FPS", - "Description": "Controlla i fotogrammi al secondo a cui eseguire il gioco." - }, "enable_3d_pickups": { "Title": "Oggetti 3D", "Description": "Sostituisce gli oggetti recuperabili 2D con i rispettivi modelli 3D." @@ -102,10 +87,6 @@ "Title": "Preselezione degli oggetti chiave", "Description": "Quando Lara preme azione contro un buco della serratura o un altro ricettacolo e ha l'oggetto corrispondente nell'inventario, quell'oggetto verrà preselezionato." }, - "aspect_mode": { - "Title": "Modalità rapporto d'aspetto", - "Description": "Imposta il rapporto d'aspetto del gioco." - }, "screenshot_format": { "Title": "Formato istantanea dello schermo", "Description": "Formato del file da utilizzare per le istantanee dello schermo." diff --git a/tools/config/TR2X_ConfigTool/Resources/specification.json b/tools/config/TR2X_ConfigTool/Resources/specification.json index 2fa813a6c..e5f4a5b07 100644 --- a/tools/config/TR2X_ConfigTool/Resources/specification.json +++ b/tools/config/TR2X_ConfigTool/Resources/specification.json @@ -4,15 +4,6 @@ "jpg", "png" ], - "fps": [ - "30", - "60" - ], - "aspect_mode": [ - "any", - "16:9", - "4:3" - ], "underwater_music": [ "full", "quiet", @@ -160,18 +151,6 @@ "DataType": "Bool", "DefaultValue": true }, - { - "Field": "fps", - "DataType": "Enum", - "EnumKey": "fps", - "DefaultValue": "60" - }, - { - "Field": "aspect_mode", - "DataType": "Enum", - "EnumKey": "aspect_mode", - "DefaultValue": "any" - }, { "Field": "screenshot_format", "DataType": "Enum",