settings: restore pre-migration configuration behaviour, add regression checks

The single-source migration changed the emitted configuration tables in
four distinct ways, none of which produce any diagnostic. This restores
the pre-migration behaviour and adds the checks that would have caught
each one, verified offline before commit: full Makefile build, a
griffin-order unity compile of the settings TUs at -Werror for three
profiles, and an entry-by-entry diff of the emitted tables against the
pre-migration commit (31f3a60641) for desktop and Android define sets.

1) Transcribed default values. cloud_sync_sync_saves and
   cloud_sync_sync_configs were registered true and came back false;
   menu_linear_filter was registered DEFAULT_VIDEO_SMOOTH and came back a
   literal true, discarding the platform conditional. Restored.

2) Guard breadth. Twelve rows had their configuration registration
   narrowed to the descriptor's platform guard, so on other platforms
   they get no default and are neither saved nor loaded:
   audio_block_frames, microphone_block_frames,
   keyboard_gamepad_mapping_type (worst: guard moved from ANDROID to
   TARGET_OS_IPHONE, so its Android default of 1 was never applied),
   menu_show_reboot, menu_show_shutdown, sustained_performance_mode,
   ui_menubar_enable, video_ctx_scaling, suspend_screensaver_enable,
   video_disable_composition, accessibility_narrator_engine, and
   network_remote_enable (registered under HAVE_NETWORKGAMEPAD before,
   HAVE_NETWORKING && HAVE_NETWORK_CMD after). The guards gain
   SETTINGS_DEF_CONFIG_PASS terms so the configuration row emits where
   the hand-written table emitted it; descriptor and menu rows keep
   their current platform restriction.

3) default_enable. The generated grammar always applies a default, but
   six rows were deliberately registered without one:
   rgui_show_start_screen, netplay_start_as_spectator,
   network_remote_enable, ui_companion_toggle, state_slot, replay_slot.
   Applying a default resets the state and replay slots to 0 on every
   config load and forces the others back to compiled-in values. These
   rows are excluded from the configuration pass in their def files and
   registered by hand in configuration.c, the same idiom
   accessibility_enable already uses. Deliberately, no new emitter
   spelling is introduced anywhere: a previous attempt added _ND row
   names via self-aliasing '#ifndef' blocks, which leak into any
   translation unit that includes a def file before configuration.c
   defines the name for real - in the griffin unity build that is
   msg_hash.h, and MSVC flagged the redefinition (C4005). With no new
   names there is nothing to collide and nothing to undefine.

4) Duplicate registration. video_fullscreen_x/y were registered twice in
   the uint table, by the surviving hand-written rows and the generated
   ones. The hand-written pair is removed and its __WINRT__ exclusion
   moved onto the generated rows. This requires the config passes to
   define SETTINGS_DEF_CONFIG_PASS before the video_fullscreen include
   rather than after it; that ordering applied to all five passes.

tools/settings_check.py carries both regression checks:

  table - preprocesses configuration.c for desktop, android and console
          profiles and diffs every emitted (kind, ident, default_enable,
          default) against tools/settings_table.reference. Intentional
          settings changes regenerate the reference in the same commit,
          putting the table delta in the diff for review.
  unity - compiles configuration.c, msg_hash.c, intl/msg_hash_us.c and
          menu/menu_setting.c concatenated in griffin/griffin.c order at
          -Werror for three profiles. This is the configuration in which
          the C4005 collision manifested; per-file builds cannot see it.
          Negative-tested by planting a leaked guarded alias: the check
          fails with the redefinition error, and passes after removal.

Both run in the new Settings-Checks workflow on every push and pull
request: preprocessor and -fsyntax-only only, no configure step, no
dependencies beyond the runner's gcc and python3, well under a minute.

The remaining table deltas against 31f3a60641 are intentional and
verified benign: settings added since July, the separate config.def.h
change to audio_fastpath_s16, and ORIENTATION_NORMAL spelled as its
value 0.

No sanitizer sweep is applicable: preprocessor-level changes and
build-time tooling only; no executable code paths are modified.
This commit is contained in:
LibretroAdmin authored and libretroadmin committed 2026-08-10 01:14:11 +02:00
1 parent a7a4a9cf9d
commit 558b24a685
22 files changed
+2262 -25

No files matched your search

+46
View File
@@ -0,0 +1,46 @@
name: CI Settings definitions
on:
push:
branches:
- master
pull_request:
branches:
- master
workflow_dispatch:
permissions:
contents: read
env:
ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true
jobs:
settings-checks:
name: Settings table drift and griffin-order unity compile
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Configuration table drift
shell: bash
run: |
set -eu
# A def row that stops reaching the configuration tables
# produces no compile diagnostic anywhere; this diff is the
# only thing that notices. Preprocessor only, no configure.
python3 tools/settings_check.py table \
--check tools/settings_table.reference
- name: Griffin-order unity compile
shell: bash
run: |
set -eu
# Compiles the settings TUs concatenated in griffin/griffin.c
# order at -Werror. Macro leakage between msg_hash.h, the
# settings/ def files and configuration.c only manifests in
# this concatenation; per-file builds cannot see it.
python3 tools/settings_check.py unity
+25 -10
View File
@@ -1891,6 +1891,20 @@ static struct config_bool_setting *populate_settings_bool(
SETTING_BOOL("video_force_aspect", &settings->bools.video_force_aspect, true, DEFAULT_FORCE_ASPECT, false);
SETTING_BOOL("video_threaded", video_driver_get_threaded(), true, DEFAULT_VIDEO_THREADED, false);
SETTING_BOOL("video_shared_context", &settings->bools.video_shared_context, true, DEFAULT_VIDEO_SHARED_CONTEXT, false);
/* Rows with no default in the configuration table. The generated
* grammar always applies a default, so these are registered here
* instead and excluded from the configuration pass in their
* settings/ def file, the same as accessibility_enable. */
SETTING_BOOL("rgui_show_start_screen", &settings->bools.menu_show_start_screen, false, DEFAULT_MENU_SHOW_START_SCREEN, false);
#ifdef HAVE_NETWORKING
SETTING_BOOL("netplay_start_as_spectator", &settings->bools.netplay_start_as_spectator, false, DEFAULT_NETPLAY_START_AS_SPECTATOR, false);
#endif
#ifdef HAVE_NETWORKGAMEPAD
SETTING_BOOL("network_remote_enable", &settings->bools.network_remote_enable, false, false, false);
#endif
#if defined(HAVE_QT) || defined(HAVE_COCOA)
SETTING_BOOL("ui_companion_toggle", &settings->bools.ui_companion_toggle, false, DEFAULT_UI_COMPANION_TOGGLE, false);
#endif
/* GENERATED: single-source setting rows (bool kind emits here) */
#define S_BOOL(f, T, n, d, sd, df, c, us, sub) \
SETTING_BOOL(n, &settings->bools.f, true, d, false);
@@ -1940,8 +1954,8 @@ static struct config_bool_setting *populate_settings_bool(
#define S_INT_AT_NS(offs, T, n, d, sd, df, c, mn, mx, st, ob, ok, rp, us)
#define S_UINT_AT_EX(offs, T, n, d, sd, df, c, mn, mx, st, ob, ok, rp, sta, sel, lf, rt, ui, us, sub)
#define S_UINT_AT_EX_NS(offs, T, n, d, sd, df, c, mn, mx, st, ob, ok, rp, sta, sel, lf, rt, ui, us)
#include "settings/settings_def_video_fullscreen.h"
#define SETTINGS_DEF_CONFIG_PASS
#include "settings/settings_def_video_fullscreen.h"
#include "settings/settings_def_video_sync.h"
#ifdef HAVE_GAME_AI
#include "settings/settings_def_game_ai.h"
@@ -2651,8 +2665,8 @@ static struct config_float_setting *populate_settings_float(
#define S_INT_AT_NS(offs, T, n, d, sd, df, c, mn, mx, st, ob, ok, rp, us)
#define S_UINT_AT_EX(offs, T, n, d, sd, df, c, mn, mx, st, ob, ok, rp, sta, sel, lf, rt, ui, us, sub)
#define S_UINT_AT_EX_NS(offs, T, n, d, sd, df, c, mn, mx, st, ob, ok, rp, sta, sel, lf, rt, ui, us)
#include "settings/settings_def_video_fullscreen.h"
#define SETTINGS_DEF_CONFIG_PASS
#include "settings/settings_def_video_fullscreen.h"
#include "settings/settings_def_video_sync.h"
#ifdef HAVE_GAME_AI
#include "settings/settings_def_game_ai.h"
@@ -3264,11 +3278,6 @@ static struct config_uint_setting *populate_settings_uint(
SETTING_UINT("video_windowed_position_y", &settings->uints.window_position_y, true, 0, false);
SETTING_UINT("video_windowed_position_width", &settings->uints.window_position_width, true, DEFAULT_WINDOW_WIDTH, false);
SETTING_UINT("video_windowed_position_height",&settings->uints.window_position_height, true, DEFAULT_WINDOW_HEIGHT, false);
#ifdef __WINRT__
#else
SETTING_UINT("video_fullscreen_x", &settings->uints.video_fullscreen_x, true, DEFAULT_FULLSCREEN_X, false);
SETTING_UINT("video_fullscreen_y", &settings->uints.video_fullscreen_y, true, DEFAULT_FULLSCREEN_Y, false);
#endif
#ifdef GEKKO
SETTING_UINT("video_viwidth", &settings->uints.video_viwidth, true, DEFAULT_VIDEO_VI_WIDTH, false);
#endif
@@ -3319,8 +3328,8 @@ static struct config_uint_setting *populate_settings_uint(
#define S_INT_AT_NS(offs, T, n, d, sd, df, c, mn, mx, st, ob, ok, rp, us)
#define S_UINT_AT_EX(offs, T, n, d, sd, df, c, mn, mx, st, ob, ok, rp, sta, sel, lf, rt, ui, us, sub)
#define S_UINT_AT_EX_NS(offs, T, n, d, sd, df, c, mn, mx, st, ob, ok, rp, sta, sel, lf, rt, ui, us)
#include "settings/settings_def_video_fullscreen.h"
#define SETTINGS_DEF_CONFIG_PASS
#include "settings/settings_def_video_fullscreen.h"
#include "settings/settings_def_video_sync.h"
#ifdef HAVE_GAME_AI
#include "settings/settings_def_game_ai.h"
@@ -3977,6 +3986,12 @@ static struct config_int_setting *populate_settings_int(
SETTING_INT("crt_switch_center_adjust", &settings->ints.crt_switch_center_adjust, false, DEFAULT_CRT_SWITCH_CENTER_ADJUST, false);
SETTING_INT("crt_switch_porch_adjust", &settings->ints.crt_switch_porch_adjust, false, DEFAULT_CRT_SWITCH_PORCH_ADJUST, false);
SETTING_INT("crt_switch_vertical_adjust", &settings->ints.crt_switch_vertical_adjust, false, DEFAULT_CRT_SWITCH_VERTICAL_ADJUST, false);
/* Rows with no default in the configuration table; see the note in
* populate_settings_bool(). */
SETTING_INT("state_slot", &settings->ints.state_slot, false, 0, false);
#ifdef HAVE_BSV_MOVIE
SETTING_INT("replay_slot", &settings->ints.replay_slot, false, 0, false);
#endif
/* GENERATED: single-source setting rows (int kind emits here) */
#define S_BOOL(f, T, n, d, sd, df, c, us, sub)
#define S_BOOL_NS(f, T, n, d, sd, df, c, us)
@@ -4024,8 +4039,8 @@ static struct config_int_setting *populate_settings_int(
#define S_INT_AT_NS(offs, T, n, d, sd, df, c, mn, mx, st, ob, ok, rp, us)
#define S_UINT_AT_EX(offs, T, n, d, sd, df, c, mn, mx, st, ob, ok, rp, sta, sel, lf, rt, ui, us, sub)
#define S_UINT_AT_EX_NS(offs, T, n, d, sd, df, c, mn, mx, st, ob, ok, rp, sta, sel, lf, rt, ui, us)
#include "settings/settings_def_video_fullscreen.h"
#define SETTINGS_DEF_CONFIG_PASS
#include "settings/settings_def_video_fullscreen.h"
#include "settings/settings_def_video_sync.h"
#ifdef HAVE_GAME_AI
#include "settings/settings_def_game_ai.h"
@@ -4616,8 +4631,8 @@ static struct config_int_setting *populate_settings_int(
#define S_INT_AT_NS(offs, T, n, d, sd, df, c, mn, mx, st, ob, ok, rp, us)
#define S_UINT_AT_EX(offs, T, n, d, sd, df, c, mn, mx, st, ob, ok, rp, sta, sel, lf, rt, ui, us, sub)
#define S_UINT_AT_EX_NS(offs, T, n, d, sd, df, c, mn, mx, st, ob, ok, rp, sta, sel, lf, rt, ui, us)
#include "settings/settings_def_video_fullscreen.h"
#define SETTINGS_DEF_CONFIG_PASS
#include "settings/settings_def_video_fullscreen.h"
#include "settings/settings_def_video_sync.h"
#ifdef HAVE_GAME_AI
#include "settings/settings_def_game_ai.h"
+1 -1
View File
@@ -20,7 +20,7 @@ S_UINT_EX(accessibility_narrator_speech_speed, ACCESSIBILITY_NARRATOR_SPEECH_SPE
"The speed for the Text-to-Speech voice.")
/* Descriptor and configuration rows are #if defined(__linux__) && !defined(ANDROID); the string
* tables always carry this row via the strings pass. */
#if (defined(__linux__) && !defined(ANDROID)) || defined(SETTINGS_DEF_STRINGS_PASS)
#if (defined(__linux__) && !defined(ANDROID)) || defined(SETTINGS_DEF_STRINGS_PASS) || defined(SETTINGS_DEF_CONFIG_PASS)
S_UINT_EX(accessibility_narrator_engine, ACCESSIBILITY_NARRATOR_ENGINE,
"accessibility_narrator_engine",
DEFAULT_ACCESSIBILITY_NARRATOR_ENGINE, SD_FLAG_NONE, SDESC_RANGE_MINMAX, 0, 0, ACCESSIBILITY_NARRATOR_ENGINE_LAST - 1, 1, 0, setting_action_ok_uint, setting_get_string_representation_uint_accessibility_narrator_engine, NULL, NULL, NULL, NULL, 0,
+1 -1
View File
@@ -18,7 +18,7 @@ S_FLOAT_EX_H(audio_max_timing_skew, AUDIO_MAX_TIMING_SKEW,
"The maximum change in audio input rate. Increasing this enables very large changes in timing at the cost of an inaccurate audio pitch (e.g. running PAL cores on NTSC displays).")
/* Descriptor and configuration rows are #ifdef RARCH_MOBILE; the string
* tables always carry this row via the strings pass. */
#if defined(RARCH_MOBILE) || defined(SETTINGS_DEF_STRINGS_PASS)
#if defined(RARCH_MOBILE) || defined(SETTINGS_DEF_STRINGS_PASS) || defined(SETTINGS_DEF_CONFIG_PASS)
S_UINT_NS(audio_block_frames, AUDIO_BLOCK_FRAMES,
"audio_block_frames",
0, SD_FLAG_ADVANCED, 0, 0, 0, 0, 0, 0, NULL, NULL,
+2 -2
View File
@@ -27,7 +27,7 @@ S_BOOL(cloud_sync_destructive, CLOUD_SYNC_DESTRUCTIVE,
#if defined(HAVE_CLOUDSYNC) || defined(SETTINGS_DEF_STRINGS_PASS)
S_BOOL(cloud_sync_sync_saves, CLOUD_SYNC_SYNC_SAVES,
"cloud_sync_sync_saves",
false, SD_FLAG_NONE, 0, 0,
true, SD_FLAG_NONE, 0, 0,
"Sync: Saves/States",
"When enabled, saves/states will be synced to cloud.")
#endif
@@ -36,7 +36,7 @@ S_BOOL(cloud_sync_sync_saves, CLOUD_SYNC_SYNC_SAVES,
#if defined(HAVE_CLOUDSYNC) || defined(SETTINGS_DEF_STRINGS_PASS)
S_BOOL(cloud_sync_sync_configs, CLOUD_SYNC_SYNC_CONFIGS,
"cloud_sync_sync_configs",
false, SD_FLAG_NONE, 0, 0,
true, SD_FLAG_NONE, 0, 0,
"Sync: Configuration Files",
"When enabled, configuration files will be synced to cloud.")
#endif
+5
View File
@@ -47,8 +47,13 @@ S_BOOL_EX_NS(desktop_menu_enable, DESKTOP_MENU_ENABLE,
/* Descriptor and configuration rows are #if defined(HAVE_QT) || defined(HAVE_COCOA); the string
* tables always carry this row via the strings pass. */
#if (defined(HAVE_QT) || defined(HAVE_COCOA)) || defined(SETTINGS_DEF_STRINGS_PASS)
/* The configuration table registers this row by hand in
* configuration.c because it carries no default there; the
* generated row is for the other passes. */
#ifndef SETTINGS_DEF_CONFIG_PASS
S_BOOL_NS(ui_companion_toggle, UI_COMPANION_TOGGLE,
"ui_companion_toggle",
DEFAULT_UI_COMPANION_TOGGLE, SD_FLAG_NONE, 0, 0,
"Open Desktop Menu on Startup")
#endif
#endif
+1 -1
View File
@@ -18,7 +18,7 @@ S_BOOL_NS(input_keyboard_gamepad_enable, INPUT_ICADE_ENABLE,
#endif
/* Descriptor and configuration rows are #if TARGET_OS_IPHONE; the string
* tables always carry this row via the strings pass. */
#if TARGET_OS_IPHONE || defined(SETTINGS_DEF_STRINGS_PASS)
#if TARGET_OS_IPHONE || defined(SETTINGS_DEF_STRINGS_PASS) || defined(SETTINGS_DEF_CONFIG_PASS)
S_UINT_EX_NS(input_keyboard_gamepad_mapping_type, INPUT_KEYBOARD_GAMEPAD_MAPPING_TYPE,
"keyboard_gamepad_mapping_type",
1, SD_FLAG_NONE, SDESC_RANGE_MINMAX, 0, 0, 3, 1, 0, setting_action_ok_uint, setting_get_string_representation_uint_keyboard_gamepad_mapping_type, NULL, NULL, NULL, NULL, 0,
+10
View File
@@ -4,20 +4,30 @@
* matches SDESC_<kind>_ROW; row order is menu display order;
* h2json.py parses these rows for the Crowdin source upload. */
/* The configuration table registers this row by hand in
* configuration.c because it carries no default there; the
* generated row is for the other passes. */
#ifndef SETTINGS_DEF_CONFIG_PASS
S_INT_EX(state_slot, STATE_SLOT,
"state_slot",
0, SD_FLAG_NONE, SDESC_RANGE_MINMAX, 0, -1, 999, 1, -1, setting_action_ok_uint, setting_get_string_representation_state_slot, NULL, NULL, NULL, NULL, 0,
"State Slot",
"Change the currently selected state slot.")
#endif
/* Descriptor and configuration rows are #ifdef HAVE_BSV_MOVIE; the string
* tables always carry this row via the strings pass. */
#if defined(HAVE_BSV_MOVIE) || defined(SETTINGS_DEF_STRINGS_PASS)
/* The configuration table registers this row by hand in
* configuration.c because it carries no default there; the
* generated row is for the other passes. */
#ifndef SETTINGS_DEF_CONFIG_PASS
S_INT_EX(replay_slot, REPLAY_SLOT,
"replay_slot",
0, SD_FLAG_NONE, SDESC_RANGE_MINMAX, 0, -1, 999, 1, -1, setting_action_ok_uint, setting_get_string_representation_state_slot, NULL, NULL, NULL, NULL, 0,
"Replay Slot",
"Change the currently selected state slot.")
#endif
#endif
S_ACTION(START_CORE,
"start_core",
"Start Core",
+2 -2
View File
@@ -6,7 +6,7 @@
/* Descriptor and configuration rows are #if defined(HAVE_LAKKA) || defined(HAVE_ODROIDGO2); the string
* tables always carry this row via the strings pass. */
#if defined(HAVE_LAKKA) || defined(HAVE_ODROIDGO2) || defined(SETTINGS_DEF_STRINGS_PASS)
#if defined(HAVE_LAKKA) || defined(HAVE_ODROIDGO2) || defined(SETTINGS_DEF_STRINGS_PASS) || (defined(SETTINGS_DEF_CONFIG_PASS) && defined(HAVE_MENU))
S_BOOL(menu_show_reboot, MENU_SHOW_REBOOT,
"menu_show_reboot",
DEFAULT_MENU_SHOW_REBOOT, SD_FLAG_NONE, 0, 0,
@@ -15,7 +15,7 @@ S_BOOL(menu_show_reboot, MENU_SHOW_REBOOT,
#endif
/* Descriptor and configuration rows are #if defined(HAVE_LAKKA) || defined(HAVE_ODROIDGO2); the string
* tables always carry this row via the strings pass. */
#if defined(HAVE_LAKKA) || defined(HAVE_ODROIDGO2) || defined(SETTINGS_DEF_STRINGS_PASS)
#if defined(HAVE_LAKKA) || defined(HAVE_ODROIDGO2) || defined(SETTINGS_DEF_STRINGS_PASS) || (defined(SETTINGS_DEF_CONFIG_PASS) && defined(HAVE_MENU))
S_BOOL(menu_show_shutdown, MENU_SHOW_SHUTDOWN,
"menu_show_shutdown",
DEFAULT_MENU_SHOW_SHUTDOWN, SD_FLAG_NONE, 0, 0,
+1 -1
View File
@@ -6,7 +6,7 @@
S_BOOL(menu_linear_filter, MENU_LINEAR_FILTER,
"menu_linear_filter",
true, SD_FLAG_NONE, 0, 0,
DEFAULT_VIDEO_SMOOTH, SD_FLAG_NONE, 0, 0,
"Linear Filter",
"Adds a slight blur to the menu to soften hard pixel edges.")
S_UINT_EX(menu_rgui_internal_upscale_level, MENU_RGUI_INTERNAL_UPSCALE_LEVEL,
@@ -5,8 +5,13 @@
* h2json.py parses these rows for the Crowdin source upload. */
/* FIXME Not RGUI specific */ /* FIXME Not RGUI specific */
/* The configuration table registers this row by hand in
* configuration.c because it carries no default there; the
* generated row is for the other passes. */
#ifndef SETTINGS_DEF_CONFIG_PASS
S_BOOL(menu_show_start_screen, RGUI_SHOW_START_SCREEN,
"rgui_show_start_screen",
DEFAULT_MENU_SHOW_START_SCREEN, SD_FLAG_ADVANCED, 0, 0,
"Display Start Screen",
"Show startup screen in menu. This is automatically set to false after the program starts for the first time.")
#endif
+1 -1
View File
@@ -5,7 +5,7 @@
* h2json.py parses these rows for the Crowdin source upload. */
#ifdef HAVE_MICROPHONE
#ifdef RARCH_MOBILE
#if defined(RARCH_MOBILE) || defined(SETTINGS_DEF_CONFIG_PASS)
S_UINT_NS(microphone_block_frames, MICROPHONE_BLOCK_FRAMES,
"microphone_block_frames",
0, SD_FLAG_ADVANCED, 0, 0, 0, 0, 0, 0, NULL, NULL,
+5
View File
@@ -20,6 +20,10 @@
/* The configuration row lives under defined(HAVE_NETWORKING); other passes are
* unaffected. */
#if !defined(SETTINGS_DEF_CONFIG_PASS) || (defined(HAVE_NETWORKING))
/* The configuration table registers this row by hand in
* configuration.c because it carries no default there; the
* generated row is for the other passes. */
#ifndef SETTINGS_DEF_CONFIG_PASS
S_BOOL_H(netplay_start_as_spectator, NETPLAY_START_AS_SPECTATOR,
"netplay_start_as_spectator",
DEFAULT_NETPLAY_START_AS_SPECTATOR, SD_FLAG_NONE, 0, 0,
@@ -27,6 +31,7 @@ S_BOOL_H(netplay_start_as_spectator, NETPLAY_START_AS_SPECTATOR,
"Start netplay in spectator mode.")
#endif
#endif
#endif
/* Descriptor and configuration rows are #if defined(HAVE_NETWORKING); the string
* tables always carry this row via the strings pass. */
#if defined(HAVE_NETWORKING) || defined(SETTINGS_DEF_STRINGS_PASS)
+6 -1
View File
@@ -6,9 +6,14 @@
/* Descriptor and configuration rows are #if defined(HAVE_NETWORKING) #if defined(HAVE_NETWORK_CMD); the string
* tables always carry this row via the strings pass. */
#if defined(HAVE_NETWORKING) && defined(HAVE_NETWORK_CMD) || defined(SETTINGS_DEF_STRINGS_PASS)
#if defined(HAVE_NETWORKING) && defined(HAVE_NETWORK_CMD) || defined(SETTINGS_DEF_STRINGS_PASS) || (defined(SETTINGS_DEF_CONFIG_PASS) && defined(HAVE_NETWORKGAMEPAD))
/* The configuration table registers this row by hand in
* configuration.c because it carries no default there; the
* generated row is for the other passes. */
#ifndef SETTINGS_DEF_CONFIG_PASS
S_BOOL_EX_NS(network_remote_enable, NETWORK_REMOTE_ENABLE,
"network_remote_enable",
false, SD_FLAG_ADVANCED, 0, 0, setting_bool_action_left_with_refresh, NULL, NULL, NULL, setting_bool_action_left_with_refresh, setting_bool_action_right_with_refresh, 0,
"Network RetroPad")
#endif
#endif
@@ -6,7 +6,7 @@
/* Descriptor and configuration rows are #ifdef ANDROID; the string
* tables always carry this row via the strings pass. */
#if defined(ANDROID) || defined(SETTINGS_DEF_STRINGS_PASS)
#if defined(ANDROID) || defined(SETTINGS_DEF_STRINGS_PASS) || defined(SETTINGS_DEF_CONFIG_PASS)
S_BOOL_NS(sustained_performance_mode, SUSTAINED_PERFORMANCE_MODE,
"sustained_performance_mode",
DEFAULT_SUSTAINED_PERFORMANCE_MODE, SD_FLAG_CMD_APPLY_AUTO, 0, 0,
+1 -1
View File
@@ -19,7 +19,7 @@ S_BOOL(pause_nonactive, PAUSE_NONACTIVE,
"Pause content when RetroArch is not the active window.")
/* Descriptor and configuration rows are #if !defined(RARCH_MOBILE); the string
* tables always carry this row via the strings pass. */
#if !defined(RARCH_MOBILE) || defined(SETTINGS_DEF_STRINGS_PASS)
#if !defined(RARCH_MOBILE) || defined(SETTINGS_DEF_STRINGS_PASS) || defined(SETTINGS_DEF_CONFIG_PASS)
S_BOOL_H(video_disable_composition, VIDEO_DISABLE_COMPOSITION,
"video_disable_composition",
DEFAULT_DISABLE_COMPOSITION, SD_FLAG_CMD_APPLY_AUTO | SD_FLAG_LAKKA_ADVANCED, 0, CMD_EVENT_REINIT,
+1 -1
View File
@@ -6,7 +6,7 @@
/* Descriptor and configuration rows are #if defined(_WIN32) && !defined(_XBOX) && !defined(__WINRT__); the string
* tables always carry this row via the strings pass. */
#if defined(_WIN32) && !defined(_XBOX) && !defined(__WINRT__) || defined(SETTINGS_DEF_STRINGS_PASS)
#if defined(_WIN32) && !defined(_XBOX) && !defined(__WINRT__) || defined(SETTINGS_DEF_STRINGS_PASS) || defined(SETTINGS_DEF_CONFIG_PASS)
S_BOOL(ui_menubar_enable, UI_MENUBAR_ENABLE,
"ui_menubar_enable",
DEFAULT_UI_MENUBAR_ENABLE, SD_FLAG_NONE, 0, CMD_EVENT_REINIT,
+1 -1
View File
@@ -6,7 +6,7 @@
/* Descriptor and configuration rows are #ifdef HAVE_ODROIDGO2; the string
* tables always carry this row via the strings pass. */
#if defined(HAVE_ODROIDGO2) || defined(SETTINGS_DEF_STRINGS_PASS)
#if defined(HAVE_ODROIDGO2) || defined(SETTINGS_DEF_STRINGS_PASS) || defined(SETTINGS_DEF_CONFIG_PASS)
S_BOOL_LV(video_ctx_scaling, VIDEO_CTX_SCALING, VIDEO_RGA_SCALING,
"video_ctx_scaling",
DEFAULT_VIDEO_CTX_SCALING, SD_FLAG_NONE, 0, CMD_EVENT_REINIT,
+2
View File
@@ -14,6 +14,7 @@ S_BOOL(video_windowed_fullscreen, VIDEO_WINDOWED_FULLSCREEN,
DEFAULT_WINDOWED_FULLSCREEN, SD_FLAG_LAKKA_ADVANCED, 0, CMD_EVENT_NONE,
"Windowed Fullscreen Mode",
"If fullscreen, prefer using a fullscreen window to prevent display mode switching.")
#if !defined(__WINRT__) || !defined(SETTINGS_DEF_CONFIG_PASS)
S_UINT(video_fullscreen_x, VIDEO_FULLSCREEN_X,
"video_fullscreen_x",
DEFAULT_FULLSCREEN_X, SD_FLAG_NONE, SDESC_RANGE_MINMAX, CMD_EVENT_NONE, 0, 7680, 8, 0, setting_action_ok_uint_special, NULL,
@@ -24,3 +25,4 @@ S_UINT(video_fullscreen_y, VIDEO_FULLSCREEN_Y,
DEFAULT_FULLSCREEN_Y, SD_FLAG_NONE, SDESC_RANGE_MINMAX, CMD_EVENT_NONE, 0, 4320, 8, 0, setting_action_ok_uint_special, NULL,
"Fullscreen Height",
"Set the custom height size for the non-windowed fullscreen mode. Leaving it unset will use the desktop resolution.")
#endif
@@ -13,7 +13,7 @@
#endif
/* Descriptor and configuration rows are #if (!defined(RARCH_CONSOLE) && !defined(RARCH_MOBILE)) || (defined(IOS) && TARGET_OS_TV); the string
* tables always carry this row via the strings pass. */
#if (!defined(RARCH_CONSOLE) && !defined(RARCH_MOBILE)) || (defined(IOS) && TARGET_OS_TV) || defined(SETTINGS_DEF_STRINGS_PASS)
#if (!defined(RARCH_CONSOLE) && !defined(RARCH_MOBILE)) || (defined(IOS) && TARGET_OS_TV) || defined(SETTINGS_DEF_STRINGS_PASS) || defined(SETTINGS_DEF_CONFIG_PASS)
S_BOOL_H(ui_suspend_screensaver_enable, SUSPEND_SCREENSAVER_ENABLE,
"suspend_screensaver_enable",
true, SD_FLAG_LAKKA_ADVANCED, 0, 0,
+219
View File
@@ -0,0 +1,219 @@
#!/usr/bin/env python3
"""Regression checks for the single-source settings definitions.
Two checks, both preprocessor/front-end only, no configured build tree:
table - preprocess configuration.c for several platform profiles, extract
every (kind, ident, default_enable, default) the five
populate_settings_* tables emit, and diff against a committed
reference. A def row whose guard is too narrow, whose default was
transcribed wrongly, or which lost its no-default registration
produces no compile diagnostic; this is the only thing that
notices.
unity - compile the settings translation units concatenated in
griffin/griffin.c order with -Werror, the way the MSVC griffin
build compiles them. Macro leakage between msg_hash.h, the def
files and configuration.c only manifests in this concatenation;
per-file builds cannot see it.
Usage:
tools/settings_check.py table --check tools/settings_table.reference
tools/settings_check.py table --write tools/settings_table.reference
tools/settings_check.py unity
"""
import argparse
import os
import re
import subprocess
import sys
import tempfile
KINDS = ('bool', 'int', 'uint', 'float', 'size')
COMMON = [
'RARCH_INTERNAL', 'HAVE_MENU', 'HAVE_XMB', 'HAVE_OZONE', 'HAVE_RGUI',
'HAVE_MATERIALUI', 'HAVE_NETWORKING', 'HAVE_NETPLAY', 'HAVE_NETWORK_CMD',
'HAVE_NETWORKGAMEPAD', 'HAVE_COMMAND', 'HAVE_CHEEVOS', 'HAVE_OVERLAY',
'HAVE_TRANSLATE', 'HAVE_LANGEXTRA', 'HAVE_MICROPHONE', 'HAVE_CLOUDSYNC',
'HAVE_SMBCLIENT', 'HAVE_IMAGEVIEWER', 'HAVE_CRTSWITCHRES',
'HAVE_ACCESSIBILITY', 'HAVE_GFX_WIDGETS', 'HAVE_THREADS',
'HAVE_AUDIOMIXER', 'HAVE_REWIND', 'HAVE_RUNAHEAD', 'HAVE_SCREENSHOTS',
'HAVE_BLUETOOTH', 'HAVE_WIFI', 'HAVE_BSV_MOVIE', 'HAVE_CONFIGFILE',
'HAVE_PATCH', 'HAVE_CHEATS', 'HAVE_ZLIB', 'HAVE_COMPRESSION',
'HAVE_UPDATE_CORES', 'HAVE_LIBRETRODB', 'HAVE_DYNAMIC',
'HAVE_SHADERPIPELINE', 'HAVE_GLSL', 'HAVE_SLANG', 'HAVE_OPENGL',
'HAVE_VIDEO_LAYOUT', 'HAVE_STB_FONT', 'HAVE_CC_RESAMPLER',
]
PROFILES = {
'desktop': ['HAVE_VULKAN', 'HAVE_QT', 'HAVE_DISCORD'],
'android': ['ANDROID', 'RARCH_MOBILE', 'HAVE_VULKAN'],
'console': ['RARCH_CONSOLE'],
}
INCLUDES = [
'.', 'libretro-common/include', 'deps', 'deps/stb',
'deps/rcheevos/include',
]
# The settings slice of griffin/griffin.c, in griffin's inclusion order.
# These four are the consumers of the settings/ def files; the collision
# class this guards against (macro leakage across them) needs exactly this
# concatenation to show up.
UNITY_TUS = [
'configuration.c',
'msg_hash.c',
'intl/msg_hash_us.c',
'menu/menu_setting.c',
]
UNITY_EXTRA = [
'HAVE_STDIN_CMD', 'HAVE_RWAV', 'HAVE_ONLINE_UPDATER',
'HAVE_UPDATE_ASSETS', 'HAVE_CORE_INFO_CACHE', 'HAVE_DSP_FILTER',
'HAVE_VIDEO_FILTER', 'HAVE_7ZIP', 'HAVE_RPNG', 'HAVE_RJPEG',
'HAVE_RBMP', 'HAVE_RTGA',
]
# The unity check compiles at -Werror, so it gets its own profile set:
# ANDROID is replaced by bare RARCH_MOBILE because configuration.c's
# '#ifdef ANDROID' accessibility block calls is_screen_reader_enabled()
# without a visible prototype (declared in frontend/drivers/
# platform_unix.h, which configuration.c does not include) - a
# pre-existing condition unrelated to the settings definitions this
# check guards. The macro-collision class it detects is
# platform-independent, so mobile coverage of the def-file guards is
# what matters, not the ANDROID spelling.
UNITY_PROFILES = {
'desktop': ['HAVE_VULKAN', 'HAVE_QT', 'HAVE_DISCORD'],
'mobile': ['RARCH_MOBILE', 'HAVE_VULKAN'],
'console': ['RARCH_CONSOLE'],
}
ROW = re.compile(
r'tmp\[count\]\.ident\s*=\s*"([^"]*)";\s*'
r'tmp\[count\]\.ptr\s*=\s*([^;]*);\s*'
r'if\s*\((\d+)\)\s*\{\s*tmp\[count\]\.flags[^;]*;\s*'
r'tmp\[count\]\.def\s*=\s*([^;]*);')
BARE = re.compile(r'tmp\[count\]\.ident\s*=\s*"([^"]*)"')
def gcc_args(root, defines):
argv = ['gcc', '-std=gnu99']
argv += ['-D' + d for d in defines]
for inc in INCLUDES:
argv += ['-I', os.path.join(root, inc)]
return argv
def preprocess(root, defines):
argv = gcc_args(root, COMMON + defines) + [
'-E', '-P', os.path.join(root, 'configuration.c')]
proc = subprocess.run(argv, capture_output=True, text=True)
if proc.returncode != 0:
sys.stderr.write(proc.stderr)
sys.exit('preprocessing configuration.c failed')
return proc.stdout
def extract(text):
rows = []
for kind in KINDS:
start = text.find('*populate_settings_%s(' % kind)
if start < 0:
continue
end = text.find('*size = count;', start)
body = text[start:end]
defs = {}
for m in ROW.finditer(body):
defs[m.group(1)] = (m.group(3), ' '.join(m.group(4).split()))
for ident in BARE.findall(body):
enable, value = defs.get(ident, ('0', '-'))
rows.append((kind, ident, enable, value))
return rows
def render(root):
out = []
for profile in sorted(PROFILES):
out.append('[%s]' % profile)
for row in extract(preprocess(root, PROFILES[profile])):
out.append('\t'.join(row))
return '\n'.join(out) + '\n'
def cmd_table(args, root):
current = render(root)
if args.write:
with open(args.write, 'w') as handle:
handle.write(current)
print('wrote %s' % args.write)
return 0
with open(args.check) as handle:
reference = handle.read()
if reference == current:
print('settings tables match %s' % args.check)
return 0
import difflib
sys.stdout.writelines(difflib.unified_diff(
reference.splitlines(True), current.splitlines(True),
fromfile='reference', tofile='current'))
sys.stderr.write(
'\nThe emitted configuration tables changed. If intended, '
'regenerate:\n tools/settings_check.py table --write %s\n'
% args.check)
return 1
def cmd_unity(args, root):
src = ['/* Settings slice of griffin/griffin.c; same inclusion order.',
' * Generated by tools/settings_check.py, not committed. */']
for tu in UNITY_TUS:
src.append('#include "%s"' % os.path.join(root, tu))
with tempfile.NamedTemporaryFile(
'w', suffix='.c', prefix='settings_unity_',
delete=False) as handle:
handle.write('\n'.join(src) + '\n')
path = handle.name
try:
failures = 0
for profile in sorted(UNITY_PROFILES):
defines = COMMON + UNITY_EXTRA + UNITY_PROFILES[profile]
# -Werror promotes macro-redefinition (and every other)
# warning in these TUs to a failure; the normal build is
# warning-clean here, so anything new is a regression.
argv = gcc_args(root, defines) + [
'-fsyntax-only', '-Werror', path]
proc = subprocess.run(argv, capture_output=True, text=True)
if proc.returncode != 0:
sys.stderr.write('[%s]\n%s' % (profile, proc.stderr))
failures += 1
else:
print('unity [%s]: clean' % profile)
return 1 if failures else 0
finally:
os.unlink(path)
def main():
ap = argparse.ArgumentParser()
sub = ap.add_subparsers(dest='cmd', required=True)
t = sub.add_parser('table')
t.add_argument('--write', metavar='FILE')
t.add_argument('--check', metavar='FILE')
sub.add_parser('unity')
ap.add_argument('--root', default=os.path.join(
os.path.dirname(os.path.abspath(__file__)), '..'))
args = ap.parse_args()
root = os.path.normpath(args.root)
if args.cmd == 'table':
if not args.write and not args.check:
sys.exit('table: pass --write FILE or --check FILE')
return cmd_table(args, root)
return cmd_unity(args, root)
if __name__ == '__main__':
sys.exit(main())
File diff suppressed because it is too large. Load diff