Files
RetroArch/configuration.c
T
LibretroAdmin ccffeb553a slang: drop vendored glslang and SPIRV-Cross
rslc is the slang compiler everywhere. ./configure --enable-glslang
--enable-spirv_cross links the system's glslang and SPIRV-Cross next to
it when both are found, and only then does Settings > Drivers offer a
Shader Compiler choice between the two: one setting read per stage
picks the path, with nothing copied.

The MSVC 2010 project builds Vulkan and rslc. Samples that used the
vendored copies run on rslc or the system's SPIRV-Cross.
2026-10-25 08:52:52 +01:00

11523 lines
427 KiB
C

/* RetroArch - A frontend for libretro.
* Copyright (C) 2010-2014 - Hans-Kristian Arntzen
* Copyright (C) 2011-2017 - Daniel De Matteis
* Copyright (C) 2014-2017 - Jean-André Santoni
* Copyright (C) 2015-2019 - Andrés Suárez (input remapping + other things)
* Copyright (C) 2016-2019 - Brad Parker
*
* RetroArch is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with RetroArch.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include <ctype.h>
#include <libretro.h>
#include <file/config_file.h>
#include <file/file_path.h>
#include <compat/strl.h>
#include <compat/posix_string.h>
#include <string/stdstring.h>
#include <streams/file_stream.h>
#include <streams/rzip_stream.h>
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef HAVE_SSL
#include <net/net_socket_ssl.h>
#endif
#include "file_path_special.h"
#include "command.h"
#include "configuration.h"
#include "gfx/video_windows.h"
#include "content.h"
#include "config.def.h"
#include "config.features.h"
#include "input/input_keymaps.h"
#include "input/input_remapping.h"
#include "input/input_driver.h"
#include "led/led_defines.h"
#include "msg_hash_lbl_str.h"
#include "defaults.h"
#include "core.h"
#include "paths.h"
#include "retroarch.h"
#include "verbosity.h"
#include "audio/audio_driver.h"
#include "record/record_driver.h"
#include "gfx/gfx_animation.h"
#include "tasks/task_content.h"
#ifdef __PS3__
#include "frontend/drivers/platform_ps3_paths.h"
#endif
/* The keychain seals values with libretro-common/crypto, which the
* small consoles leave out; without it the file stays in the clear. */
#if defined(HAVE_KEYCHAIN) && !defined(HAVE_CRYPTO)
#undef HAVE_KEYCHAIN
#endif
#if defined(HAVE_CONFIGFILE) && defined(HAVE_KEYCHAIN)
#include <file/keychain.h>
#endif
#include "tasks/tasks_internal.h"
#include "accessibility.h"
#ifdef ANDROID
/* Defined in frontend/drivers/platform_unix.c; declared here rather
* than via platform_unix.h, whose JNI includes host-side tooling
* cannot preprocess. */
void android_app_set_window_settings(bool notch_write_over,
bool auto_mouse_grab);
#endif
#include "list_special.h"
#if defined(__WINRT__) || defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
#include "uwp/uwp_func.h"
#endif
#include "lakka.h"
#ifdef HAVE_LAKKA_SWITCH
#include "lakka-switch.h"
#endif
#if defined(HAVE_LIBNX)
#include "switch_performance_profiles.h"
#endif
#if __APPLE__
#include "ui/drivers/cocoa/apple_platform.h"
#endif
#include "ui/ui_companion_driver.h"
#ifdef HAVE_LAKKA
#include <time.h>
#ifdef __MACH__
#include <TargetConditionals.h>
#endif
#endif
/* Compile-time upper bounds for setting array sizes.
* These must be >= the actual count returned by the corresponding
* populate_settings_* functions, including the +MAX_USERS slack in
* populate_settings_array. They are used so each populate function
* can do a single exact-size malloc instead of the old
* sizeof(struct)/sizeof(placeholder) over-estimate. */
#define SETTINGS_BOOL_COUNT_MAX 512
#define SETTINGS_INT_COUNT_MAX 64
#define SETTINGS_UINT_COUNT_MAX 320
#define SETTINGS_FLOAT_COUNT_MAX 128
#define SETTINGS_SIZE_COUNT_MAX 8
/* (three a user: the reserved device, and the keyboard and the mouse
* a port is pinned to) */
#define SETTINGS_ARRAY_COUNT_MAX (96 + 3 * MAX_USERS)
#define SETTINGS_PATH_COUNT_MAX 128
enum video_driver_enum
{
VIDEO_GL = 0,
VIDEO_GL1,
VIDEO_GL_CORE,
VIDEO_VULKAN,
VIDEO_METAL,
VIDEO_DRM,
VIDEO_XVIDEO,
VIDEO_SDL,
VIDEO_SDL2,
VIDEO_SDL3,
VIDEO_SDL_DINGUX,
VIDEO_SDL_RS90,
VIDEO_EXT,
VIDEO_WII,
VIDEO_WIIU,
VIDEO_XENON360,
VIDEO_PSP1,
VIDEO_GXM,
VIDEO_PS2,
VIDEO_CTR,
VIDEO_SWITCH,
VIDEO_D3D8,
VIDEO_D3D9_CG,
VIDEO_D3D9_HLSL,
VIDEO_D3D10,
VIDEO_D3D11,
VIDEO_D3D12,
VIDEO_VG,
VIDEO_OMAP,
VIDEO_EXYNOS,
VIDEO_SUNXI,
VIDEO_DISPMANX,
VIDEO_CACA,
VIDEO_GDI,
VIDEO_VGA,
VIDEO_FPGA,
VIDEO_RSX,
VIDEO_NULL
};
enum audio_driver_enum
{
AUDIO_RSOUND = VIDEO_NULL + 1,
AUDIO_AUDIOIO,
AUDIO_OSS,
AUDIO_ALSA,
AUDIO_TINYALSA,
AUDIO_ROAR,
AUDIO_AL,
AUDIO_SL,
AUDIO_JACK,
AUDIO_SDL,
AUDIO_SDL2,
AUDIO_SDL3,
AUDIO_XAUDIO,
AUDIO_PULSE,
AUDIO_EXT,
AUDIO_DSOUND,
AUDIO_WAVEOUT,
AUDIO_WASAPI,
AUDIO_COREAUDIO,
AUDIO_PS3,
AUDIO_XENON360,
AUDIO_WII,
AUDIO_WIIU,
AUDIO_RWEBAUDIO,
AUDIO_AUDIOWORKLET,
AUDIO_PSP,
AUDIO_PS2,
AUDIO_CTR,
AUDIO_SWITCH,
AUDIO_PIPEWIRE,
AUDIO_NULL
};
enum microphone_driver_enum
{
MICROPHONE_ALSA = AUDIO_NULL + 1,
MICROPHONE_SDL2,
MICROPHONE_SDL3,
MICROPHONE_WASAPI,
MICROPHONE_PIPEWIRE,
MICROPHONE_COREAUDIO,
MICROPHONE_NULL
};
enum audio_resampler_driver_enum
{
AUDIO_RESAMPLER_CC = MICROPHONE_NULL + 1,
AUDIO_RESAMPLER_SINC,
AUDIO_RESAMPLER_NEAREST,
AUDIO_RESAMPLER_NULL
};
enum input_driver_enum
{
INPUT_ANDROID = AUDIO_RESAMPLER_NULL + 1,
INPUT_SDL,
INPUT_SDL2,
INPUT_SDL3,
INPUT_SDL_DINGUX,
INPUT_X,
INPUT_WAYLAND,
INPUT_DINPUT,
INPUT_PS4,
INPUT_PS3,
INPUT_PSP,
INPUT_PS2,
INPUT_CTR,
INPUT_SWITCH,
INPUT_XENON360,
INPUT_WII,
INPUT_WIIU,
INPUT_XINPUT,
INPUT_UWP,
INPUT_UDEV,
INPUT_LINUXRAW,
INPUT_COCOA,
INPUT_QNX,
INPUT_RWEBINPUT,
INPUT_DOS,
INPUT_WINRAW,
INPUT_WIN32,
INPUT_NULL
};
enum joypad_driver_enum
{
JOYPAD_PS3 = INPUT_NULL + 1,
JOYPAD_XINPUT,
JOYPAD_GX,
JOYPAD_WIIU,
JOYPAD_XDK,
JOYPAD_PS4,
JOYPAD_PSP,
JOYPAD_PS2,
JOYPAD_CTR,
JOYPAD_SWITCH,
JOYPAD_DINPUT,
JOYPAD_WINMM,
JOYPAD_UDEV,
JOYPAD_LINUXRAW,
JOYPAD_ANDROID,
JOYPAD_SDL,
JOYPAD_SDL_DINGUX,
JOYPAD_DOS,
JOYPAD_HID,
JOYPAD_QNX,
JOYPAD_RWEBPAD,
JOYPAD_MFI,
JOYPAD_WINRAW,
JOYPAD_NULL
};
enum camera_driver_enum
{
CAMERA_V4L2 = JOYPAD_NULL + 1,
CAMERA_RWEBCAM,
CAMERA_ANDROID,
CAMERA_AVFOUNDATION,
CAMERA_PIPEWIRE,
CAMERA_FFMPEG,
CAMERA_NULL
};
enum bluetooth_driver_enum
{
BLUETOOTH_BLUETOOTHCTL = CAMERA_NULL + 1,
BLUETOOTH_BLUEZ,
BLUETOOTH_WINDOWS,
BLUETOOTH_NULL
};
enum wifi_driver_enum
{
WIFI_CONNMANCTL = BLUETOOTH_NULL + 1,
WIFI_NMCLI,
WIFI_NULL
};
enum location_driver_enum
{
LOCATION_ANDROID = WIFI_NULL + 1,
LOCATION_CORELOCATION,
LOCATION_NULL
};
enum osk_driver_enum
{
OSK_PS3 = LOCATION_NULL + 1,
OSK_NULL
};
enum menu_driver_enum
{
MENU_RGUI = OSK_NULL + 1,
MENU_MATERIALUI,
MENU_XMB,
MENU_STRIPES,
MENU_OZONE,
MENU_NULL
};
enum record_driver_enum
{
RECORD_FFMPEG = MENU_NULL + 1,
RECORD_WAV,
RECORD_NULL
};
enum midi_driver_enum
{
MIDI_WINMM = RECORD_NULL + 1,
MIDI_ALSA,
MIDI_COREMIDI,
MIDI_NULL
};
#define DECLARE_BIND(base, bind, desc) { #base, desc, 0, bind, true }
#define DECLARE_META_BIND(level, base, bind, desc) { #base, desc, level, bind, true }
const struct input_bind_map input_config_bind_map[RARCH_BIND_LIST_END_NULL] = {
DECLARE_BIND(b, RETRO_DEVICE_ID_JOYPAD_B, MENU_ENUM_LABEL_VALUE_INPUT_JOYPAD_B),
DECLARE_BIND(y, RETRO_DEVICE_ID_JOYPAD_Y, MENU_ENUM_LABEL_VALUE_INPUT_JOYPAD_Y),
DECLARE_BIND(select, RETRO_DEVICE_ID_JOYPAD_SELECT,MENU_ENUM_LABEL_VALUE_INPUT_JOYPAD_SELECT),
DECLARE_BIND(start, RETRO_DEVICE_ID_JOYPAD_START, MENU_ENUM_LABEL_VALUE_INPUT_JOYPAD_START),
DECLARE_BIND(up, RETRO_DEVICE_ID_JOYPAD_UP, MENU_ENUM_LABEL_VALUE_INPUT_JOYPAD_UP),
DECLARE_BIND(down, RETRO_DEVICE_ID_JOYPAD_DOWN, MENU_ENUM_LABEL_VALUE_INPUT_JOYPAD_DOWN),
DECLARE_BIND(left, RETRO_DEVICE_ID_JOYPAD_LEFT, MENU_ENUM_LABEL_VALUE_INPUT_JOYPAD_LEFT),
DECLARE_BIND(right, RETRO_DEVICE_ID_JOYPAD_RIGHT, MENU_ENUM_LABEL_VALUE_INPUT_JOYPAD_RIGHT),
DECLARE_BIND(a, RETRO_DEVICE_ID_JOYPAD_A, MENU_ENUM_LABEL_VALUE_INPUT_JOYPAD_A),
DECLARE_BIND(x, RETRO_DEVICE_ID_JOYPAD_X, MENU_ENUM_LABEL_VALUE_INPUT_JOYPAD_X),
DECLARE_BIND(l, RETRO_DEVICE_ID_JOYPAD_L, MENU_ENUM_LABEL_VALUE_INPUT_JOYPAD_L),
DECLARE_BIND(r, RETRO_DEVICE_ID_JOYPAD_R, MENU_ENUM_LABEL_VALUE_INPUT_JOYPAD_R),
DECLARE_BIND(l2, RETRO_DEVICE_ID_JOYPAD_L2, MENU_ENUM_LABEL_VALUE_INPUT_JOYPAD_L2),
DECLARE_BIND(r2, RETRO_DEVICE_ID_JOYPAD_R2, MENU_ENUM_LABEL_VALUE_INPUT_JOYPAD_R2),
DECLARE_BIND(l3, RETRO_DEVICE_ID_JOYPAD_L3, MENU_ENUM_LABEL_VALUE_INPUT_JOYPAD_L3),
DECLARE_BIND(r3, RETRO_DEVICE_ID_JOYPAD_R3, MENU_ENUM_LABEL_VALUE_INPUT_JOYPAD_R3),
DECLARE_BIND(l_x_plus, RARCH_ANALOG_LEFT_X_PLUS, MENU_ENUM_LABEL_VALUE_INPUT_ANALOG_LEFT_X_PLUS),
DECLARE_BIND(l_x_minus, RARCH_ANALOG_LEFT_X_MINUS, MENU_ENUM_LABEL_VALUE_INPUT_ANALOG_LEFT_X_MINUS),
DECLARE_BIND(l_y_plus, RARCH_ANALOG_LEFT_Y_PLUS, MENU_ENUM_LABEL_VALUE_INPUT_ANALOG_LEFT_Y_PLUS),
DECLARE_BIND(l_y_minus, RARCH_ANALOG_LEFT_Y_MINUS, MENU_ENUM_LABEL_VALUE_INPUT_ANALOG_LEFT_Y_MINUS),
DECLARE_BIND(r_x_plus, RARCH_ANALOG_RIGHT_X_PLUS, MENU_ENUM_LABEL_VALUE_INPUT_ANALOG_RIGHT_X_PLUS),
DECLARE_BIND(r_x_minus, RARCH_ANALOG_RIGHT_X_MINUS, MENU_ENUM_LABEL_VALUE_INPUT_ANALOG_RIGHT_X_MINUS),
DECLARE_BIND(r_y_plus, RARCH_ANALOG_RIGHT_Y_PLUS, MENU_ENUM_LABEL_VALUE_INPUT_ANALOG_RIGHT_Y_PLUS),
DECLARE_BIND(r_y_minus, RARCH_ANALOG_RIGHT_Y_MINUS, MENU_ENUM_LABEL_VALUE_INPUT_ANALOG_RIGHT_Y_MINUS),
DECLARE_BIND(gun_trigger, RARCH_LIGHTGUN_TRIGGER, MENU_ENUM_LABEL_VALUE_INPUT_LIGHTGUN_TRIGGER),
DECLARE_BIND(gun_offscreen_shot, RARCH_LIGHTGUN_RELOAD, MENU_ENUM_LABEL_VALUE_INPUT_LIGHTGUN_RELOAD),
DECLARE_BIND(gun_aux_a, RARCH_LIGHTGUN_AUX_A, MENU_ENUM_LABEL_VALUE_INPUT_LIGHTGUN_AUX_A),
DECLARE_BIND(gun_aux_b, RARCH_LIGHTGUN_AUX_B, MENU_ENUM_LABEL_VALUE_INPUT_LIGHTGUN_AUX_B),
DECLARE_BIND(gun_aux_c, RARCH_LIGHTGUN_AUX_C, MENU_ENUM_LABEL_VALUE_INPUT_LIGHTGUN_AUX_C),
DECLARE_BIND(gun_start, RARCH_LIGHTGUN_START, MENU_ENUM_LABEL_VALUE_INPUT_LIGHTGUN_START),
DECLARE_BIND(gun_select, RARCH_LIGHTGUN_SELECT, MENU_ENUM_LABEL_VALUE_INPUT_LIGHTGUN_SELECT),
DECLARE_BIND(gun_dpad_up, RARCH_LIGHTGUN_DPAD_UP, MENU_ENUM_LABEL_VALUE_INPUT_LIGHTGUN_DPAD_UP),
DECLARE_BIND(gun_dpad_down, RARCH_LIGHTGUN_DPAD_DOWN, MENU_ENUM_LABEL_VALUE_INPUT_LIGHTGUN_DPAD_DOWN),
DECLARE_BIND(gun_dpad_left, RARCH_LIGHTGUN_DPAD_LEFT, MENU_ENUM_LABEL_VALUE_INPUT_LIGHTGUN_DPAD_LEFT),
DECLARE_BIND(gun_dpad_right, RARCH_LIGHTGUN_DPAD_RIGHT, MENU_ENUM_LABEL_VALUE_INPUT_LIGHTGUN_DPAD_RIGHT),
DECLARE_BIND(turbo, RARCH_TURBO_ENABLE, MENU_ENUM_LABEL_VALUE_INPUT_TURBO),
DECLARE_BIND(hold, RARCH_HOLD_ENABLE, MENU_ENUM_LABEL_VALUE_INPUT_HOLD),
DECLARE_META_BIND(2, enable_hotkey, RARCH_ENABLE_HOTKEY, MENU_ENUM_LABEL_VALUE_INPUT_META_ENABLE_HOTKEY),
DECLARE_META_BIND(1, menu_toggle, RARCH_MENU_TOGGLE, MENU_ENUM_LABEL_VALUE_INPUT_META_MENU_TOGGLE),
#ifdef HAVE_LAKKA
DECLARE_META_BIND(2, exit_emulator, RARCH_QUIT_KEY, MENU_ENUM_LABEL_VALUE_INPUT_META_RESTART_KEY),
#else
DECLARE_META_BIND(2, exit_emulator, RARCH_QUIT_KEY, MENU_ENUM_LABEL_VALUE_INPUT_META_QUIT_KEY),
#endif
DECLARE_META_BIND(2, close_content, RARCH_CLOSE_CONTENT_KEY, MENU_ENUM_LABEL_VALUE_INPUT_META_CLOSE_CONTENT_KEY),
DECLARE_META_BIND(2, reset, RARCH_RESET, MENU_ENUM_LABEL_VALUE_INPUT_META_RESET),
DECLARE_META_BIND(1, toggle_fast_forward, RARCH_FAST_FORWARD_KEY, MENU_ENUM_LABEL_VALUE_INPUT_META_FAST_FORWARD_KEY),
DECLARE_META_BIND(2, hold_fast_forward, RARCH_FAST_FORWARD_HOLD_KEY, MENU_ENUM_LABEL_VALUE_INPUT_META_FAST_FORWARD_HOLD_KEY),
DECLARE_META_BIND(1, toggle_slowmotion, RARCH_SLOWMOTION_KEY, MENU_ENUM_LABEL_VALUE_INPUT_META_SLOWMOTION_KEY),
DECLARE_META_BIND(2, hold_slowmotion, RARCH_SLOWMOTION_HOLD_KEY, MENU_ENUM_LABEL_VALUE_INPUT_META_SLOWMOTION_HOLD_KEY),
DECLARE_META_BIND(1, rewind, RARCH_REWIND, MENU_ENUM_LABEL_VALUE_INPUT_META_REWIND),
DECLARE_META_BIND(2, pause_toggle, RARCH_PAUSE_TOGGLE, MENU_ENUM_LABEL_VALUE_INPUT_META_PAUSE_TOGGLE),
DECLARE_META_BIND(2, frame_advance, RARCH_FRAMEADVANCE, MENU_ENUM_LABEL_VALUE_INPUT_META_FRAMEADVANCE),
DECLARE_META_BIND(2, audio_mute, RARCH_MUTE, MENU_ENUM_LABEL_VALUE_INPUT_META_MUTE),
DECLARE_META_BIND(2, volume_up, RARCH_VOLUME_UP, MENU_ENUM_LABEL_VALUE_INPUT_META_VOLUME_UP),
DECLARE_META_BIND(2, volume_down, RARCH_VOLUME_DOWN, MENU_ENUM_LABEL_VALUE_INPUT_META_VOLUME_DOWN),
DECLARE_META_BIND(1, load_state, RARCH_LOAD_STATE_KEY, MENU_ENUM_LABEL_VALUE_INPUT_META_LOAD_STATE_KEY),
DECLARE_META_BIND(1, save_state, RARCH_SAVE_STATE_KEY, MENU_ENUM_LABEL_VALUE_INPUT_META_SAVE_STATE_KEY),
DECLARE_META_BIND(2, state_slot_increase, RARCH_STATE_SLOT_PLUS, MENU_ENUM_LABEL_VALUE_INPUT_META_STATE_SLOT_PLUS),
DECLARE_META_BIND(2, state_slot_decrease, RARCH_STATE_SLOT_MINUS, MENU_ENUM_LABEL_VALUE_INPUT_META_STATE_SLOT_MINUS),
DECLARE_META_BIND(1, play_replay, RARCH_PLAY_REPLAY_KEY, MENU_ENUM_LABEL_VALUE_INPUT_META_PLAY_REPLAY_KEY),
DECLARE_META_BIND(1, record_replay, RARCH_RECORD_REPLAY_KEY, MENU_ENUM_LABEL_VALUE_INPUT_META_RECORD_REPLAY_KEY),
DECLARE_META_BIND(1, halt_replay, RARCH_HALT_REPLAY_KEY, MENU_ENUM_LABEL_VALUE_INPUT_META_HALT_REPLAY_KEY),
DECLARE_META_BIND(1, save_replay_checkpoint,RARCH_SAVE_REPLAY_CHECKPOINT_KEY, MENU_ENUM_LABEL_VALUE_INPUT_META_SAVE_REPLAY_CHECKPOINT_KEY),
DECLARE_META_BIND(1, prev_replay_checkpoint,RARCH_PREV_REPLAY_CHECKPOINT_KEY, MENU_ENUM_LABEL_VALUE_INPUT_META_PREV_REPLAY_CHECKPOINT_KEY),
DECLARE_META_BIND(1, next_replay_checkpoint,RARCH_NEXT_REPLAY_CHECKPOINT_KEY, MENU_ENUM_LABEL_VALUE_INPUT_META_NEXT_REPLAY_CHECKPOINT_KEY),
DECLARE_META_BIND(2, replay_slot_increase, RARCH_REPLAY_SLOT_PLUS, MENU_ENUM_LABEL_VALUE_INPUT_META_REPLAY_SLOT_PLUS),
DECLARE_META_BIND(2, replay_slot_decrease, RARCH_REPLAY_SLOT_MINUS, MENU_ENUM_LABEL_VALUE_INPUT_META_REPLAY_SLOT_MINUS),
DECLARE_META_BIND(2, disk_eject_toggle, RARCH_DISK_EJECT_TOGGLE, MENU_ENUM_LABEL_VALUE_INPUT_META_DISK_EJECT_TOGGLE),
DECLARE_META_BIND(2, disk_next, RARCH_DISK_NEXT, MENU_ENUM_LABEL_VALUE_INPUT_META_DISK_NEXT),
DECLARE_META_BIND(2, disk_prev, RARCH_DISK_PREV, MENU_ENUM_LABEL_VALUE_INPUT_META_DISK_PREV),
DECLARE_META_BIND(2, shader_toggle, RARCH_SHADER_TOGGLE, MENU_ENUM_LABEL_VALUE_INPUT_META_SHADER_TOGGLE),
DECLARE_META_BIND(2, shader_hold, RARCH_SHADER_HOLD, MENU_ENUM_LABEL_VALUE_INPUT_META_SHADER_HOLD),
DECLARE_META_BIND(2, shader_next, RARCH_SHADER_NEXT, MENU_ENUM_LABEL_VALUE_INPUT_META_SHADER_NEXT),
DECLARE_META_BIND(2, shader_prev, RARCH_SHADER_PREV, MENU_ENUM_LABEL_VALUE_INPUT_META_SHADER_PREV),
DECLARE_META_BIND(2, cheat_toggle, RARCH_CHEAT_TOGGLE, MENU_ENUM_LABEL_VALUE_INPUT_META_CHEAT_TOGGLE),
DECLARE_META_BIND(2, cheat_index_plus, RARCH_CHEAT_INDEX_PLUS, MENU_ENUM_LABEL_VALUE_INPUT_META_CHEAT_INDEX_PLUS),
DECLARE_META_BIND(2, cheat_index_minus, RARCH_CHEAT_INDEX_MINUS, MENU_ENUM_LABEL_VALUE_INPUT_META_CHEAT_INDEX_MINUS),
DECLARE_META_BIND(2, screenshot, RARCH_SCREENSHOT, MENU_ENUM_LABEL_VALUE_INPUT_META_SCREENSHOT),
DECLARE_META_BIND(2, recording_toggle, RARCH_RECORDING_TOGGLE, MENU_ENUM_LABEL_VALUE_INPUT_META_RECORDING_TOGGLE),
DECLARE_META_BIND(2, streaming_toggle, RARCH_STREAMING_TOGGLE, MENU_ENUM_LABEL_VALUE_INPUT_META_STREAMING_TOGGLE),
DECLARE_META_BIND(2, turbo_fire_toggle, RARCH_TURBO_FIRE_TOGGLE, MENU_ENUM_LABEL_VALUE_INPUT_META_TURBO_FIRE_TOGGLE),
DECLARE_META_BIND(2, grab_mouse_toggle, RARCH_GRAB_MOUSE_TOGGLE, MENU_ENUM_LABEL_VALUE_INPUT_META_GRAB_MOUSE_TOGGLE),
DECLARE_META_BIND(2, game_focus_toggle, RARCH_GAME_FOCUS_TOGGLE, MENU_ENUM_LABEL_VALUE_INPUT_META_GAME_FOCUS_TOGGLE),
DECLARE_META_BIND(2, toggle_fullscreen, RARCH_FULLSCREEN_TOGGLE_KEY, MENU_ENUM_LABEL_VALUE_INPUT_META_FULLSCREEN_TOGGLE_KEY),
DECLARE_META_BIND(2, desktop_menu_toggle, RARCH_UI_COMPANION_TOGGLE, MENU_ENUM_LABEL_VALUE_INPUT_META_UI_COMPANION_TOGGLE),
DECLARE_META_BIND(2, toggle_vrr_runloop, RARCH_VRR_RUNLOOP_TOGGLE, MENU_ENUM_LABEL_VALUE_INPUT_META_VRR_RUNLOOP_TOGGLE),
DECLARE_META_BIND(2, runahead_toggle, RARCH_RUNAHEAD_TOGGLE, MENU_ENUM_LABEL_VALUE_INPUT_META_RUNAHEAD_TOGGLE),
DECLARE_META_BIND(2, preempt_toggle, RARCH_PREEMPT_TOGGLE, MENU_ENUM_LABEL_VALUE_INPUT_META_PREEMPT_TOGGLE),
DECLARE_META_BIND(2, video_filter_toggle, RARCH_VIDEO_FILTER_TOGGLE, MENU_ENUM_LABEL_VALUE_INPUT_META_VIDEO_FILTER_TOGGLE),
DECLARE_META_BIND(2, headset_recenter, RARCH_HEADSET_RECENTER, MENU_ENUM_LABEL_VALUE_INPUT_META_HEADSET_RECENTER),
DECLARE_META_BIND(2, laser_pointer_toggle, RARCH_LASER_POINTER_TOGGLE, MENU_ENUM_LABEL_VALUE_INPUT_META_LASER_POINTER_TOGGLE),
DECLARE_META_BIND(2, headset_view_toggle, RARCH_HEADSET_VIEW_TOGGLE, MENU_ENUM_LABEL_VALUE_INPUT_META_HEADSET_VIEW_TOGGLE),
DECLARE_META_BIND(2, fps_toggle, RARCH_FPS_TOGGLE, MENU_ENUM_LABEL_VALUE_INPUT_META_FPS_TOGGLE),
DECLARE_META_BIND(2, toggle_statistics, RARCH_STATISTICS_TOGGLE, MENU_ENUM_LABEL_VALUE_INPUT_META_STATISTICS_TOGGLE),
DECLARE_META_BIND(2, ai_service, RARCH_AI_SERVICE, MENU_ENUM_LABEL_VALUE_INPUT_META_AI_SERVICE),
DECLARE_META_BIND(2, netplay_ping_toggle, RARCH_NETPLAY_PING_TOGGLE, MENU_ENUM_LABEL_VALUE_INPUT_META_NETPLAY_PING_TOGGLE),
DECLARE_META_BIND(2, netplay_host_toggle, RARCH_NETPLAY_HOST_TOGGLE, MENU_ENUM_LABEL_VALUE_INPUT_META_NETPLAY_HOST_TOGGLE),
DECLARE_META_BIND(2, netplay_game_watch, RARCH_NETPLAY_GAME_WATCH, MENU_ENUM_LABEL_VALUE_INPUT_META_NETPLAY_GAME_WATCH),
DECLARE_META_BIND(2, netplay_player_chat, RARCH_NETPLAY_PLAYER_CHAT, MENU_ENUM_LABEL_VALUE_INPUT_META_NETPLAY_PLAYER_CHAT),
DECLARE_META_BIND(2, netplay_fade_chat_toggle, RARCH_NETPLAY_FADE_CHAT_TOGGLE, MENU_ENUM_LABEL_VALUE_INPUT_META_NETPLAY_FADE_CHAT_TOGGLE),
/* Hidden in displaylist */
DECLARE_META_BIND(2, overlay_next, RARCH_OVERLAY_NEXT, MENU_ENUM_LABEL_VALUE_INPUT_META_OVERLAY_NEXT),
DECLARE_META_BIND(2, osk_toggle, RARCH_OSK, MENU_ENUM_LABEL_VALUE_INPUT_META_OSK),
};
#if defined(HAVE_METAL)
#if defined(HAVE_VULKAN)
/* Default to Vulkan/MoltenVK when available */
static const enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_VULKAN;
#else
/* iOS supports both the OpenGL and Metal video drivers; default to OpenGL since Metal support is preliminary */
#if defined(HAVE_COCOATOUCH) && defined(HAVE_OPENGL)
static const enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_GL;
#else
static const enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_METAL;
#endif
#endif
#elif defined(HAVE_D3D11) || defined(__WINRT__) || (defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
/* Default to D3D11 in UWP, even when its compiled with ANGLE, since ANGLE is just calling D3D anyway.*/
static const enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_D3D11;
#elif defined(HAVE_GXM)
static const enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_GXM;
#elif defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) || defined(HAVE_PSGL)
static const enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_GL;
#elif defined(HAVE_OPENGL_CORE) && !defined(__HAIKU__)
static const enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_GL_CORE;
#elif defined(HAVE_D3D9) && defined(HAVE_HLSL)
#define GFX_VIDEO_DRIVER_DEFAULT "d3d9_hlsl"
#elif defined(HAVE_OPENGL1)
static const enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_GL1;
#elif defined(HAVE_VULKAN)
static const enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_VULKAN;
#elif defined(GEKKO)
static const enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_WII;
#elif defined(WIIU)
static const enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_WIIU;
#elif defined(XENON)
static const enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_XENON360;
#elif defined(HAVE_D3D12)
/* FIXME/WARNING: DX12 performance on Xbox is horrible for
* some reason. For now, we will default to D3D11 when possible. */
static const enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_D3D12;
#elif defined(HAVE_D3D10)
static const enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_D3D10;
#elif defined(HAVE_D3D9)
static const enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_D3D9;
#elif defined(HAVE_D3D8)
static const enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_D3D8;
#elif defined(HAVE_VG)
static const enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_VG;
#elif defined(PSP)
static const enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_PSP1;
#elif defined(PS2)
static const enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_PS2;
#elif defined(_3DS)
static const enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_CTR;
#elif defined(SWITCH)
static const enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_SWITCH;
#elif defined(HAVE_XVIDEO)
static const enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_XVIDEO;
#elif defined(HAVE_SDL3)
static const enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_SDL3;
#elif defined(HAVE_SDL) && !defined(HAVE_SDL_DINGUX)
static const enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_SDL;
#elif defined(HAVE_SDL2)
static const enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_SDL2;
#elif defined(HAVE_SDL_DINGUX)
#if defined(RS90) || defined(MIYOO)
static const enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_SDL_RS90;
#else
static const enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_SDL_DINGUX;
#endif
#elif defined(_WIN32) && !defined(_XBOX)
static const enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_GDI;
#elif defined(DJGPP)
static const enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_VGA;
#elif defined(HAVE_FPGA)
static const enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_FPGA;
#elif defined(HAVE_DYLIB) && !defined(ANDROID)
static const enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_EXT;
#elif defined(__PSL1GHT__)
static const enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_RSX;
#else
static const enum video_driver_enum VIDEO_DEFAULT_DRIVER = VIDEO_NULL;
#endif
#if defined(XENON)
static const enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_XENON360;
#elif defined(GEKKO)
static const enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_WII;
#elif defined(WIIU)
static const enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_WIIU;
#elif defined(PSP) || defined(VITA) || defined(ORBIS)
static const enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_PSP;
#elif defined(PS2)
static const enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_PS2;
#elif defined(__PS3__)
static const enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_PS3;
#elif defined(_3DS)
static const enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_CTR;
#elif defined(SWITCH)
static const enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_SWITCH;
#elif (defined(DINGUX_BETA) || defined(MIYOO)) && defined(HAVE_ALSA)
static const enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_ALSA;
#elif defined(DINGUX) && defined(HAVE_AL)
static const enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_AL;
#elif defined(HAVE_PULSE)
static const enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_PULSE;
#elif defined(HAVE_PIPEWIRE)
static const enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_PIPEWIRE;
#elif defined(HAVE_ALSA)
/* Was AUDIO_ALSATHREAD when built with threads. That driver is gone and
* the threaded pipeline, on by default, does what it did from the audio
* thread - and more, since the resampler moves off the frame too. */
static const enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_ALSA;
#elif defined(HAVE_TINYALSA)
static const enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_TINYALSA;
#elif defined(HAVE_AUDIOIO)
static const enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_AUDIOIO;
#elif defined(HAVE_OSS)
static const enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_OSS;
#elif defined(HAVE_JACK)
static const enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_JACK;
#elif defined(HAVE_COREAUDIO)
static const enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_COREAUDIO;
#elif defined(HAVE_WASAPI)
static const enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_WASAPI;
#elif defined(HAVE_XAUDIO)
static const enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_XAUDIO;
#elif defined(HAVE_DSOUND)
static const enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_DSOUND;
#elif defined(HAVE_WAVEOUT)
static const enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_WAVEOUT;
#elif defined(HAVE_AL)
static const enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_AL;
#elif defined(HAVE_SL)
static const enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_SL;
#elif defined(HAVE_AUDIOWORKLET)
static const enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_AUDIOWORKLET;
#elif defined(HAVE_RWEBAUDIO)
static const enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_RWEBAUDIO;
#elif defined(HAVE_SDL3)
static const enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_SDL3;
#elif defined(HAVE_SDL)
static const enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_SDL;
#elif defined(HAVE_SDL2)
static const enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_SDL2;
#elif defined(HAVE_RSOUND)
static const enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_RSOUND;
#elif defined(HAVE_ROAR)
static const enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_ROAR;
#elif defined(HAVE_DYLIB) && !defined(ANDROID)
static const enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_EXT;
#else
static const enum audio_driver_enum AUDIO_DEFAULT_DRIVER = AUDIO_NULL;
#endif
#if defined(HAVE_MICROPHONE)
#if defined(HAVE_WASAPI)
/* The default mic driver on Windows is WASAPI if it's available. */
static const enum microphone_driver_enum MICROPHONE_DEFAULT_DRIVER = MICROPHONE_WASAPI;
#elif defined(HAVE_ALSA)
/* Was MICROPHONE_ALSATHREAD when built with threads. That driver is
* gone: the frontend's threaded capture, on by default, does what its
* worker did - and for every microphone driver that can wait on its
* device, not just this one. */
static const enum microphone_driver_enum MICROPHONE_DEFAULT_DRIVER = MICROPHONE_ALSA;
#elif defined(HAVE_PIPEWIRE)
static const enum microphone_driver_enum MICROPHONE_DEFAULT_DRIVER = MICROPHONE_PIPEWIRE;
#elif defined(HAVE_COREAUDIO)
static const enum microphone_driver_enum MICROPHONE_DEFAULT_DRIVER = MICROPHONE_COREAUDIO;
#elif defined(HAVE_SDL3)
static const enum microphone_driver_enum MICROPHONE_DEFAULT_DRIVER = MICROPHONE_SDL3;
#elif defined(HAVE_SDL2)
/* The default fallback driver is SDL2, if available. */
static const enum microphone_driver_enum MICROPHONE_DEFAULT_DRIVER = MICROPHONE_SDL2;
#else
static const enum microphone_driver_enum MICROPHONE_DEFAULT_DRIVER = MICROPHONE_NULL;
#endif
#endif
#if defined(RS90) || defined(MIYOO)
static const enum audio_resampler_driver_enum AUDIO_DEFAULT_RESAMPLER_DRIVER = AUDIO_RESAMPLER_NEAREST;
#elif defined(PSP) || (defined(__EMSCRIPTEN__) && defined(HAVE_CC_RESAMPLER))
static const enum audio_resampler_driver_enum AUDIO_DEFAULT_RESAMPLER_DRIVER = AUDIO_RESAMPLER_CC;
#else
static const enum audio_resampler_driver_enum AUDIO_DEFAULT_RESAMPLER_DRIVER = AUDIO_RESAMPLER_SINC;
#endif
#if defined(HAVE_FFMPEG)
static const enum record_driver_enum RECORD_DEFAULT_DRIVER = RECORD_FFMPEG;
#else
static const enum record_driver_enum RECORD_DEFAULT_DRIVER = RECORD_WAV;
#endif
#ifdef HAVE_WINMM
static const enum midi_driver_enum MIDI_DEFAULT_DRIVER = MIDI_WINMM;
#elif defined(HAVE_COREMIDI)
static const enum midi_driver_enum MIDI_DEFAULT_DRIVER = MIDI_COREMIDI;
#elif defined(HAVE_ALSA) && !defined(HAVE_HAKCHI) && !defined(HAVE_SEGAM) && !defined(DINGUX)
static const enum midi_driver_enum MIDI_DEFAULT_DRIVER = MIDI_ALSA;
#else
static const enum midi_driver_enum MIDI_DEFAULT_DRIVER = MIDI_NULL;
#endif
#if defined(HAVE_STEAM) && defined(__linux__) && defined(HAVE_SDL3)
static const enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_SDL3;
#elif defined(HAVE_STEAM) && defined(__linux__) && defined(HAVE_SDL2)
static const enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_SDL2;
#elif defined(__WINRT__) || defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
static const enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_UWP;
#elif defined(XENON)
static const enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_XENON360;
#elif defined(_XBOX360) || defined(_XBOX) || defined(HAVE_XINPUT2) || defined(HAVE_XINPUT_XBOX1)
static const enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_XINPUT;
#elif defined(ANDROID)
static const enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_ANDROID;
#elif defined(__EMSCRIPTEN__) && defined(HAVE_SDL2)
static const enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_SDL2;
#elif defined(WEBOS) && defined(HAVE_SDL2)
static const enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_SDL2;
#elif defined(WEBOS) && defined(HAVE_SDL3)
static const enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_SDL3;
#elif defined(WEBOS) && defined(HAVE_WAYLAND)
static const enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_WAYLAND;
#elif defined(__EMSCRIPTEN__)
static const enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_RWEBINPUT;
#elif defined(_WIN32) && defined(HAVE_DINPUT)
static const enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_DINPUT;
#elif defined(_WIN32) && !defined(HAVE_DINPUT) && _WIN32_WINNT >= 0x0501
static const enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_WINRAW;
#elif defined(_WIN32) && defined(HAVE_WIN32INPUT)
static const enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_WIN32;
#elif defined(PS2)
static const enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_PS2;
#elif defined(__PS3__)
static const enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_PS3;
#elif defined(ORBIS)
static const enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_PS4;
#elif defined(PSP) || defined(VITA)
static const enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_PSP;
#elif defined(_3DS)
static const enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_CTR;
#elif defined(SWITCH)
static const enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_SWITCH;
#elif defined(GEKKO)
static const enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_WII;
#elif defined(WIIU)
static const enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_WIIU;
#elif defined(DINGUX) && defined(HAVE_SDL_DINGUX)
static const enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_SDL_DINGUX;
#elif defined(HAVE_X11)
static const enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_X;
#elif defined(HAVE_UDEV)
static const enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_UDEV;
#elif defined(__linux__) && !defined(ANDROID)
static const enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_LINUXRAW;
#elif defined(HAVE_WAYLAND)
static const enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_WAYLAND;
#elif defined(HAVE_COCOA) || defined(HAVE_COCOATOUCH)
static const enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_COCOA;
#elif defined(__QNX__)
static const enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_QNX;
#elif defined(HAVE_SDL3)
static const enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_SDL3;
#elif defined(HAVE_SDL)
static const enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_SDL;
#elif defined(HAVE_SDL2)
static const enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_SDL2;
#elif defined(DJGPP)
static const enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_DOS;
#else
static const enum input_driver_enum INPUT_DEFAULT_DRIVER = INPUT_NULL;
#endif
#if defined(HAVE_STEAM) && defined(__linux__) && (defined(HAVE_SDL2) || defined(HAVE_SDL3))
static const enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_SDL;
#elif defined(HAVE_XINPUT)
static const enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_XINPUT;
#elif defined(GEKKO)
static const enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_GX;
#elif defined(WIIU)
static const enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_WIIU;
#elif defined(WEBOS)
static const enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_SDL;
#elif defined(_XBOX)
static const enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_XDK;
#elif defined(PS2)
static const enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_PS2;
#elif defined(__PS3__) || defined(__PSL1GHT__)
static const enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_PS3;
#elif defined(ORBIS)
static const enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_PS4;
#elif defined(PSP) || defined(VITA)
static const enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_PSP;
#elif defined(_3DS)
static const enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_CTR;
#elif defined(SWITCH)
static const enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_SWITCH;
#elif defined(DINGUX) && defined(HAVE_SDL_DINGUX)
static const enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_SDL_DINGUX;
#elif defined(HAVE_DINPUT)
static const enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_DINPUT;
#elif defined(HAVE_WINMM_JOYPAD)
static const enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_WINMM;
#elif defined(HAVE_UDEV)
static const enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_UDEV;
#elif defined(__linux) && !defined(ANDROID)
static const enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_LINUXRAW;
#elif defined(HAVE_WINRAWINPUT)
static const enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_WINRAW;
#elif defined(ANDROID)
static const enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_ANDROID;
#elif defined(HAVE_MFI)
static const enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_MFI;
#elif defined(HAVE_SDL) || defined(HAVE_SDL2) || defined(HAVE_SDL3)
static const enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_SDL;
#elif defined(DJGPP)
static const enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_DOS;
#elif defined(HAVE_HID)
static const enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_HID;
#elif defined(__QNX__)
static const enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_QNX;
#elif defined(__EMSCRIPTEN__)
static const enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_RWEBPAD;
#else
static const enum joypad_driver_enum JOYPAD_DEFAULT_DRIVER = JOYPAD_NULL;
#endif
#if defined(HAVE_V4L2)
static const enum camera_driver_enum CAMERA_DEFAULT_DRIVER = CAMERA_V4L2;
#elif defined(__EMSCRIPTEN__)
static const enum camera_driver_enum CAMERA_DEFAULT_DRIVER = CAMERA_RWEBCAM;
#elif defined(ANDROID)
static const enum camera_driver_enum CAMERA_DEFAULT_DRIVER = CAMERA_ANDROID;
#elif defined(HAVE_PIPEWIRE)
static const enum camera_driver_enum CAMERA_DEFAULT_DRIVER = CAMERA_PIPEWIRE;
#elif defined(HAVE_FFMPEG)
static const enum camera_driver_enum CAMERA_DEFAULT_DRIVER = CAMERA_FFMPEG;
#elif defined(HAVE_AVF)
static const enum camera_driver_enum CAMERA_DEFAULT_DRIVER = CAMERA_AVFOUNDATION;
#else
static const enum camera_driver_enum CAMERA_DEFAULT_DRIVER = CAMERA_NULL;
#endif
#if defined(HAVE_BLUETOOTH)
# if defined(_WIN32)
static const enum bluetooth_driver_enum BLUETOOTH_DEFAULT_DRIVER = BLUETOOTH_WINDOWS;
# elif defined(HAVE_DBUS)
static const enum bluetooth_driver_enum BLUETOOTH_DEFAULT_DRIVER = BLUETOOTH_BLUEZ;
# else
static const enum bluetooth_driver_enum BLUETOOTH_DEFAULT_DRIVER = BLUETOOTH_BLUETOOTHCTL;
# endif
#else
static const enum bluetooth_driver_enum BLUETOOTH_DEFAULT_DRIVER = BLUETOOTH_NULL;
#endif
#if defined(HAVE_LAKKA)
static const enum wifi_driver_enum WIFI_DEFAULT_DRIVER = WIFI_CONNMANCTL;
#else
static const enum wifi_driver_enum WIFI_DEFAULT_DRIVER = WIFI_NULL;
#endif
#if defined(ANDROID)
static const enum location_driver_enum LOCATION_DEFAULT_DRIVER = LOCATION_ANDROID;
#elif defined(HAVE_CORELOCATION)
static const enum location_driver_enum LOCATION_DEFAULT_DRIVER = LOCATION_CORELOCATION;
#else
static const enum location_driver_enum LOCATION_DEFAULT_DRIVER = LOCATION_NULL;
#endif
#if (defined(_3DS) || defined(DINGUX)) && defined(HAVE_RGUI)
static const enum menu_driver_enum MENU_DEFAULT_DRIVER = MENU_RGUI;
#elif TARGET_OS_IPHONE && !TARGET_OS_TV
#define MENU_DEFAULT_DRIVER (ios_running_on_ipad() ? MENU_OZONE : MENU_MATERIALUI)
#elif defined(HAVE_MATERIALUI) && defined(RARCH_MOBILE)
static const enum menu_driver_enum MENU_DEFAULT_DRIVER = MENU_MATERIALUI;
#elif defined(HAVE_OZONE)
static const enum menu_driver_enum MENU_DEFAULT_DRIVER = MENU_OZONE;
#elif defined(HAVE_XMB) && !defined(_XBOX)
static const enum menu_driver_enum MENU_DEFAULT_DRIVER = MENU_XMB;
#elif defined(HAVE_RGUI)
static const enum menu_driver_enum MENU_DEFAULT_DRIVER = MENU_RGUI;
#else
static const enum menu_driver_enum MENU_DEFAULT_DRIVER = MENU_NULL;
#endif
/* All config related settings go here. */
enum config_bool_flags
{
CFG_BOOL_FLG_DEF_ENABLE = (1 << 0),
CFG_BOOL_FLG_HANDLE = (1 << 1),
CFG_BOOL_FLG_SENSITIVE = (1 << 2)
};
struct config_bool_setting
{
const char *ident;
bool *ptr;
enum rarch_override_setting override;
uint8_t flags;
bool def;
};
struct config_int_setting
{
const char *ident;
int *ptr;
int def;
enum rarch_override_setting override;
uint8_t flags;
/* CFG_HALF_*: when set, ptr addresses a packed word and this row
* is one half of it. The config file keeps a key per half either
* way, so a file written before the pair was packed still loads. */
uint8_t half;
};
struct config_uint_setting
{
const char *ident;
unsigned *ptr;
unsigned def;
enum rarch_override_setting override;
uint8_t flags;
uint8_t half; /* CFG_HALF_*, as for config_int_setting */
};
#define CFG_HALF_NONE 0
#define CFG_HALF_HI 1
#define CFG_HALF_LO 2
/* A row's value, whole word or half of one. The signed pair rides
* VIDEO_POS_PACK's layout and the unsigned pair VIDEO_SCALE_PACK's,
* so the halves come back out through the same macros the rest of
* the tree reads them with. */
static INLINE unsigned cfg_uint_get(const struct config_uint_setting *s)
{
if (s->half == CFG_HALF_HI)
return VIDEO_SCALE_W(*s->ptr);
if (s->half == CFG_HALF_LO)
return VIDEO_SCALE_H(*s->ptr);
return *s->ptr;
}
static INLINE void cfg_uint_set(const struct config_uint_setting *s,
unsigned v)
{
if (s->half == CFG_HALF_HI)
VIDEO_SCALE_PUT_W(*s->ptr, v);
else if (s->half == CFG_HALF_LO)
VIDEO_SCALE_PUT_H(*s->ptr, v);
else
*s->ptr = v;
}
static INLINE int cfg_int_get(const struct config_int_setting *s)
{
if (s->half == CFG_HALF_HI)
return VIDEO_POS_X(*s->ptr);
if (s->half == CFG_HALF_LO)
return VIDEO_POS_Y(*s->ptr);
return *s->ptr;
}
static INLINE void cfg_int_set(const struct config_int_setting *s, int v)
{
if (s->half == CFG_HALF_HI)
VIDEO_POS_PUT_X(*s->ptr, v);
else if (s->half == CFG_HALF_LO)
VIDEO_POS_PUT_Y(*s->ptr, v);
else
*s->ptr = v;
}
struct config_size_setting
{
const char *ident;
size_t *ptr;
size_t def;
enum rarch_override_setting override;
uint8_t flags;
};
struct config_float_setting
{
const char *ident;
float *ptr;
float def;
enum rarch_override_setting override;
uint8_t flags;
};
struct config_array_setting
{
const char *ident;
const char *def;
char *ptr;
enum rarch_override_setting override;
uint8_t flags;
};
struct config_path_setting
{
const char *ident;
char *ptr;
char *def;
uint8_t flags;
};
static void config_settings_list_full(const char *key, unsigned cap)
{
RARCH_ERR("[Config] No room for the setting \"%s\": its list holds %u."
" It is neither loaded nor saved. Raise the list's"
" SETTINGS_*_COUNT_MAX in configuration.c.\n", key, cap);
}
/* Rows the settings/ def files generate, and hand-written ones keyed
* by a menu label: the key, the value's offset in settings_t and its
* default, copied into a list by config_*_rows_add() where the rows
* stood. With the menu, a key is its label's offset in the packed
* label blob, which needs no relocation. A row whose label the blob
* lacks fails to compile here; register such a setting by hand, as
* microphone_block_frames is. */
#ifdef HAVE_MENU
#define CFG_ROW(field, T, d) \
{ (uint32_t)offsetof(settings_t, field), \
(uint16_t)offsetof(struct msg_hash_us_lbl_blob_s, \
m_MENU_ENUM_LABEL_##T), \
(d) }
#define CFG_ROW_KEY(r) ((const char*)&msg_hash_us_lbl_blob + (r)->key)
#define CFG_ROW_STRUCT(kind, type) \
struct config_##kind##_row \
{ \
uint32_t offset; \
uint16_t key; \
type def; \
};
typedef char config_row_key_fits[
(sizeof(struct msg_hash_us_lbl_blob_s) <= 0x10000) ? 1 : -1];
#else
#define CFG_ROW(field, T, d) \
{ MENU_ENUM_LABEL_##T##_STR, (uint32_t)offsetof(settings_t, field), (d) }
#define CFG_ROW_KEY(r) ((r)->key)
#define CFG_ROW_STRUCT(kind, type) \
struct config_##kind##_row \
{ \
const char *key; \
uint32_t offset; \
type def; \
};
#endif
CFG_ROW_STRUCT(bool, bool)
CFG_ROW_STRUCT(float, float)
CFG_ROW_STRUCT(uint, unsigned)
CFG_ROW_STRUCT(int, int)
/* The tables end in an empty row, so that none is empty. */
#define CONFIG_ROWS_ADD(kind, type) \
static unsigned config_##kind##_rows_add( \
struct config_##kind##_setting *tmp, unsigned count, unsigned cap, \
settings_t *settings) \
{ \
const struct config_##kind##_row *r = config_##kind##_rows; \
size_t n = ARRAY_SIZE(config_##kind##_rows) - 1; \
size_t i; \
if (n > cap - count) \
{ \
for (i = cap - count; i < n; i++) \
config_settings_list_full(CFG_ROW_KEY(&r[i]), cap); \
n = cap - count; \
} \
tmp += count; \
for (i = 0; i < n; i++) \
{ \
tmp[i].ident = CFG_ROW_KEY(&r[i]); \
tmp[i].ptr = (type*)((uint8_t*)settings + r[i].offset); \
tmp[i].flags = CFG_BOOL_FLG_DEF_ENABLE; \
tmp[i].def = r[i].def; \
} \
return count + (unsigned)n; \
}
/* A setting is added to the list being made, which holds @cap of
* them (the SETTINGS_*_COUNT_MAX the list was allocated with).
*
* The lists are of a fixed size, and adding a setting used to write
* to the next place whether there was one or not: one setting too
* many for its list wrote past the end of the allocation, and the
* process died of heap corruption at the next allocation - at
* startup, on every run. A setting there is no room for is now left
* out and said so, loudly; tools/settings_capacity_check.c, in CI,
* counts what each list is given against what it holds, so that it
* is found before anything is run. */
#define GENERAL_SETTING(key, configval, default_enable, default_setting, type, handle_setting) \
{ \
if (count < cap) \
{ \
tmp[count].ident = key; \
tmp[count].ptr = configval; \
if (default_enable) \
{ \
tmp[count].flags |= CFG_BOOL_FLG_DEF_ENABLE; \
tmp[count].def = default_setting; \
} \
if (handle_setting) \
tmp[count].flags |= CFG_BOOL_FLG_HANDLE; \
count++; \
} \
else \
config_settings_list_full(key, cap); \
}
#define SETTING_BOOL(key, configval, default_enable, default_setting, handle_setting) \
GENERAL_SETTING(key, configval, default_enable, default_setting, struct config_bool_setting, handle_setting)
#define SETTING_FLOAT(key, configval, default_enable, default_setting, handle_setting) \
GENERAL_SETTING(key, configval, default_enable, default_setting, struct config_float_setting, handle_setting)
#define SETTING_INT(key, configval, default_enable, default_setting, handle_setting) \
GENERAL_SETTING(key, configval, default_enable, default_setting, struct config_int_setting, handle_setting)
#define SETTING_UINT(key, configval, default_enable, default_setting, handle_setting) \
GENERAL_SETTING(key, configval, default_enable, default_setting, struct config_uint_setting, handle_setting)
/* A row that is one half of a packed word: 'which' is CFG_HALF_HI or
* CFG_HALF_LO and configval addresses the whole word. */
#define SETTING_UINT_HALF(key, configval, which, default_enable, default_setting, handle_setting) \
{ \
GENERAL_SETTING(key, configval, default_enable, default_setting, struct config_uint_setting, handle_setting) \
tmp[count - 1].half = (which); \
}
#define SETTING_INT_HALF(key, configval, which, default_enable, default_setting, handle_setting) \
{ \
GENERAL_SETTING(key, configval, default_enable, default_setting, struct config_int_setting, handle_setting) \
tmp[count - 1].half = (which); \
}
#define SETTING_SIZE(key, configval, default_enable, default_setting, handle_setting) \
GENERAL_SETTING(key, configval, default_enable, default_setting, struct config_size_setting, handle_setting)
#define SETTING_PATH(key, configval, default_enable, default_setting, handle_setting) \
GENERAL_SETTING(key, configval, default_enable, default_setting, struct config_path_setting, handle_setting)
#define SETTING_ARRAY(key, configval, default_enable, default_setting, handle_setting) \
GENERAL_SETTING(key, configval, default_enable, default_setting, struct config_array_setting, handle_setting)
#define SETTING_OVERRIDE(override_setting) \
tmp[count-1].override = override_setting
/* As SETTING_OVERRIDE, for the row of @field wherever it was added;
* the override is only read once set, so only then is it looked for. */
#define SETTING_OVERRIDE_FOR(field, override_setting) \
do \
{ \
unsigned j; \
if (retroarch_override_setting_is_set(override_setting, NULL)) \
for (j = 0; j < count; j++) \
if (tmp[j].ptr == &settings->field) \
{ \
tmp[j].override = override_setting; \
break; \
} \
} while (0)
#define SETTING_SENSITIVE() \
tmp[count-1].flags |= CFG_BOOL_FLG_SENSITIVE
#define SETTING_ARRAY_SENSITIVE(key, configval, default_enable, default_setting, handle_setting) \
SETTING_ARRAY(key, configval, default_enable, default_setting, handle_setting) \
SETTING_SENSITIVE()
#define SETTING_PATH_SENSITIVE(key, configval, default_enable, default_setting, handle_setting) \
SETTING_PATH(key, configval, default_enable, default_setting, handle_setting) \
SETTING_SENSITIVE()
/* Forward declarations */
#ifdef HAVE_CONFIGFILE
static void config_parse_file(void);
static size_t config_get_credentials_path(char *s, size_t len);
static bool config_save_credentials(
config_file_t *main_conf,
const struct config_array_setting *array_settings,
int array_settings_size,
const struct config_path_setting *path_settings,
int path_settings_size);
/* Every ident that is marked SETTING_*_SENSITIVE in any build.
* Kept unconditional so a build without a feature still moves
* that feature's secrets out of retroarch.cfg instead of
* carrying them over as unknown entries. */
static const char *config_sensitive_keys[] = {
"cheevos_username",
"cheevos_password",
"cheevos_token",
"webdav_username",
"webdav_password",
"google_drive_refresh_token",
"access_key_id",
"secret_access_key",
"youtube_stream_key",
"twitch_stream_key",
"facebook_stream_key",
"kick_stream_key",
"smb_client_username",
"smb_client_password",
"mcp_server_token",
"netplay_password",
"netplay_spectate_password",
"kiosk_mode_password",
"content_show_settings_password"
};
#ifdef HAVE_KEYCHAIN
/**
* config_keychain_init:
*
* Derives the keychain master key from the per-install key file that
* sits beside retroarch.cfg. Idempotent. Logging is left to the
* callers: the first config load runs before file logging is up.
*
* Returns: true when sealed values can be opened and written.
**/
static bool config_keychain_init(void)
{
char keyfile_path[PATH_MAX_LENGTH];
char config_directory[DIR_MAX_LENGTH];
if (keychain_is_ready())
return true;
if (path_is_empty(RARCH_PATH_CONFIG))
return false;
fill_pathname_basedir(config_directory,
#ifdef __PS3__
g_defaults.path_config,
#else
path_get(RARCH_PATH_CONFIG),
#endif
sizeof(config_directory));
fill_pathname_join_special(keyfile_path, config_directory,
"retroarch-keychain.key", sizeof(keyfile_path));
return keychain_init(keyfile_path);
}
/**
* config_keychain_open_entries:
*
* Replaces every sealed sensitive value in @conf with its plaintext so
* the rest of the loader reads it like any other setting. A value that
* cannot be opened (sealed on another machine or install, tampered)
* is left in place: the loader ignores it as an unknown value and the
* next save carries it through untouched, so nothing is destroyed by
* a key file that is temporarily out of reach.
*
* Returns: number of values that could not be opened.
**/
/* Bit i set: config_sensitive_keys[i] was sealed and could not be
* opened at the last load. Only those are carried through a save
* untouched; any other empty value really is empty, and clearing a
* password has to reach the file. */
static uint32_t config_keychain_unopened = 0;
/* one bit per sensitive key: fails to compile past 32 of them */
typedef char config_sensitive_keys_fit_mask[
(sizeof(config_sensitive_keys) / sizeof(config_sensitive_keys[0]) <= 32) ? 1 : -1];
static int config_sensitive_key_index(const char *key)
{
unsigned i;
for (i = 0; i < ARRAY_SIZE(config_sensitive_keys); i++)
if (string_is_equal(config_sensitive_keys[i], key))
return (int)i;
return -1;
}
static unsigned config_keychain_open_entries(config_file_t *conf)
{
unsigned i;
unsigned failed = 0;
for (i = 0; i < ARRAY_SIZE(config_sensitive_keys); i++)
{
char *plain;
const char *key = config_sensitive_keys[i];
struct config_entry_list *entry = config_get_entry(conf, key);
config_keychain_unopened &= ~((uint32_t)1 << i);
if (!entry || !keychain_value_is_sealed(entry->value))
continue;
if (!(plain = keychain_open_alloc(key, entry->value)))
{
config_keychain_unopened |= (uint32_t)1 << i;
/* Drop it from what the loader sees, or the blob itself
* would be read as the setting's value. The file on disk
* still has it; config_keychain_set() keeps it there. */
config_unset(conf, key);
failed++;
continue;
}
config_set_string(conf, key, plain);
free(plain);
}
return failed;
}
/* Sealed values the last save carried through unopened. */
static unsigned config_keychain_carried = 0;
/* Values set while the keychain was locked, left out of the save. */
static unsigned config_keychain_withheld = 0;
/**
* config_keychain_set:
*
* Writes @value for @key into the keychain file being built, sealed
* when the keychain is ready. An empty @value does not overwrite a
* sealed blob already in the file: that is the value this machine
* could not open at load time, and it belongs to whoever can.
**/
static void config_keychain_set(config_file_t *conf,
const char *key, const char *value, bool from_settings)
{
char *sealed;
const struct config_entry_list *have = config_get_entry(conf, key);
if (string_is_empty(value) && have
&& keychain_value_is_sealed(have->value))
{
int idx = config_sensitive_key_index(key);
if (idx >= 0 && (config_keychain_unopened & ((uint32_t)1 << idx)))
{
config_keychain_carried++;
return;
}
}
/* A locked keychain (wrapped on another machine, passphrase not
* yet given) can seal nothing. A value set here in the meantime is
* not written in the clear; it is left out until the keychain is
* unlocked, and whatever the file held for it stays. Plaintext
* carried over from retroarch.cfg was already in the clear. */
if (from_settings && keychain_is_locked())
{
if (!string_is_empty(value))
config_keychain_withheld++;
return;
}
if (keychain_is_ready() && (sealed = keychain_seal_alloc(key, value)))
{
config_set_string(conf, key, sealed);
free(sealed);
}
else
config_set_string(conf, key, value);
}
#else
#define config_keychain_set(conf, key, value, from_settings) config_set_string(conf, key, value)
#endif
#endif
struct defaults g_defaults;
static settings_t *config_st = NULL;
settings_t *config_get_ptr(void)
{
return config_st;
}
/**
* config_get_default_audio:
*
* Gets default audio driver.
*
* Returns: Default audio driver.
**/
const char *config_get_default_audio(void)
{
enum audio_driver_enum default_driver = AUDIO_DEFAULT_DRIVER;
switch (default_driver)
{
case AUDIO_RSOUND:
return "rsound";
case AUDIO_AUDIOIO:
return "audioio";
case AUDIO_OSS:
return "oss";
case AUDIO_ALSA:
return "alsa";
case AUDIO_TINYALSA:
return "tinyalsa";
case AUDIO_ROAR:
return "roar";
case AUDIO_COREAUDIO:
return "coreaudio";
case AUDIO_AL:
return "openal";
case AUDIO_SL:
return "opensl";
case AUDIO_SDL:
return "sdl";
case AUDIO_SDL2:
return "sdl2";
case AUDIO_SDL3:
return "sdl3";
case AUDIO_DSOUND:
return "dsound";
case AUDIO_WAVEOUT:
return "waveout";
case AUDIO_WASAPI:
return "wasapi";
case AUDIO_XAUDIO:
return "xaudio";
case AUDIO_PULSE:
return "pulse";
case AUDIO_PIPEWIRE:
return "pipewire";
case AUDIO_EXT:
return "ext";
case AUDIO_XENON360:
return "xenon360";
case AUDIO_PS3:
return "ps3";
case AUDIO_WII:
return "gx";
case AUDIO_WIIU:
return "AX";
case AUDIO_PSP:
#if defined(VITA)
return "vita";
#elif defined(ORBIS)
return "orbis";
#else
return "psp";
#endif
case AUDIO_PS2:
return "ps2";
case AUDIO_CTR:
return "dsp";
case AUDIO_SWITCH:
#if defined(HAVE_LIBNX)
/* Was "switch_audren_thread". That driver is gone and this one
* reaches the same decoupling through the threaded pipeline,
* which also takes the resampler off the frame. */
return "switch_audren";
#else
return "switch";
#endif
case AUDIO_RWEBAUDIO:
return "rwebaudio";
case AUDIO_AUDIOWORKLET:
return "audioworklet";
case AUDIO_JACK:
return "jack";
case AUDIO_NULL:
break;
}
return "null";
}
#if defined(HAVE_MICROPHONE)
/**
* config_get_default_microphone:
*
* Gets default microphone driver.
*
* Returns: Default microphone driver.
**/
const char *config_get_default_microphone(void)
{
enum microphone_driver_enum default_driver = MICROPHONE_DEFAULT_DRIVER;
switch (default_driver)
{
case MICROPHONE_ALSA:
return "alsa";
case MICROPHONE_PIPEWIRE:
return "pipewire";
case MICROPHONE_WASAPI:
return "wasapi";
case MICROPHONE_SDL2:
return "sdl2";
case MICROPHONE_SDL3:
return "sdl3";
case MICROPHONE_COREAUDIO:
return "coreaudio";
case MICROPHONE_NULL:
break;
}
return "null";
}
#endif
const char *config_get_default_record(void)
{
enum record_driver_enum default_driver = RECORD_DEFAULT_DRIVER;
switch (default_driver)
{
case RECORD_FFMPEG:
return "ffmpeg";
case RECORD_WAV:
return "wav";
case RECORD_NULL:
break;
}
return "null";
}
/**
* config_get_default_audio_resampler:
*
* Gets default audio resampler driver.
*
* Returns: Default audio resampler driver.
**/
const char *config_get_default_audio_resampler(void)
{
enum audio_resampler_driver_enum default_driver = AUDIO_DEFAULT_RESAMPLER_DRIVER;
switch (default_driver)
{
case AUDIO_RESAMPLER_CC:
return "cc";
case AUDIO_RESAMPLER_SINC:
return "sinc";
case AUDIO_RESAMPLER_NEAREST:
return "nearest";
case AUDIO_RESAMPLER_NULL:
break;
}
return "null";
}
/**
* config_get_default_video:
*
* Gets default video driver.
*
* Returns: Default video driver.
**/
const char *config_get_default_video(void)
{
enum video_driver_enum default_driver = VIDEO_DEFAULT_DRIVER;
switch (default_driver)
{
case VIDEO_GL:
return "gl";
case VIDEO_GL1:
return "gl1";
case VIDEO_GL_CORE:
return "glcore";
case VIDEO_VULKAN:
return "vulkan";
case VIDEO_METAL:
return "metal";
case VIDEO_DRM:
return "drm";
case VIDEO_WII:
return "gx";
case VIDEO_WIIU:
return "gx2";
case VIDEO_XENON360:
return "xenon360";
case VIDEO_D3D8:
return "d3d8";
case VIDEO_D3D9_CG:
return "d3d9_cg";
case VIDEO_D3D9_HLSL:
return "d3d9_hlsl";
case VIDEO_D3D10:
return "d3d10";
case VIDEO_D3D11:
return "d3d11";
case VIDEO_D3D12:
return "d3d12";
case VIDEO_PSP1:
return "psp1";
case VIDEO_PS2:
return "ps2";
case VIDEO_GXM:
return "vita2d";
case VIDEO_CTR:
return "ctr";
case VIDEO_SWITCH:
return "switch";
case VIDEO_XVIDEO:
return "xvideo";
case VIDEO_SDL_DINGUX:
return "sdl_dingux";
case VIDEO_SDL_RS90:
return "sdl_rs90";
case VIDEO_SDL:
return "sdl";
case VIDEO_SDL2:
return "sdl2";
case VIDEO_SDL3:
return "sdl3";
case VIDEO_EXT:
return "ext";
case VIDEO_VG:
return "vg";
case VIDEO_OMAP:
return "omap";
case VIDEO_EXYNOS:
return "exynos";
case VIDEO_DISPMANX:
return "dispmanx";
case VIDEO_SUNXI:
return "sunxi";
case VIDEO_CACA:
return "caca";
case VIDEO_GDI:
return "gdi";
case VIDEO_VGA:
return "vga";
case VIDEO_FPGA:
return "fpga";
case VIDEO_RSX:
return "rsx";
case VIDEO_NULL:
break;
}
return "null";
}
/**
* config_get_default_input:
*
* Gets default input driver.
*
* Returns: Default input driver.
**/
const char *config_get_default_input(void)
{
enum input_driver_enum default_driver = INPUT_DEFAULT_DRIVER;
switch (default_driver)
{
case INPUT_ANDROID:
return "android";
case INPUT_PS4:
return "ps4";
case INPUT_PS3:
return "ps3";
case INPUT_PSP:
#ifdef VITA
return "vita";
#else
return "psp";
#endif
case INPUT_PS2:
return "ps2";
case INPUT_CTR:
return "ctr";
case INPUT_SWITCH:
return "switch";
case INPUT_SDL:
return "sdl";
case INPUT_SDL2:
return "sdl2";
case INPUT_SDL3:
return "sdl3";
case INPUT_SDL_DINGUX:
return "sdl_dingux";
case INPUT_DINPUT:
return "dinput";
case INPUT_WIN32:
return "win32";
case INPUT_WINRAW:
return "raw";
case INPUT_X:
return "x";
case INPUT_WAYLAND:
return "wayland";
case INPUT_XENON360:
return "xenon360";
case INPUT_XINPUT:
return "xinput";
case INPUT_UWP:
return "uwp";
case INPUT_WII:
return "gx";
case INPUT_WIIU:
return "wiiu";
case INPUT_LINUXRAW:
return "linuxraw";
case INPUT_UDEV:
return "udev";
case INPUT_COCOA:
return "cocoa";
case INPUT_QNX:
return "qnx_input";
case INPUT_RWEBINPUT:
return "rwebinput";
case INPUT_DOS:
return "dos";
case INPUT_NULL:
break;
}
return "null";
}
/**
* config_get_default_joypad:
*
* Gets default input joypad driver.
*
* Returns: Default input joypad driver.
**/
const char *config_get_default_joypad(void)
{
enum joypad_driver_enum default_driver = JOYPAD_DEFAULT_DRIVER;
switch (default_driver)
{
case JOYPAD_PS4:
return "ps4";
case JOYPAD_PS3:
return "ps3";
case JOYPAD_XINPUT:
return "xinput";
case JOYPAD_GX:
return "gx";
case JOYPAD_WIIU:
return "wiiu";
case JOYPAD_XDK:
return "xdk";
case JOYPAD_PSP:
#ifdef VITA
return "vita";
#else
return "psp";
#endif
case JOYPAD_PS2:
return "ps2";
case JOYPAD_CTR:
return "ctr";
case JOYPAD_SWITCH:
return "switch";
case JOYPAD_DINPUT:
return "dinput";
case JOYPAD_WINMM:
return "winmm";
case JOYPAD_UDEV:
return "udev";
case JOYPAD_LINUXRAW:
return "linuxraw";
case JOYPAD_ANDROID:
return "android";
case JOYPAD_SDL:
#ifdef HAVE_SDL3
return "sdl3";
#elif defined(HAVE_SDL2)
return "sdl2";
#else
return "sdl";
#endif
case JOYPAD_SDL_DINGUX:
return "sdl_dingux";
case JOYPAD_HID:
return "hid";
case JOYPAD_QNX:
return "qnx";
case JOYPAD_RWEBPAD:
return "rwebpad";
case JOYPAD_DOS:
return "dos";
case JOYPAD_MFI:
return "mfi";
case JOYPAD_WINRAW:
return "winraw";
case JOYPAD_NULL:
break;
}
return "null";
}
/**
* config_get_default_camera:
*
* Gets default camera driver.
*
* Returns: Default camera driver.
**/
const char *config_get_default_camera(void)
{
enum camera_driver_enum default_driver = CAMERA_DEFAULT_DRIVER;
switch (default_driver)
{
case CAMERA_V4L2:
return "video4linux2";
case CAMERA_RWEBCAM:
return "rwebcam";
case CAMERA_ANDROID:
return "android";
case CAMERA_AVFOUNDATION:
return "avfoundation";
case CAMERA_PIPEWIRE:
return "pipewire";
case CAMERA_FFMPEG:
return "ffmpeg";
case CAMERA_NULL:
break;
}
return "null";
}
/**
* config_get_default_bluetooth:
*
* Gets default bluetooth driver.
*
* Returns: Default bluetooth driver.
**/
const char *config_get_default_bluetooth(void)
{
enum bluetooth_driver_enum default_driver = BLUETOOTH_DEFAULT_DRIVER;
switch (default_driver)
{
case BLUETOOTH_BLUETOOTHCTL:
return "bluetoothctl";
case BLUETOOTH_BLUEZ:
return "bluez";
case BLUETOOTH_WINDOWS:
return "windows";
case BLUETOOTH_NULL:
break;
}
return "null";
}
/**
* config_get_default_wifi:
*
* Gets default wifi driver.
*
* Returns: Default wifi driver.
**/
const char *config_get_default_wifi(void)
{
enum wifi_driver_enum default_driver = WIFI_DEFAULT_DRIVER;
switch (default_driver)
{
case WIFI_CONNMANCTL:
return "connmanctl";
case WIFI_NMCLI:
return "nmcli";
case WIFI_NULL:
break;
}
return "null";
}
/**
* config_get_default_led:
*
* Gets default led driver.
*
* Returns: Default led driver.
**/
const char *config_get_default_led(void)
{
return "null";
}
/**
* config_get_default_cloudsync:
*
* Gets default cloud sync driver.
*
* Returns: Default cloud sync driver.
**/
const char *config_get_default_cloudsync(void)
{
return "null";
}
/**
* config_get_default_location:
*
* Gets default location driver.
*
* Returns: Default location driver.
**/
const char *config_get_default_location(void)
{
enum location_driver_enum default_driver = LOCATION_DEFAULT_DRIVER;
switch (default_driver)
{
case LOCATION_ANDROID:
return "android";
case LOCATION_CORELOCATION:
return "corelocation";
case LOCATION_NULL:
break;
}
return "null";
}
/**
* config_get_default_menu:
*
* Gets default menu driver.
*
* Returns: Default menu driver.
**/
const char *config_get_default_menu(void)
{
#ifdef HAVE_MENU
enum menu_driver_enum default_driver = MENU_DEFAULT_DRIVER;
if (*g_defaults.settings_menu)
return g_defaults.settings_menu;
switch (default_driver)
{
case MENU_RGUI:
return "rgui";
case MENU_OZONE:
return "ozone";
case MENU_MATERIALUI:
return "glui";
case MENU_XMB:
return "xmb";
case MENU_STRIPES:
return "stripes";
case MENU_NULL:
break;
}
#endif
return "null";
}
const char *config_get_default_midi(void)
{
enum midi_driver_enum default_driver = MIDI_DEFAULT_DRIVER;
switch (default_driver)
{
case MIDI_WINMM:
return "winmm";
case MIDI_ALSA:
return "alsa";
case MIDI_COREMIDI:
return "coremidi";
case MIDI_NULL:
break;
}
return "null";
}
const char *config_get_midi_driver_options(void)
{
return char_list_new_special(STRING_LIST_MIDI_DRIVERS, NULL);
}
#ifdef HAVE_LAKKA
void config_set_timezone(char *timezone)
{
setenv("TZ", timezone, 1);
tzset();
}
const char *config_get_all_timezones(void)
{
return char_list_new_special(STRING_LIST_TIMEZONES, NULL);
}
static void load_timezone(char *s, size_t len)
{
char haystack[TIMEZONE_LENGTH+32];
RFILE *tzfp = filestream_open(LAKKA_TIMEZONE_PATH,
RETRO_VFS_FILE_ACCESS_READ,
RETRO_VFS_FILE_ACCESS_HINT_NONE);
if (tzfp)
{
static char *needle = "TIMEZONE=";
char *start = NULL;
filestream_gets(tzfp, haystack, sizeof(haystack)-1);
filestream_close(tzfp);
if ((start = strstr(haystack, needle)))
strlcpy(s, start + STRLEN_CONST("TIMEZONE="), len);
else
strlcpy(s, DEFAULT_TIMEZONE, len);
}
else
strlcpy(s, DEFAULT_TIMEZONE, len);
config_set_timezone(s);
}
#endif
bool config_overlay_enable_default(void)
{
if (g_defaults.overlay_set)
return g_defaults.overlay_enable;
#if defined(RARCH_MOBILE) && !TARGET_OS_TV
return true;
#else
return false;
#endif
}
static struct config_array_setting *populate_settings_array(
settings_t *settings, int *size)
{
unsigned i = 0;
unsigned count = 0;
unsigned cap = SETTINGS_ARRAY_COUNT_MAX;
struct config_array_setting *tmp = (struct config_array_setting*)calloc(SETTINGS_ARRAY_COUNT_MAX, sizeof(struct config_array_setting));
if (!tmp)
return NULL;
/* Arrays */
SETTING_ARRAY("audio_driver", settings->arrays.audio_driver, false, NULL, true);
#ifdef HAVE_COMPANION_WIMP
SETTING_ARRAY("desktop_menu_dock_search", settings->arrays.desktop_menu_dock_search, false, NULL, true);
SETTING_ARRAY("desktop_menu_dock_playlists", settings->arrays.desktop_menu_dock_playlists, false, NULL, true);
SETTING_ARRAY("desktop_menu_dock_core", settings->arrays.desktop_menu_dock_core, false, NULL, true);
SETTING_ARRAY("desktop_menu_dock_boxart", settings->arrays.desktop_menu_dock_boxart, false, NULL, true);
SETTING_ARRAY("desktop_menu_dock_title", settings->arrays.desktop_menu_dock_title, false, NULL, true);
SETTING_ARRAY("desktop_menu_dock_screenshot", settings->arrays.desktop_menu_dock_screenshot, false, NULL, true);
SETTING_ARRAY("desktop_menu_dock_logo", settings->arrays.desktop_menu_dock_logo, false, NULL, true);
SETTING_ARRAY("desktop_menu_dock_core_info", settings->arrays.desktop_menu_dock_core_info, false, NULL, true);
SETTING_ARRAY("desktop_menu_dock_log", settings->arrays.desktop_menu_dock_log, false, NULL, true);
SETTING_ARRAY("desktop_menu_options_window", settings->arrays.desktop_menu_options_window, false, NULL, true);
#endif
SETTING_ARRAY("audio_device", settings->arrays.audio_device, false, NULL, true);
SETTING_ARRAY("audio_resampler", settings->arrays.audio_resampler, false, NULL, true);
#ifdef HAVE_MICROPHONE
SETTING_ARRAY("microphone_device", settings->arrays.microphone_device, false, NULL, true);
SETTING_ARRAY("microphone_driver", settings->arrays.microphone_driver, false, NULL, true);
SETTING_ARRAY("microphone_resampler", settings->arrays.microphone_resampler, false, NULL, true);
#endif
SETTING_ARRAY("midi_driver", settings->arrays.midi_driver, false, NULL, true);
SETTING_ARRAY("ui_companion_driver", settings->arrays.ui_companion_driver, false, NULL, true);
SETTING_ARRAY("desktop_menu_hidden_playlists", settings->arrays.desktop_menu_hidden_playlists, false, NULL, true);
SETTING_ARRAY("desktop_menu_highlight_color", settings->arrays.desktop_menu_highlight_color, false, NULL, true);
SETTING_ARRAY("midi_input", settings->arrays.midi_input, true, DEFAULT_MIDI_INPUT, true);
SETTING_ARRAY("midi_output", settings->arrays.midi_output, true, DEFAULT_MIDI_OUTPUT, true);
SETTING_ARRAY("ai_service_backend", settings->arrays.ai_service_backend, false, NULL, true);
SETTING_ARRAY("video_driver", settings->arrays.video_driver, false, NULL, true);
SETTING_ARRAY("video_context_driver", settings->arrays.video_context_driver, false, NULL, true);
SETTING_ARRAY("crt_switch_timings", settings->arrays.crt_switch_timings, false, NULL, true);
SETTING_ARRAY("input_driver", settings->arrays.input_driver, false, NULL, true);
SETTING_ARRAY("input_joypad_driver", settings->arrays.input_joypad_driver, false, NULL, true);
SETTING_ARRAY("input_keyboard_layout", settings->arrays.input_keyboard_layout, false, NULL, true);
#ifdef ANDROID
SETTING_ARRAY("input_android_physical_keyboard", settings->arrays.input_android_physical_keyboard, false, NULL, true);
#endif
{
/* Use static storage for per-user key strings to avoid strdup/free overhead */
static char reserved_keys[MAX_USERS][32];
for (i = 0; i < MAX_USERS; i++)
{
size_t _len = strlcpy_lit(reserved_keys[i], "input_player", sizeof(reserved_keys[i]));
_len += snprintf(reserved_keys[i] + _len, sizeof(reserved_keys[i]) - _len, "%u", i + 1);
strlcpy_lit(reserved_keys[i] + _len, "_reserved_device", sizeof(reserved_keys[i]) - _len);
SETTING_ARRAY(reserved_keys[i], settings->arrays.input_reserved_devices[i], false, NULL, true);
}
}
{
/* input_playerN_keyboard_device: the keyboard the port is given,
* by its identity; input_playerN_keyboard_index follows from it */
static char keyboard_keys[MAX_USERS][40];
for (i = 0; i < MAX_USERS; i++)
{
size_t _len = strlcpy_lit(keyboard_keys[i], "input_player", sizeof(keyboard_keys[i]));
_len += snprintf(keyboard_keys[i] + _len, sizeof(keyboard_keys[i]) - _len, "%u", i + 1);
strlcpy_lit(keyboard_keys[i] + _len, "_keyboard_device", sizeof(keyboard_keys[i]) - _len);
SETTING_ARRAY(keyboard_keys[i], settings->arrays.input_keyboard_device[i], false, NULL, true);
}
}
{
/* input_playerN_mouse_device: the same for the port's mouse,
* set when a mouse is chosen for the port by hand */
static char mouse_keys[MAX_USERS][40];
for (i = 0; i < MAX_USERS; i++)
{
size_t _len = strlcpy_lit(mouse_keys[i], "input_player", sizeof(mouse_keys[i]));
_len += snprintf(mouse_keys[i] + _len, sizeof(mouse_keys[i]) - _len, "%u", i + 1);
strlcpy_lit(mouse_keys[i] + _len, "_mouse_device", sizeof(mouse_keys[i]) - _len);
SETTING_ARRAY(mouse_keys[i], settings->arrays.input_mouse_device[i], false, NULL, true);
}
}
#ifdef HAVE_MENU
SETTING_ARRAY("menu_driver", settings->arrays.menu_driver, false, NULL, true);
#ifdef HAVE_OZONE
SETTING_ARRAY("ozone_menu_color_theme", settings->arrays.menu_ozone_color_theme, false, NULL, false);
#endif
#endif
SETTING_ARRAY("record_driver", settings->arrays.record_driver, false, NULL, true);
SETTING_ARRAY("camera_driver", settings->arrays.camera_driver, false, NULL, true);
SETTING_ARRAY("camera_device", settings->arrays.camera_device, false, NULL, true);
SETTING_ARRAY("bluetooth_driver", settings->arrays.bluetooth_driver, false, NULL, true);
SETTING_ARRAY("wifi_driver", settings->arrays.wifi_driver, false, NULL, true);
SETTING_ARRAY("led_driver", settings->arrays.led_driver, false, NULL, true);
SETTING_ARRAY("location_driver", settings->arrays.location_driver, false, NULL, true);
SETTING_ARRAY("cloud_sync_driver", settings->arrays.cloud_sync_driver, false, NULL, true);
#ifdef HAVE_CHEEVOS
SETTING_ARRAY("cheevos_custom_host", settings->arrays.cheevos_custom_host, false, NULL, true);
SETTING_ARRAY_SENSITIVE("cheevos_username", settings->arrays.cheevos_username, false, NULL, true);
SETTING_ARRAY_SENSITIVE("cheevos_password", settings->arrays.cheevos_password, false, NULL, true);
SETTING_ARRAY_SENSITIVE("cheevos_token", settings->arrays.cheevos_token, false, NULL, true);
SETTING_ARRAY("cheevos_leaderboards_enable", settings->arrays.cheevos_leaderboards_enable, true, "", true); /* deprecated */
#endif
#ifdef HAVE_NETWORKING
SETTING_ARRAY("network_cmd_bind_address", settings->arrays.network_cmd_bind_address, false, NULL, true);
SETTING_ARRAY("mcp_server_bind_address", settings->arrays.mcp_server_bind_address, false, NULL, true);
SETTING_ARRAY_SENSITIVE("mcp_server_token", settings->arrays.mcp_server_token, false, NULL, true);
SETTING_ARRAY("netplay_mitm_server", settings->arrays.netplay_mitm_server, false, NULL, true);
#ifdef HAVE_CLOUDSYNC
SETTING_ARRAY("webdav_url", settings->arrays.webdav_url, false, NULL, true);
SETTING_ARRAY_SENSITIVE("webdav_username", settings->arrays.webdav_username, false, NULL, true);
SETTING_ARRAY_SENSITIVE("webdav_password", settings->arrays.webdav_password, false, NULL, true);
SETTING_ARRAY_SENSITIVE("google_drive_refresh_token", settings->arrays.google_drive_refresh_token, false, NULL, true);
#ifdef HAVE_S3
SETTING_ARRAY("s3_url", settings->arrays.s3_url, false, NULL, true);
SETTING_ARRAY_SENSITIVE("access_key_id", settings->arrays.access_key_id, false, NULL, true);
SETTING_ARRAY_SENSITIVE("secret_access_key", settings->arrays.secret_access_key, false, NULL, true);
#endif
#endif
SETTING_ARRAY_SENSITIVE("youtube_stream_key", settings->arrays.youtube_stream_key, true, NULL, true);
SETTING_ARRAY_SENSITIVE("twitch_stream_key", settings->arrays.twitch_stream_key, true, NULL, true);
SETTING_ARRAY_SENSITIVE("facebook_stream_key", settings->arrays.facebook_stream_key, true, NULL, true);
SETTING_ARRAY_SENSITIVE("kick_stream_key", settings->arrays.kick_stream_key, true, NULL, true);
SETTING_ARRAY("video_gpu_name_vulkan", settings->arrays.video_gpu_name_vulkan, false, NULL, true);
SETTING_ARRAY("video_gpu_name_gl", settings->arrays.video_gpu_name_gl, false, NULL, true);
SETTING_ARRAY("video_gpu_name_d3d10", settings->arrays.video_gpu_name_d3d10, false, NULL, true);
SETTING_ARRAY("video_gpu_name_d3d11", settings->arrays.video_gpu_name_d3d11, false, NULL, true);
SETTING_ARRAY("video_gpu_name_d3d12", settings->arrays.video_gpu_name_d3d12, false, NULL, true);
SETTING_ARRAY("video_gpu_name_metal", settings->arrays.video_gpu_name_metal, false, NULL, true);
SETTING_ARRAY("discord_app_id", settings->arrays.discord_app_id, true, DEFAULT_DISCORD_APP_ID, true);
SETTING_ARRAY("ai_service_url", settings->arrays.ai_service_url, true, DEFAULT_AI_SERVICE_URL, true);
#endif
#ifdef HAVE_SMBCLIENT
SETTING_ARRAY("smb_client_server_address", settings->arrays.smb_client_server_address, false, NULL, true);
SETTING_ARRAY("smb_client_share", settings->arrays.smb_client_share, false, NULL, true);
SETTING_ARRAY("smb_client_subdir", settings->arrays.smb_client_subdir, false, NULL, true);
#endif
#ifdef HAVE_NFSCLIENT
SETTING_ARRAY("nfs_server", settings->arrays.nfs_server, false, NULL, true);
SETTING_ARRAY("nfs_export", settings->arrays.nfs_export, false, NULL, true);
SETTING_ARRAY("nfs_subdir", settings->arrays.nfs_subdir, false, NULL, true);
#ifdef HAVE_CLOUDSYNC
SETTING_ARRAY("cloud_sync_nfs_subdir", settings->arrays.cloud_sync_nfs_subdir, false, NULL, true);
#endif
#endif
#ifdef HAVE_SMBCLIENT
SETTING_ARRAY_SENSITIVE("smb_client_username", settings->arrays.smb_client_username, false, NULL, true);
SETTING_ARRAY_SENSITIVE("smb_client_password", settings->arrays.smb_client_password, false, NULL, true);
SETTING_ARRAY("smb_client_workgroup", settings->arrays.smb_client_workgroup, false, NULL, true);
SETTING_ARRAY("smb_client_realm", settings->arrays.smb_client_realm, false, NULL, true);
SETTING_ARRAY("smb_client_kdc", settings->arrays.smb_client_kdc, false, NULL, true);
#endif
#ifdef HAVE_LAKKA
SETTING_ARRAY("cpu_main_gov", settings->arrays.cpu_main_gov, false, NULL, true);
SETTING_ARRAY("cpu_menu_gov", settings->arrays.cpu_menu_gov, false, NULL, true);
#endif
#ifdef HAVE_LAKKA_SWITCH
SETTING_ARRAY("reboot_payload_name", settings->arrays.reboot_payload_name, false, NULL, true);
#endif
*size = count;
return tmp;
}
static struct config_path_setting *populate_settings_path(
settings_t *settings, int *size)
{
unsigned count = 0;
recording_state_t *recording_st = recording_state_get_ptr();
unsigned cap = SETTINGS_PATH_COUNT_MAX;
struct config_path_setting *tmp = (struct config_path_setting*)calloc(SETTINGS_PATH_COUNT_MAX, sizeof(struct config_path_setting));
if (!tmp)
return NULL;
/* Paths */
#if !defined(ANDROID)
/* On Android the bundle asset paths come from the launch intent
* (see platform_unix.c) and are not user configuration. */
SETTING_PATH("bundle_assets_src_path", settings->paths.bundle_assets_src, false, NULL, true);
SETTING_PATH("bundle_assets_dst_path", settings->paths.bundle_assets_dst, false, NULL, true);
SETTING_PATH("bundle_assets_dst_path_subdir", settings->paths.bundle_assets_dst_subdir, false, NULL, true);
#endif
SETTING_PATH("core_updater_buildbot_cores_url", settings->paths.network_buildbot_url, false, NULL, true);
SETTING_PATH("core_updater_buildbot_assets_url", settings->paths.network_buildbot_assets_url, false, NULL, true);
SETTING_PATH("libretro_directory", settings->paths.directory_libretro, false, NULL, false);
SETTING_PATH("core_options_path", settings->paths.path_core_options, false, NULL, true);
SETTING_PATH("libretro_info_path", settings->paths.path_libretro_info, false, NULL, true);
SETTING_PATH("playlist_directory", settings->paths.directory_playlist, true, NULL, true);
SETTING_PATH("cheat_database_path", settings->paths.path_cheat_database, false, NULL, true);
SETTING_PATH("system_directory", settings->paths.directory_system, true, NULL, true);
SETTING_PATH("cache_directory", settings->paths.directory_cache, false, NULL, true);
SETTING_PATH("audio_dsp_plugin", settings->paths.path_audio_dsp_plugin, false, NULL, true);
SETTING_PATH("audio_filter_dir", settings->paths.directory_audio_filter, true, NULL, true);
SETTING_PATH("video_shader_dir", settings->paths.directory_video_shader, true, NULL, true);
SETTING_PATH("video_filter_dir", settings->paths.directory_video_filter, true, NULL, true);
SETTING_PATH("video_filter", settings->paths.path_softfilter_plugin, false, NULL, true);
SETTING_PATH("video_font_path", settings->paths.path_font, false, NULL, true);
SETTING_PATH("video_record_config", settings->paths.path_record_config, false, NULL, true);
SETTING_PATH("video_stream_config", settings->paths.path_stream_config, false, NULL, true);
SETTING_PATH("video_stream_url", settings->paths.path_stream_url, false, NULL, true);
SETTING_PATH("input_remapping_directory", settings->paths.directory_input_remapping, false, NULL, true);
SETTING_PATH("core_assets_directory", settings->paths.directory_core_assets, true, NULL, true);
SETTING_PATH("assets_directory", settings->paths.directory_assets, true, NULL, true);
SETTING_PATH("dynamic_wallpapers_directory", settings->paths.directory_dynamic_wallpapers, true, NULL, true);
SETTING_PATH("thumbnails_directory", settings->paths.directory_thumbnails, true, NULL, true);
SETTING_PATH("runtime_log_directory", settings->paths.directory_runtime_log, true, NULL, true);
SETTING_PATH("joypad_autoconfig_dir", settings->paths.directory_autoconfig, false, NULL, true);
SETTING_PATH("savefile_directory", dir_get_ptr(RARCH_DIR_SAVEFILE), true, NULL, false);
SETTING_PATH("savestate_directory", dir_get_ptr(RARCH_DIR_SAVESTATE), true, NULL, false);
SETTING_PATH("screenshot_directory", settings->paths.directory_screenshot, true, NULL, true);
SETTING_PATH("recording_output_directory", recording_st->output_dir, false, NULL, true);
SETTING_PATH("recording_config_directory", recording_st->config_dir, false, NULL, true);
SETTING_PATH("content_database_path", settings->paths.path_content_database, false, NULL, true);
SETTING_PATH("content_favorites_path", settings->paths.path_content_favorites, false, NULL, true);
SETTING_PATH("content_history_path", settings->paths.path_content_history, false, NULL, true);
SETTING_PATH("desktop_menu_initial_playlist", settings->paths.desktop_menu_initial_playlist, false, NULL, true);
SETTING_PATH("desktop_menu_custom_theme", settings->paths.desktop_menu_custom_theme, false, NULL, true);
SETTING_PATH("content_image_history_path", settings->paths.path_content_image_history, false, NULL, true);
SETTING_PATH("content_music_history_path", settings->paths.path_content_music_history, false, NULL, true);
SETTING_PATH("content_video_history_path", settings->paths.path_content_video_history, false, NULL, true);
SETTING_PATH("content_favorites_directory", settings->paths.directory_content_favorites, true, NULL, true);
SETTING_PATH("content_history_directory", settings->paths.directory_content_history, true, NULL, true);
SETTING_PATH("content_image_history_directory", settings->paths.directory_content_image_history, true, NULL, true);
SETTING_PATH("content_music_history_directory", settings->paths.directory_content_music_history, true, NULL, true);
SETTING_PATH("content_video_directory", settings->paths.directory_content_video_history, true, NULL, true);
#ifdef HAVE_MENU
SETTING_PATH_SENSITIVE("content_show_settings_password", settings->paths.menu_content_show_settings_password, false, NULL, true);
SETTING_PATH_SENSITIVE("kiosk_mode_password", settings->paths.kiosk_mode_password, false, NULL, true);
SETTING_PATH("menu_wallpaper", settings->paths.path_menu_wallpaper, false, NULL, true);
#ifdef HAVE_RGUI
SETTING_PATH("rgui_menu_theme_preset", settings->paths.path_rgui_theme_preset, false, NULL, true);
#endif
/* Browser and config directories are not RGUI dependent, but name is kept to avoid config file change */
SETTING_PATH("rgui_browser_directory", settings->paths.directory_menu_content, true, NULL, true);
SETTING_PATH("rgui_config_directory", settings->paths.directory_menu_config, true, NULL, true);
#ifdef HAVE_XMB
SETTING_PATH("xmb_font", settings->paths.path_menu_xmb_font, false, NULL, true);
#endif
#ifdef HAVE_OZONE
SETTING_PATH("ozone_font", settings->paths.path_menu_ozone_font, false, NULL, true);
#endif
#endif /* HAVE_MENU */
#ifdef HAVE_OVERLAY
SETTING_PATH("input_overlay", settings->paths.path_overlay, false, NULL, true);
SETTING_PATH("input_osk_overlay", settings->paths.path_osk_overlay, false, NULL, true);
SETTING_PATH("overlay_directory", settings->paths.directory_overlay, true, NULL, true);
SETTING_PATH("osk_overlay_directory", settings->paths.directory_osk_overlay, true, NULL, true);
#endif
#ifdef HAVE_NETWORKING
SETTING_PATH("netplay_ip_address", settings->paths.netplay_server, false, NULL, true);
SETTING_PATH("netplay_custom_mitm_server", settings->paths.netplay_custom_mitm_server, false, NULL, true);
SETTING_PATH("netplay_nickname", settings->paths.username, false, NULL, true);
SETTING_PATH_SENSITIVE("netplay_password", settings->paths.netplay_password, false, NULL, true);
SETTING_PATH_SENSITIVE("netplay_spectate_password", settings->paths.netplay_spectate_password, false, NULL, true);
#endif
#ifdef _3DS
SETTING_PATH("bottom_assets_directory", settings->paths.directory_bottom_assets, true, NULL, true);
#endif
#ifdef HAVE_TEST_DRIVERS
SETTING_PATH("test_input_file_joypad", settings->paths.test_input_file_joypad, false, NULL, true);
SETTING_PATH("test_input_file_general", settings->paths.test_input_file_general, false, NULL, true);
#endif
SETTING_ARRAY("log_dir", settings->paths.log_dir, true, NULL, true);
SETTING_ARRAY("app_icon", settings->paths.app_icon, true, NULL, true);
*size = count;
return tmp;
}
#if defined(__APPLE__) && defined(HAVE_VULKAN)
bool config_metal_arg_buffers_default(void)
{
if (__builtin_available(macOS 12.0, iOS 13.0, tvOS 12.0, *))
return true;
return false;
}
#endif
/* ---------------------------------------------------------------------------
* SETTINGS_*_COUNT_MAX constants are defined above the populate functions.
* Compile-time check (via negative array) can be added here if needed.
* -------------------------------------------------------------------------- */
static const struct config_bool_row config_bool_rows[] = {
/* GENERATED: single-source setting rows (bool kind emits here) */
#define S_BOOL(f, T, n, d, sd, df, c, us, sub) \
CFG_ROW(bools.f, T, d),
#define S_BOOL_NS(f, T, n, d, sd, df, c, us) \
CFG_ROW(bools.f, T, d),
#define S_UINT(f, T, n, d, sd, df, c, mn, mx, st, ob, ok, rp, us, sub)
#define S_UINT_NS(f, T, n, d, sd, df, c, mn, mx, st, ob, ok, rp, us)
#define S_INT(f, T, n, d, sd, df, c, mn, mx, st, ob, ok, rp, us, sub)
#define S_INT_NS(f, T, n, d, sd, df, c, mn, mx, st, ob, ok, rp, us)
#define S_FLOAT(f, T, n, d, rnd, sd, df, c, mn, mx, st, ok, rp, us, sub)
#define S_FLOAT_NS(f, T, n, d, rnd, sd, df, c, mn, mx, st, ok, rp, us)
#define S_STRING(f, T, n, d, sd, c, ok, rp, sta, sel, lf, rt, ui, us, sub)
#define S_STRING_NS(f, T, n, d, sd, c, ok, rp, sta, sel, lf, rt, ui, us)
#define S_DIR(f, T, n, d, el, sd, c, sta, us, sub)
#define S_DIR_NS(f, T, n, d, el, sd, c, sta, us)
#define S_STRING_P(f, T, n, d, sd, c, ok, rp, sta, sel, lf, rt, ui, us, sub)
#define S_STRING_P_NS(f, T, n, d, sd, c, ok, rp, sta, sel, lf, rt, ui, us)
#define S_PATH(f, T, n, d, sd, c, vals, rp, ui, us, sub)
#define S_PATH_NS(f, T, n, d, sd, c, vals, rp, ui, us)
#define S_PATH_DS(f, T, n, df2, sd, c, vals, rp, ui, us, sub)
#define S_PATH_DS_NS(f, T, n, df2, sd, c, vals, rp, ui, us)
#define S_ACTION(T, n, us, sub)
#define S_ACTION_NS(T, n, us)
#define S_BOOL_EX(f, T, n, d, sd, df, c, ok, rp, sta, sel, lf, rt, ui, us, sub) \
CFG_ROW(bools.f, T, d),
#define S_BOOL_EX_NS(f, T, n, d, sd, df, c, ok, rp, sta, sel, lf, rt, ui, us) \
CFG_ROW(bools.f, T, d),
#define S_UINT_EX(f, T, n, d, sd, df, c, mn, mx, st, ob, ok, rp, sta, sel, lf, rt, ui, us, sub)
#define S_UINT_EX_NS(f, T, n, d, sd, df, c, mn, mx, st, ob, ok, rp, sta, sel, lf, rt, ui, us)
#define S_INT_EX(f, T, n, d, sd, df, c, mn, mx, st, ob, ok, rp, sta, sel, lf, rt, ui, us, sub)
#define S_INT_EX_NS(f, T, n, d, sd, df, c, mn, mx, st, ob, ok, rp, sta, sel, lf, rt, ui, us)
#define S_FLOAT_EX(f, T, n, d, rnd, sd, df, c, mn, mx, st, ok, rp, sta, sel, lf, rt, ui, us, sub)
#define S_FLOAT_EX_NS(f, T, n, d, rnd, sd, df, c, mn, mx, st, ok, rp, sta, sel, lf, rt, ui, us)
#define S_ACTION_EX(T, n, sd, ok, rp, c, us, sub)
#define S_ACTION_EX_NS(T, n, sd, ok, rp, c, us)
#define S_BOOL_LV(f, T, TV, n, d, sd, df, c, us, sub) \
CFG_ROW(bools.f, T, d),
#define S_BOOL_LV_NS(f, T, TV, n, d, sd, df, c, us) \
CFG_ROW(bools.f, T, d),
#define S_FLOAT_LV(f, T, TV, n, d, rnd, sd, df, c, us, sub)
#define S_FLOAT_LV_NS(f, T, TV, n, d, rnd, sd, df, c, us)
#define S_STRING_LV(f, T, TV, n, d, sd, c, ok, rp, sta, sel, lf, rt, ui, us, sub)
#define S_STRING_LV_NS(f, T, TV, n, d, sd, c, ok, rp, sta, sel, lf, rt, ui, us)
#define S_ACTION_LV(T, TV, n, sd, ok, rp, c, us, sub)
#define S_ACTION_LV_NS(T, TV, n, sd, ok, rp, c, us)
#define S_INT_AT(offs, T, n, d, sd, df, c, mn, mx, st, ob, ok, rp, us, sub)
#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)
#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"
#endif
#include "settings/settings_def_services_actions.h"
#include "settings/settings_def_video_driver_actions.h"
#include "settings/settings_def_gpu_index_metal.h"
#include "settings/settings_def_gpu_index_d3d12.h"
#include "settings/settings_def_gpu_index_d3d11.h"
#include "settings/settings_def_gpu_index_d3d10.h"
#include "settings/settings_def_gpu_index_egl_gl.h"
#include "settings/settings_def_aspect_ratio.h"
#include "settings/settings_def_viewport_size.h"
#include "settings/settings_def_quit_visibility.h"
#include "settings/settings_def_widget_scale_fullscreen.h"
#ifdef HAVE_MENU
#include "settings/settings_def_widget_scale.h"
#endif
#include "settings/settings_def_cheevos_account.h"
#include "settings/settings_def_menu_show_restart.h"
#include "settings/settings_def_quit_restart.h"
#include "settings/settings_def_menu_frame_rate.h"
#include "settings/settings_def_video_ctx_scaling.h"
#include "settings/settings_def_input_sensors_extra.h"
#ifdef HAVE_NETWORKING
#include "settings/settings_def_netplay_advanced.h"
#endif
#include "settings/settings_def_menu_main_state.h"
#include "settings/settings_def_playlist_management.h"
#ifdef HAVE_MENU
#include "settings/settings_def_menu_privacy.h"
#endif
#ifdef HAVE_MENU
#ifdef HAVE_RGUI
#include "settings/settings_def_menu_landscape.h"
#endif
#endif
#include "settings/settings_def_cloud_sync_general.h"
#ifdef HAVE_OVERLAY
#include "settings/settings_def_overlay_appearance.h"
#endif
#include "settings/settings_def_notification_views.h"
#ifdef HAVE_MENU
#ifdef HAVE_OZONE
#include "settings/settings_def_ozone_typography.h"
#endif
#endif
#include "settings/settings_def_saving.h"
#include "settings/settings_def_notification_positions.h"
#include "settings/settings_def_menu_main_lists_4.h"
#include "settings/settings_def_menu_main_lists_3.h"
#ifdef HAVE_MENU
#ifdef HAVE_MATERIALUI
#include "settings/settings_def_ozone_extras.h"
#endif
#endif
#include "settings/settings_def_menu_main_lists_2.h"
#ifdef HAVE_OVERLAY
#include "settings/settings_def_overlay_mouse.h"
#endif
#ifdef HAVE_OVERLAY
#include "settings/settings_def_overlay_lightgun.h"
#endif
#include "settings/settings_def_input_turbo_fire.h"
#ifdef _3DS
#include "settings/settings_def_ui_appearance.h"
#endif
#include "settings/settings_def_menu_entry_display.h"
#include "settings/settings_def_crt_switchres.h"
#include "settings/settings_def_video_sdl_display_server.h"
#include "settings/settings_def_audio_state.h"
#include "settings/settings_def_analog_deadzone.h"
#include "settings/settings_def_desktop_menu.h"
#include "settings/settings_def_audio_device.h"
#include "settings/settings_def_ai_service_options.h"
#include "settings/settings_def_video_output_misc.h"
#ifdef HAVE_NETWORKING
#include "settings/settings_def_netplay_visibility.h"
#endif
#ifdef HAVE_MICROPHONE
#include "settings/settings_def_microphone_general.h"
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_startup.h"
#endif
#include "settings/settings_def_accessibility.h"
#include "settings/settings_def_video_refresh_rate.h"
#ifdef HAVE_MENU
#if defined(HAVE_MATERIALUI) || defined(HAVE_XMB) || defined(HAVE_OZONE)
#include "settings/settings_def_menu_header_footer.h"
#endif
#endif
#include "settings/settings_def_logging.h"
#include "settings/settings_def_frame_throttle_general.h"
#include "settings/settings_def_refresh_autoswitch.h"
#include "settings/settings_def_audio_skew.h"
#include "settings/settings_def_wifi.h"
#ifdef HAVE_MIST
#include "settings/settings_def_steam_presence.h"
#endif
#include "settings/settings_def_playlist_sorting.h"
#ifdef HAVE_MENU
#if defined(HAVE_OZONE) || defined(HAVE_XMB)
#include "settings/settings_def_playlist_flags.h"
#endif
#endif
#include "settings/settings_def_notification_enable.h"
#ifdef HAVE_MENU
#include "settings/settings_def_rgui_particle_effect.h"
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_savestate_resume.h"
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_framebuffer_opacity.h"
#endif
#include "settings/settings_def_input_haptics.h"
#include "settings/settings_def_input_general.h"
#ifdef HAVE_MENU
#include "settings/settings_def_ozone_appearance.h"
#endif
#ifdef HAVE_MENU
#ifdef HAVE_XMB
#include "settings/settings_def_rgui_appearance.h"
#endif
#endif
#include "settings/settings_def_playlist_display.h"
#ifdef HAVE_CHEEVOS
#include "settings/settings_def_cheevos_general.h"
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_appearance.h"
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_visibility.h"
#endif
#ifdef HAVE_NETWORKING
#include "settings/settings_def_netplay_sync.h"
#endif
#ifdef HAVE_MICROPHONE
#ifdef HAVE_WASAPI
#include "settings/settings_def_mic_wasapi.h"
#endif
#endif
#ifdef HAVE_MENU
#ifdef HAVE_OZONE
#include "settings/settings_def_ozone_sidebar.h"
#endif
#endif
#include "settings/settings_def_input_bind_timeouts.h"
#include "settings/settings_def_video_hdr_toggles.h"
#include "settings/settings_def_video_stereo.h"
#include "settings/settings_def_video_headset.h"
#include "settings/settings_def_rewind.h"
#include "settings/settings_def_playlist_history.h"
#ifdef HAVE_MENU
#include "settings/settings_def_menu_scroll.h"
#endif
#ifdef HAVE_MENU
#ifdef HAVE_XMB
#include "settings/settings_def_menu_thumbnails.h"
#endif
#endif
#include "settings/settings_def_input_turbo.h"
#include "settings/settings_def_frame_delay.h"
#ifdef HAVE_WASAPI
#include "settings/settings_def_audio_wasapi.h"
#endif
#include "settings/settings_def_audio_resampler_quality.h"
#ifdef HAVE_MENU
#include "settings/settings_def_wallpaper_opacity.h"
#endif
#ifdef HAVE_OVERLAY
#include "settings/settings_def_overlay_opacity.h"
#endif
#ifdef HAVE_MENU
#if !(defined(RARCH_CONSOLE) || defined(RARCH_MOBILE))
#include "settings/settings_def_widget_scale_windowed.h"
#endif
#endif
#include "settings/settings_def_video_hdr.h"
#ifdef HAVE_WINDOW_OFFSET
#include "settings/settings_def_video_window_offset.h"
#endif
#include "settings/settings_def_vulkan_gpu_index.h"
#ifdef HAVE_SMBCLIENT
#include "settings/settings_def_smb_client_auth.h"
#endif
#include "settings/settings_def_midi_volume.h"
#ifdef HAVE_NETWORKING
#include "settings/settings_def_netplay_ports.h"
#endif
#ifdef HAVE_MENU
#ifdef HAVE_RGUI
#include "settings/settings_def_rgui_thumbnail_downscale.h"
#endif
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_thumbnail_upscale.h"
#endif
#ifdef HAVE_MENU
#ifdef HAVE_XMB
#include "settings/settings_def_xmb_color_theme.h"
#endif
#endif
#include "settings/settings_def_xmb_shader_pipeline.h"
#include "settings/settings_def_xmb_animations.h"
#ifdef HAVE_MENU
#ifdef HAVE_RGUI
#include "settings/settings_def_rgui_color_theme.h"
#endif
#endif
#ifdef HAVE_MENU
#ifdef HAVE_RGUI
#include "settings/settings_def_rgui_aspect.h"
#endif
#endif
#include "settings/settings_def_record_threads.h"
#include "settings/settings_def_stream_quality.h"
#include "settings/settings_def_record_quality.h"
#include "settings/settings_def_input_touch_scale.h"
#ifdef GEKKO
#include "settings/settings_def_input_mouse_scale.h"
#endif
#include "settings/settings_def_black_frame_insertion.h"
#include "settings/settings_def_shader_delay.h"
#include "settings/settings_def_shader_simulated_resolution.h"
#include "settings/settings_def_screen_brightness.h"
#include "settings/settings_def_video_rotation.h"
#include "settings/settings_def_video_monitor_index.h"
#include "settings/settings_def_rewind_step.h"
#ifdef ANDROID
#include "settings/settings_def_frame_throttle_slowmotion.h"
#endif
#include "settings/settings_def_frame_throttle_fastforward.h"
#if defined(DINGUX)
#if defined(RS90) || defined(MIYOO)
#include "settings/settings_def_dingux_rs90.h"
#endif
#endif
#if defined(DINGUX)
#if defined(DINGUX_BETA)
#include "settings/settings_def_dingux_refresh_rate.h"
#endif
#endif
#if defined(DINGUX)
#include "settings/settings_def_dingux_ipu.h"
#endif
#include "settings/settings_def_ai_service.h"
#include "settings/settings_def_video_window_custom_size.h"
#include "settings/settings_def_video_window_save_position.h"
#include "settings/settings_def_user_language_action.h"
#ifdef _3DS
#include "settings/settings_def_3ds_bottom_lcd.h"
#endif
#ifdef HAVE_OVERLAY
#include "settings/settings_def_overlay_auto_scale.h"
#endif
#include "settings/settings_def_notification_widgets.h"
#ifdef HAVE_SMBCLIENT
#include "settings/settings_def_smb_client.h"
#endif
#ifdef HAVE_NETWORKING
#ifdef HAVE_NETWORKGAMEPAD
#include "settings/settings_def_netplay_stateless.h"
#endif
#endif
#include "settings/settings_def_audio_format.h"
#include "settings/settings_def_menu_main_actions_12.h"
#include "settings/settings_def_menu_main_actions_11.h"
#include "settings/settings_def_menu_main_actions_10.h"
#include "settings/settings_def_audio_asio_action.h"
#ifdef HAVE_COMMAND
#include "settings/settings_def_netplay_nat.h"
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_ex_pilot.h"
#endif
#include "settings/settings_def_accounts_streaming.h"
#include "settings/settings_def_accounts_cheevos.h"
#include "settings/settings_def_power_action.h"
#include "settings/settings_def_netplay_action.h"
#include "settings/settings_def_video_actions_5.h"
#include "settings/settings_def_video_actions_3.h"
#include "settings/settings_def_input_actions.h"
#include "settings/settings_def_video_actions_2.h"
#include "settings/settings_def_video_actions_1.h"
#include "settings/settings_def_saving_actions.h"
#include "settings/settings_def_menu_main_actions_9.h"
#include "settings/settings_def_menu_main_actions_8.h"
#include "settings/settings_def_menu_main_actions_7.h"
#include "settings/settings_def_menu_main_actions_6.h"
#include "settings/settings_def_menu_main_actions_5.h"
#include "settings/settings_def_menu_main_actions_4.h"
#include "settings/settings_def_menu_main_actions_2.h"
#include "settings/settings_def_menu_main_actions_3.h"
#include "settings/settings_def_menu_main_actions_1.h"
#include "settings/settings_def_user_identity.h"
#include "settings/settings_def_netplay_passwords.h"
#include "settings/settings_def_netplay_server.h"
#include "settings/settings_def_recording_paths.h"
#include "settings/settings_def_streaming_paths.h"
#include "settings/settings_def_settings_password.h"
#include "settings/settings_def_kiosk_password.h"
#include "settings/settings_def_ozone_font_path.h"
#include "settings/settings_def_xmb_font_path.h"
#include "settings/settings_def_rgui_theme_path.h"
#include "settings/settings_def_overlay_preset_path.h"
#include "settings/settings_def_notification_font_path.h"
#include "settings/settings_def_menu_wallpaper_path.h"
#include "settings/settings_def_audio_dsp_path.h"
#include "settings/settings_def_video_filter_path.h"
#include "settings/settings_def_dir_user.h"
#include "settings/settings_def_dir_core.h"
#include "settings/settings_def_dir_cache_log.h"
#include "settings/settings_def_cloud_sync_s3.h"
#include "settings/settings_def_cloud_sync_webdav.h"
#ifdef HAVE_MICROPHONE
#include "settings/settings_def_microphone_block.h"
#endif
#include "settings/settings_def_updater_backup.h"
#include "settings/settings_def_updater_experimental.h"
#include "settings/settings_def_updater_extract.h"
#include "settings/settings_def_gamemode.h"
#include "settings/settings_def_sustained_performance.h"
#include "settings/settings_def_power_plan.h"
#ifdef HAVE_MENU
#include "settings/settings_def_quick_menu_shaders_view.h"
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_online_updater_view.h"
#endif
#if defined(HAVE_MENU) && defined(HAVE_SMBCLIENT)
#include "settings/settings_def_settings_show_smb.h"
#endif
#ifdef HAVE_MENU
#ifdef HAVE_MIST
#include "settings/settings_def_settings_show_steam.h"
#endif
#endif
#ifdef HAVE_NETWORKING
#include "settings/settings_def_network_ondemand_thumbnails.h"
#endif
#include "settings/settings_def_network_stdin_cmd.h"
#include "settings/settings_def_privacy_discord.h"
#include "settings/settings_def_privacy_location.h"
#include "settings/settings_def_privacy_camera.h"
#ifdef HAVE_MENU
#include "settings/settings_def_menu_core_updater_view.h"
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_restart_view.h"
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_thumbnail_background.h"
#endif
#ifdef HAVE_MENU
#ifdef HAVE_RGUI
#include "settings/settings_def_menu_start_screen.h"
#endif
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_content_settings_view.h"
#endif
#ifdef HAVE_THREADS
#include "settings/settings_def_menu_threaded_data.h"
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_wraparound.h"
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_horizontal_animation.h"
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_show_full_paths.h"
#endif
#ifdef HAVE_MENU
#ifdef HAVE_RGUI
#include "settings/settings_def_menu_rgui_transparency.h"
#endif
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_wallpaper.h"
#endif
#include "settings/settings_def_runahead_warnings.h"
#include "settings/settings_def_input_auto_mouse_grab.h"
#if defined(HAVE_DINPUT) || defined(HAVE_WINRAWINPUT)
#include "settings/settings_def_input_nowinkey.h"
#endif
#include "settings/settings_def_overlay_enable.h"
#ifdef HAVE_MICROPHONE
#include "settings/settings_def_microphone.h"
#endif
#include "settings/settings_def_audio_sync.h"
#include "settings/settings_def_audio_enable.h"
#include "settings/settings_def_ui_menubar.h"
#include "settings/settings_def_video_window_decorations.h"
#include "settings/settings_def_video_srgb.h"
#ifdef WIIU
#include "settings/settings_def_video_wiiu_drc.h"
#endif
#include "settings/settings_def_shader_watch.h"
#if defined(DINGUX)
#include "settings/settings_def_video_dingux_ipu.h"
#endif
#include "settings/settings_def_video_notch.h"
#ifdef HAVE_MENU
#ifdef HAVE_MIST
#include "settings/settings_def_menu_steam.h"
#endif
#endif
#ifdef ANDROID
#include "settings/settings_def_input_android_workaround.h"
#endif
#include "settings/settings_def_video_frame_time_sample.h"
#include "settings/settings_def_video_adaptive_vsync.h"
#include "settings/settings_def_video_gl_direct_spirv.h"
#include "settings/settings_def_shader_compiler.h"
#include "settings/settings_def_video_smooth.h"
#include "settings/settings_def_frame_time_counter.h"
#include "settings/settings_def_menu_filebrowser.h"
#include "settings/settings_def_video_filter_rotation.h"
#ifdef HAVE_CHEEVOS
#include "settings/settings_def_cheevos.h"
#endif
#include "settings/settings_def_video_suspend_screensaver.h"
#ifdef HAVE_CHEEVOS
#include "settings/settings_def_cheevos_visibility.h"
#endif
#include "settings/settings_def_ui_focus.h"
#include "settings/settings_def_multimedia.h"
#ifdef HAVE_MENU
#ifdef HAVE_RGUI
#include "settings/settings_def_menu_rgui_thumbnails.h"
#endif
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_power_views.h"
#endif
#include "settings/settings_def_recording_video.h"
#include "settings/settings_def_input_backtouch.h"
#ifdef HAVE_MENU
#ifdef HAVE_RGUI
#include "settings/settings_def_menu_rgui_layout.h"
#endif
#endif
#include "settings/settings_def_cheats_apply.h"
#include "settings/settings_def_shader_preset.h"
#ifdef UDEV_TOUCH_SUPPORT
#include "settings/settings_def_input_vmouse.h"
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_desktop.h"
#endif
#ifdef GEKKO
#include "settings/settings_def_video_gamecube.h"
#endif
#include "settings/settings_def_menu_sounds.h"
#ifdef HAVE_MENU
#include "settings/settings_def_menu_main_views.h"
#include "settings/settings_def_menu_quick_views.h"
#include "settings/settings_def_menu_settings_views.h"
#endif
#include "settings/settings_def_video_bias.h"
#include "settings/settings_def_video_window.h"
#undef SETTINGS_DEF_CONFIG_PASS
#undef S_BOOL
#undef S_BOOL_NS
#undef S_BOOL_H
#undef S_BOOL_NS_H
#undef S_UINT
#undef S_UINT_NS
#undef S_UINT_H
#undef S_UINT_NS_H
#undef S_INT
#undef S_INT_NS
#undef S_INT_H
#undef S_INT_NS_H
#undef S_FLOAT
#undef S_FLOAT_NS
#undef S_FLOAT_H
#undef S_FLOAT_NS_H
#undef S_STRING
#undef S_STRING_NS
#undef S_STRING_H
#undef S_STRING_NS_H
#undef S_DIR
#undef S_DIR_NS
#undef S_DIR_H
#undef S_DIR_NS_H
#undef S_STRING_P
#undef S_STRING_P_NS
#undef S_STRING_P_H
#undef S_STRING_P_NS_H
#undef S_PATH
#undef S_PATH_NS
#undef S_PATH_H
#undef S_PATH_NS_H
#undef S_PATH_DS
#undef S_PATH_DS_NS
#undef S_PATH_DS_H
#undef S_PATH_DS_NS_H
#undef S_ACTION
#undef S_ACTION_NS
#undef S_ACTION_H
#undef S_ACTION_NS_H
#undef S_BOOL_EX
#undef S_BOOL_EX_NS
#undef S_BOOL_EX_H
#undef S_BOOL_EX_NS_H
#undef S_UINT_EX
#undef S_UINT_EX_NS
#undef S_UINT_EX_H
#undef S_UINT_EX_NS_H
#undef S_INT_EX
#undef S_INT_EX_NS
#undef S_INT_EX_H
#undef S_INT_EX_NS_H
#undef S_FLOAT_EX
#undef S_FLOAT_EX_NS
#undef S_FLOAT_EX_H
#undef S_FLOAT_EX_NS_H
#undef S_ACTION_EX
#undef S_ACTION_EX_NS
#undef S_ACTION_EX_H
#undef S_ACTION_EX_NS_H
#undef S_BOOL_LV
#undef S_BOOL_LV_NS
#undef S_BOOL_LV_H
#undef S_BOOL_LV_NS_H
#undef S_FLOAT_LV
#undef S_FLOAT_LV_NS
#undef S_FLOAT_LV_H
#undef S_FLOAT_LV_NS_H
#undef S_STRING_LV
#undef S_STRING_LV_NS
#undef S_STRING_LV_H
#undef S_STRING_LV_NS_H
#undef S_ACTION_LV
#undef S_ACTION_LV_NS
#undef S_ACTION_LV_H
#undef S_ACTION_LV_NS_H
#undef S_INT_AT
#undef S_INT_AT_NS
#undef S_INT_AT_H
#undef S_INT_AT_NS_H
#undef S_UINT_AT_EX
#undef S_UINT_AT_EX_NS
#undef S_UINT_AT_EX_H
#undef S_UINT_AT_EX_NS_H
CFG_ROW(bools.auto_overrides_enable, AUTO_OVERRIDES_ENABLE, DEFAULT_AUTO_OVERRIDES_ENABLE),
CFG_ROW(bools.auto_remaps_enable, AUTO_REMAPS_ENABLE, DEFAULT_AUTO_REMAPS_ENABLE),
CFG_ROW(bools.auto_shaders_enable, AUTO_SHADERS_ENABLE, DEFAULT_AUTO_SHADERS_ENABLE),
CFG_ROW(bools.block_sram_overwrite, BLOCK_SRAM_OVERWRITE, DEFAULT_BLOCK_SRAM_OVERWRITE),
CFG_ROW(bools.config_save_minimal, CONFIG_SAVE_MINIMAL, DEFAULT_CONFIG_SAVE_MINIMAL),
CFG_ROW(bools.config_save_on_exit, CONFIG_SAVE_ON_EXIT, DEFAULT_CONFIG_SAVE_ON_EXIT),
CFG_ROW(bools.core_info_savestate_bypass, CORE_INFO_SAVESTATE_BYPASS, DEFAULT_CORE_INFO_SAVESTATE_BYPASS),
CFG_ROW(bools.core_option_category_enable, CORE_OPTION_CATEGORY_ENABLE, DEFAULT_CORE_OPTION_CATEGORY_ENABLE),
CFG_ROW(bools.driver_switch_enable, DRIVER_SWITCH_ENABLE, DEFAULT_DRIVER_SWITCH_ENABLE),
CFG_ROW(bools.game_specific_options, GAME_SPECIFIC_OPTIONS, DEFAULT_GAME_SPECIFIC_OPTIONS),
CFG_ROW(bools.global_core_options, GLOBAL_CORE_OPTIONS, DEFAULT_GLOBAL_CORE_OPTIONS),
CFG_ROW(bools.initial_disk_change_enable, INITIAL_DISK_CHANGE_ENABLE, DEFAULT_INITIAL_DISK_CHANGE_ENABLE),
CFG_ROW(bools.input_descriptor_hide_unbound, INPUT_DESCRIPTOR_HIDE_UNBOUND, DEFAULT_INPUT_DESCRIPTOR_HIDE_UNBOUND),
CFG_ROW(bools.input_descriptor_label_show, INPUT_DESCRIPTOR_LABEL_SHOW, DEFAULT_INPUT_DESCRIPTOR_LABEL_SHOW),
CFG_ROW(bools.remap_save_on_exit, REMAP_SAVE_ON_EXIT, DEFAULT_REMAP_SAVE_ON_EXIT),
CFG_ROW(bools.savestate_auto_load, SAVESTATE_AUTO_LOAD, DEFAULT_SAVESTATE_AUTO_LOAD),
CFG_ROW(bools.savestate_auto_save, SAVESTATE_AUTO_SAVE, DEFAULT_SAVESTATE_AUTO_SAVE),
CFG_ROW(bools.sort_savefiles_by_content_enable, SORT_SAVEFILES_BY_CONTENT_ENABLE, DEFAULT_SORT_SAVEFILES_BY_CONTENT_ENABLE),
CFG_ROW(bools.sort_savefiles_enable, SORT_SAVEFILES_ENABLE, DEFAULT_SORT_SAVEFILES_ENABLE),
CFG_ROW(bools.sort_savestates_by_content_enable, SORT_SAVESTATES_BY_CONTENT_ENABLE, DEFAULT_SORT_SAVESTATES_BY_CONTENT_ENABLE),
CFG_ROW(bools.sort_savestates_enable, SORT_SAVESTATES_ENABLE, DEFAULT_SORT_SAVESTATES_ENABLE),
CFG_ROW(bools.sort_screenshots_by_content_enable, SORT_SCREENSHOTS_BY_CONTENT_ENABLE, DEFAULT_SORT_SCREENSHOTS_BY_CONTENT_ENABLE),
CFG_ROW(bools.video_allow_rotate, VIDEO_ALLOW_ROTATE, DEFAULT_ALLOW_ROTATE),
CFG_ROW(bools.video_shared_context, VIDEO_SHARED_CONTEXT, DEFAULT_VIDEO_SHARED_CONTEXT),
#ifdef HAVE_PSGL
CFG_ROW(bools.video_pal60_enable, PAL60_ENABLE, DEFAULT_PAL60_ENABLE),
#endif
#ifdef HAVE_MENU
CFG_ROW(bools.menu_scroll_fast, MENU_SCROLL_FAST, DEFAULT_MENU_SCROLL_FAST),
CFG_ROW(bools.menu_show_quit_retroarch, MENU_SHOW_QUIT_RETROARCH, DEFAULT_MENU_SHOW_QUIT),
#endif
#ifdef HAVE_CHEEVOS
CFG_ROW(bools.cheevos_appearance_padding_auto, CHEEVOS_APPEARANCE_PADDING_AUTO, DEFAULT_CHEEVOS_APPEARANCE_PADDING_AUTO),
CFG_ROW(bools.cheevos_enable, CHEEVOS_ENABLE, DEFAULT_CHEEVOS_ENABLE),
CFG_ROW(bools.cheevos_hardcore_mode_enable, CHEEVOS_HARDCORE_MODE_ENABLE, true),
CFG_ROW(bools.cheevos_visibility_lboard_trackers, CHEEVOS_VISIBILITY_LBOARD_TRACKERS, DEFAULT_CHEEVOS_VISIBILITY_LBOARD_TRACKERS),
#endif
#ifdef HAVE_OVERLAY
CFG_ROW(bools.input_osk_overlay_auto_scale, INPUT_OSK_OVERLAY_AUTO_SCALE, DEFAULT_INPUT_OVERLAY_AUTO_SCALE),
CFG_ROW(bools.input_overlay_auto_rotate, INPUT_OVERLAY_AUTO_ROTATE, DEFAULT_OVERLAY_AUTO_ROTATE),
#endif
{ 0 }
};
CONFIG_ROWS_ADD(bool, bool)
static struct config_bool_setting *populate_settings_bool(
settings_t *settings, int *size)
{
unsigned cap = SETTINGS_BOOL_COUNT_MAX;
struct config_bool_setting *tmp = (struct config_bool_setting*)calloc(SETTINGS_BOOL_COUNT_MAX, sizeof(struct config_bool_setting));
unsigned count = 0;
if (!tmp)
return NULL;
SETTING_BOOL("accessibility_enable", &settings->bools.accessibility_enable, true, DEFAULT_ACCESSIBILITY_ENABLE, false);
SETTING_BOOL("load_dummy_on_core_shutdown", &settings->bools.load_dummy_on_core_shutdown, true, DEFAULT_LOAD_DUMMY_ON_CORE_SHUTDOWN, false);
#if defined(__WINRT__) || defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
SETTING_BOOL("core_info_cache_enable", &settings->bools.core_info_cache_enable, false, DEFAULT_CORE_INFO_CACHE_ENABLE, false);
#else
SETTING_BOOL("core_info_cache_enable", &settings->bools.core_info_cache_enable, true, DEFAULT_CORE_INFO_CACHE_ENABLE, false);
#endif
SETTING_BOOL("core_set_supports_no_game_enable", &settings->bools.set_supports_no_game_enable, true, true, false);
#ifndef HAVE_DYNAMIC
SETTING_BOOL("always_reload_core_on_run_content", &settings->bools.always_reload_core_on_run_content, true, DEFAULT_ALWAYS_RELOAD_CORE_ON_RUN_CONTENT, false);
#endif
SETTING_BOOL("builtin_mediaplayer_enable", &settings->bools.multimedia_builtin_mediaplayer_enable, true, DEFAULT_BUILTIN_MEDIAPLAYER_ENABLE, false);
SETTING_BOOL("builtin_imageviewer_enable", &settings->bools.multimedia_builtin_imageviewer_enable, true, DEFAULT_BUILTIN_IMAGEVIEWER_ENABLE, false);
SETTING_BOOL("bundle_assets_extract_enable", &settings->bools.bundle_assets_extract_enable, true, DEFAULT_BUNDLE_ASSETS_EXTRACT_ENABLE, false);
SETTING_BOOL("auto_screenshot_filename", &settings->bools.auto_screenshot_filename, true, DEFAULT_AUTO_SCREENSHOT_FILENAME, false);
SETTING_BOOL("video_filter_enable", &settings->bools.video_filter_enable, true, true, false);
SETTING_BOOL("apply_cheats_after_toggle", &settings->bools.apply_cheats_after_toggle, true, DEFAULT_APPLY_CHEATS_AFTER_TOGGLE, false);
SETTING_BOOL("apply_cheats_after_load", &settings->bools.apply_cheats_after_load, true, DEFAULT_APPLY_CHEATS_AFTER_LOAD, false);
SETTING_BOOL("run_ahead_enabled", &settings->bools.run_ahead_enabled, true, false, false);
SETTING_BOOL("run_ahead_secondary_instance", &settings->bools.run_ahead_secondary_instance, true, DEFAULT_RUN_AHEAD_SECONDARY_INSTANCE, false);
SETTING_BOOL("preemptive_frames_enable", &settings->bools.preemptive_frames_enable, true, false, false);
#if HAVE_MENU
SETTING_BOOL("kiosk_mode_enable", &settings->bools.kiosk_mode_enable, true, DEFAULT_KIOSK_MODE_ENABLE, false);
#endif
SETTING_BOOL("savestate_thumbnail_enable", &settings->bools.savestate_thumbnail_enable, true, DEFAULT_SAVESTATE_THUMBNAIL_ENABLE, false);
SETTING_BOOL("savestates_in_content_dir", &settings->bools.savestates_in_content_dir, true, DEFAULT_SAVESTATES_IN_CONTENT_DIR, false);
SETTING_BOOL("savefiles_in_content_dir", &settings->bools.savefiles_in_content_dir, true, DEFAULT_SAVEFILES_IN_CONTENT_DIR, false);
SETTING_BOOL("systemfiles_in_content_dir", &settings->bools.systemfiles_in_content_dir, true, DEFAULT_SYSTEMFILES_IN_CONTENT_DIR, false);
SETTING_BOOL("screenshots_in_content_dir", &settings->bools.screenshots_in_content_dir, true, DEFAULT_SCREENSHOTS_IN_CONTENT_DIR, false);
SETTING_BOOL("show_hidden_files", &settings->bools.show_hidden_files, true, DEFAULT_SHOW_HIDDEN_FILES, false);
#ifndef HAVE_LAKKA
SETTING_BOOL("gamemode_enable", &settings->bools.gamemode_enable, true, DEFAULT_GAMEMODE_ENABLE, false);
#endif
#ifdef HAVE_LAKKA_SWITCH
SETTING_BOOL("switch_oc", &settings->bools.switch_oc, true, DEFAULT_SWITCH_OC, false);
SETTING_BOOL("switch_cec", &settings->bools.switch_cec, true, DEFAULT_SWITCH_CEC, false);
SETTING_BOOL("bluetooth_ertm_disable", &settings->bools.bluetooth_ertm_disable, true, DEFAULT_BLUETOOTH_ERTM, false);
SETTING_BOOL("reboot_force_self_on_update", &settings->bools.reboot_force_self_on_update, true, DEFAULT_REBOOT_FORCE_SELF_ON_UPDATE, false);
#endif
SETTING_BOOL("audio_rate_control", &settings->bools.audio_rate_control, true, DEFAULT_RATE_CONTROL, false);
SETTING_BOOL("audio_enable_menu_ok", &settings->bools.audio_enable_menu_ok, true, DEFAULT_AUDIO_ENABLE_MENU_OK, false);
SETTING_BOOL("audio_enable_menu_cancel", &settings->bools.audio_enable_menu_cancel, true, DEFAULT_AUDIO_ENABLE_MENU_CANCEL, false);
SETTING_BOOL("audio_enable_menu_notice", &settings->bools.audio_enable_menu_notice, true, DEFAULT_AUDIO_ENABLE_MENU_NOTICE, false);
SETTING_BOOL("audio_enable_menu_bgm", &settings->bools.audio_enable_menu_bgm, true, DEFAULT_AUDIO_ENABLE_MENU_BGM, false);
SETTING_BOOL("audio_enable_menu_scroll", &settings->bools.audio_enable_menu_scroll, true, DEFAULT_AUDIO_ENABLE_MENU_SCROLL, false);
SETTING_BOOL("audio_mute_enable", audio_get_bool_ptr(AUDIO_ACTION_MUTE_ENABLE), true, false, false);
#ifdef HAVE_AUDIOMIXER
SETTING_BOOL("audio_mixer_mute_enable", audio_get_bool_ptr(AUDIO_ACTION_MIXER_MUTE_ENABLE), true, false, false);
#endif
SETTING_BOOL("video_shader_deferred_loading", &settings->bools.video_shader_deferred_loading, true, DEFAULT_SHADER_DEFERRED_LOADING, false);
SETTING_BOOL("video_shader_preset_save_reference_enable", &settings->bools.video_shader_preset_save_reference_enable, true, DEFAULT_VIDEO_SHADER_PRESET_SAVE_REFERENCE_ENABLE, false);
/* Let implementation decide if automatic, or 1:1 PAR. */
SETTING_BOOL("video_aspect_ratio_auto", &settings->bools.video_aspect_ratio_auto, true, DEFAULT_ASPECT_RATIO_AUTO, false);
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);
/* 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
#ifdef HAVE_COMPANION_WIMP
SETTING_BOOL("ui_companion_toggle", &settings->bools.ui_companion_toggle, false, DEFAULT_UI_COMPANION_TOGGLE, false);
SETTING_BOOL("desktop_menu_save_dock_positions", &settings->bools.desktop_menu_save_dock_positions, true, DEFAULT_DESKTOP_MENU_SAVE_DOCK_POSITIONS, false);
#endif
count = config_bool_rows_add(tmp, count, cap, settings);
SETTING_BOOL("video_notch_write_over_enable", &settings->bools.video_notch_write_over_enable, true, DEFAULT_NOTCH_WRITE_OVER_ENABLE, false);
#if defined(_XBOX1) || defined(HW_RVL)
SETTING_BOOL("soft_filter_enable", &settings->bools.video_soft_filter, true, DEFAULT_SOFT_FILTER, false);
#endif
#if defined(__APPLE__) && defined(HAVE_VULKAN)
SETTING_BOOL("video_use_metal_arg_buffers", &settings->bools.video_use_metal_arg_buffers, true, config_metal_arg_buffers_default(), false);
#endif
SETTING_BOOL("video_window_save_positions", &settings->bools.video_window_save_positions, true, DEFAULT_WINDOW_SAVE_POSITIONS, false);
SETTING_BOOL("menu_enable_widgets", &settings->bools.menu_enable_widgets, true, DEFAULT_MENU_ENABLE_WIDGETS, false);
#ifdef HAVE_MENU
SETTING_BOOL("menu_unified_controls", &settings->bools.menu_unified_controls, true, false, false);
SETTING_BOOL("menu_disable_info_button", &settings->bools.menu_disable_info_button, true, false, false);
SETTING_BOOL("menu_disable_search_button", &settings->bools.menu_disable_search_button, true, false, false);
SETTING_BOOL("menu_disable_left_analog", &settings->bools.menu_disable_left_analog, true, false, false);
SETTING_BOOL("menu_disable_right_analog", &settings->bools.menu_disable_right_analog, true, false, false);
SETTING_BOOL("menu_ignore_missing_assets", &settings->bools.menu_ignore_missing_assets, true, DEFAULT_MENU_IGNORE_MISSING_ASSETS, false);
/* Actually Quick Menu items, but too late to change without breaking old confs */
SETTING_BOOL("menu_show_latency", &settings->bools.menu_show_latency, true, DEFAULT_QUICK_MENU_SHOW_LATENCY, false);
SETTING_BOOL("menu_show_rewind", &settings->bools.menu_show_rewind, true, DEFAULT_QUICK_MENU_SHOW_REWIND, false);
SETTING_BOOL("menu_show_overlays", &settings->bools.menu_show_overlays, true, DEFAULT_QUICK_MENU_SHOW_OVERLAYS, false);
SETTING_BOOL("filter_by_current_core", &settings->bools.filter_by_current_core, true, DEFAULT_FILTER_BY_CURRENT_CORE, false);
#ifdef HAVE_RGUI
SETTING_BOOL("rgui_background_filler_thickness_enable", &settings->bools.menu_rgui_background_filler_thickness_enable, true, true, false);
SETTING_BOOL("rgui_border_filler_thickness_enable", &settings->bools.menu_rgui_border_filler_thickness_enable, true, true, false);
SETTING_BOOL("rgui_border_filler_enable", &settings->bools.menu_rgui_border_filler_enable, true, true, false);
#endif
#endif /* HAVE_MENU */
#ifdef HAVE_OVERLAY
SETTING_BOOL("input_overlay_enable", &settings->bools.input_overlay_enable, true, config_overlay_enable_default(), false);
SETTING_BOOL("input_overlay_enable_autopreferred", &settings->bools.input_overlay_enable_autopreferred, true, DEFAULT_OVERLAY_ENABLE_AUTOPREFERRED, false);
SETTING_BOOL("input_overlay_behind_menu", &settings->bools.input_overlay_behind_menu, true, DEFAULT_OVERLAY_BEHIND_MENU, false);
SETTING_BOOL("input_overlay_hide_in_menu", &settings->bools.input_overlay_hide_in_menu, true, DEFAULT_OVERLAY_HIDE_IN_MENU, false);
SETTING_BOOL("input_overlay_hide_when_gamepad_connected", &settings->bools.input_overlay_hide_when_gamepad_connected, true, DEFAULT_OVERLAY_HIDE_WHEN_GAMEPAD_CONNECTED, false);
SETTING_BOOL("input_overlay_show_mouse_cursor", &settings->bools.input_overlay_show_mouse_cursor, true, DEFAULT_OVERLAY_SHOW_MOUSE_CURSOR, false);
#endif
#if defined(VITA)
SETTING_BOOL("input_backtouch_enable", &settings->bools.input_backtouch_enable, false, DEFAULT_INPUT_BACKTOUCH_ENABLE, false);
SETTING_BOOL("input_backtouch_toggle", &settings->bools.input_backtouch_toggle, false, DEFAULT_INPUT_BACKTOUCH_TOGGLE, false);
#endif
#if TARGET_OS_IPHONE
SETTING_BOOL("small_keyboard_enable", &settings->bools.input_small_keyboard_enable, true, false, false);
#endif
SETTING_BOOL("keyboard_gamepad_enable", &settings->bools.input_keyboard_gamepad_enable, true, DEFAULT_INPUT_KEYBOARD_GAMEPAD_ENABLE, false);
#ifdef HAVE_MENU
SETTING_BOOL("menu_swap_ok_cancel_buttons", &settings->bools.input_menu_swap_ok_cancel_buttons, true, DEFAULT_MENU_SWAP_OK_CANCEL_BUTTONS, false);
SETTING_BOOL("menu_swap_scroll_buttons", &settings->bools.input_menu_swap_scroll_buttons, true, DEFAULT_MENU_SWAP_SCROLL_BUTTONS, false);
#endif
SETTING_BOOL("input_android_system_keyboard", &settings->bools.input_android_system_keyboard, true, DEFAULT_INPUT_ANDROID_SYSTEM_KEYBOARD, false);
SETTING_BOOL("input_sdl3_system_keyboard", &settings->bools.input_sdl3_system_keyboard, true, DEFAULT_INPUT_SDL3_SYSTEM_KEYBOARD, false);
#ifdef HAVE_COMMAND
SETTING_BOOL("stdin_cmd_enable", &settings->bools.stdin_cmd_enable, true, DEFAULT_STDIN_CMD_ENABLE, false);
#endif
#ifdef HAVE_NETWORKING
SETTING_BOOL("netplay_request_device_p1", &settings->bools.netplay_request_devices[0], true, false, false);
SETTING_BOOL("netplay_request_device_p2", &settings->bools.netplay_request_devices[1], true, false, false);
SETTING_BOOL("netplay_request_device_p3", &settings->bools.netplay_request_devices[2], true, false, false);
SETTING_BOOL("netplay_request_device_p4", &settings->bools.netplay_request_devices[3], true, false, false);
SETTING_BOOL("netplay_request_device_p5", &settings->bools.netplay_request_devices[4], true, false, false);
SETTING_BOOL("netplay_request_device_p6", &settings->bools.netplay_request_devices[5], true, false, false);
SETTING_BOOL("netplay_request_device_p7", &settings->bools.netplay_request_devices[6], true, false, false);
SETTING_BOOL("netplay_request_device_p8", &settings->bools.netplay_request_devices[7], true, false, false);
SETTING_BOOL("netplay_request_device_p9", &settings->bools.netplay_request_devices[8], true, false, false);
SETTING_BOOL("netplay_request_device_p10", &settings->bools.netplay_request_devices[9], true, false, false);
SETTING_BOOL("netplay_request_device_p11", &settings->bools.netplay_request_devices[10], true, false, false);
SETTING_BOOL("netplay_request_device_p12", &settings->bools.netplay_request_devices[11], true, false, false);
SETTING_BOOL("netplay_request_device_p13", &settings->bools.netplay_request_devices[12], true, false, false);
SETTING_BOOL("netplay_request_device_p14", &settings->bools.netplay_request_devices[13], true, false, false);
SETTING_BOOL("netplay_request_device_p15", &settings->bools.netplay_request_devices[14], true, false, false);
SETTING_BOOL("netplay_request_device_p16", &settings->bools.netplay_request_devices[15], true, false, false);
#endif
#ifdef ANDROID
SETTING_BOOL("input_stylus_enable", &settings->bools.input_stylus_enable, true, true, false);
SETTING_BOOL("input_stylus_require_contact_for_click", &settings->bools.input_stylus_require_contact_for_click, true, true, false);
SETTING_BOOL("input_stylus_hover_moves_pointer", &settings->bools.input_stylus_hover_moves_pointer, true, true, false);
#endif
#ifdef _3DS
SETTING_BOOL("new3ds_speedup_enable", &settings->bools.new3ds_speedup_enable, true, DEFAULT_NEW_3DS_SPEEDUP_ENABLE, false);
#endif
#if defined(HAVE_COCOATOUCH) && defined(TARGET_OS_TV)
SETTING_BOOL("gcdwebserver_alert", &settings->bools.gcdwebserver_alert, true, true, false);
#endif
SETTING_OVERRIDE_FOR(bools.log_to_file, RARCH_OVERRIDE_SETTING_LOG_TO_FILE);
*size = count;
return tmp;
}
static const struct config_float_row config_float_rows[] = {
/* GENERATED: single-source setting rows (float 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)
#define S_UINT(f, T, n, d, sd, df, c, mn, mx, st, ob, ok, rp, us, sub)
#define S_UINT_NS(f, T, n, d, sd, df, c, mn, mx, st, ob, ok, rp, us)
#define S_INT(f, T, n, d, sd, df, c, mn, mx, st, ob, ok, rp, us, sub)
#define S_INT_NS(f, T, n, d, sd, df, c, mn, mx, st, ob, ok, rp, us)
#define S_FLOAT(f, T, n, d, rnd, sd, df, c, mn, mx, st, ok, rp, us, sub) \
CFG_ROW(floats.f, T, d),
#define S_FLOAT_NS(f, T, n, d, rnd, sd, df, c, mn, mx, st, ok, rp, us) \
CFG_ROW(floats.f, T, d),
#define S_STRING(f, T, n, d, sd, c, ok, rp, sta, sel, lf, rt, ui, us, sub)
#define S_STRING_NS(f, T, n, d, sd, c, ok, rp, sta, sel, lf, rt, ui, us)
#define S_DIR(f, T, n, d, el, sd, c, sta, us, sub)
#define S_DIR_NS(f, T, n, d, el, sd, c, sta, us)
#define S_STRING_P(f, T, n, d, sd, c, ok, rp, sta, sel, lf, rt, ui, us, sub)
#define S_STRING_P_NS(f, T, n, d, sd, c, ok, rp, sta, sel, lf, rt, ui, us)
#define S_PATH(f, T, n, d, sd, c, vals, rp, ui, us, sub)
#define S_PATH_NS(f, T, n, d, sd, c, vals, rp, ui, us)
#define S_PATH_DS(f, T, n, df2, sd, c, vals, rp, ui, us, sub)
#define S_PATH_DS_NS(f, T, n, df2, sd, c, vals, rp, ui, us)
#define S_ACTION(T, n, us, sub)
#define S_ACTION_NS(T, n, us)
#define S_BOOL_EX(f, T, n, d, sd, df, c, ok, rp, sta, sel, lf, rt, ui, us, sub)
#define S_BOOL_EX_NS(f, T, n, d, sd, df, c, ok, rp, sta, sel, lf, rt, ui, us)
#define S_UINT_EX(f, T, n, d, sd, df, c, mn, mx, st, ob, ok, rp, sta, sel, lf, rt, ui, us, sub)
#define S_UINT_EX_NS(f, T, n, d, sd, df, c, mn, mx, st, ob, ok, rp, sta, sel, lf, rt, ui, us)
#define S_INT_EX(f, T, n, d, sd, df, c, mn, mx, st, ob, ok, rp, sta, sel, lf, rt, ui, us, sub)
#define S_INT_EX_NS(f, T, n, d, sd, df, c, mn, mx, st, ob, ok, rp, sta, sel, lf, rt, ui, us)
#define S_FLOAT_EX(f, T, n, d, rnd, sd, df, c, mn, mx, st, ok, rp, sta, sel, lf, rt, ui, us, sub) \
CFG_ROW(floats.f, T, d),
#define S_FLOAT_EX_NS(f, T, n, d, rnd, sd, df, c, mn, mx, st, ok, rp, sta, sel, lf, rt, ui, us) \
CFG_ROW(floats.f, T, d),
#define S_ACTION_EX(T, n, sd, ok, rp, c, us, sub)
#define S_ACTION_EX_NS(T, n, sd, ok, rp, c, us)
#define S_BOOL_LV(f, T, TV, n, d, sd, df, c, us, sub)
#define S_BOOL_LV_NS(f, T, TV, n, d, sd, df, c, us)
#define S_FLOAT_LV(f, T, TV, n, d, rnd, sd, df, c, us, sub) \
CFG_ROW(floats.f, T, d),
#define S_FLOAT_LV_NS(f, T, TV, n, d, rnd, sd, df, c, us) \
CFG_ROW(floats.f, T, d),
#define S_STRING_LV(f, T, TV, n, d, sd, c, ok, rp, sta, sel, lf, rt, ui, us, sub)
#define S_STRING_LV_NS(f, T, TV, n, d, sd, c, ok, rp, sta, sel, lf, rt, ui, us)
#define S_ACTION_LV(T, TV, n, sd, ok, rp, c, us, sub)
#define S_ACTION_LV_NS(T, TV, n, sd, ok, rp, c, us)
#define S_INT_AT(offs, T, n, d, sd, df, c, mn, mx, st, ob, ok, rp, us, sub)
#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)
#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"
#endif
#include "settings/settings_def_services_actions.h"
#include "settings/settings_def_video_driver_actions.h"
#include "settings/settings_def_gpu_index_metal.h"
#include "settings/settings_def_gpu_index_d3d12.h"
#include "settings/settings_def_gpu_index_d3d11.h"
#include "settings/settings_def_gpu_index_d3d10.h"
#include "settings/settings_def_gpu_index_egl_gl.h"
#include "settings/settings_def_aspect_ratio.h"
#include "settings/settings_def_viewport_size.h"
#include "settings/settings_def_quit_visibility.h"
#include "settings/settings_def_widget_scale_fullscreen.h"
#ifdef HAVE_MENU
#include "settings/settings_def_widget_scale.h"
#endif
#include "settings/settings_def_cheevos_account.h"
#include "settings/settings_def_menu_show_restart.h"
#include "settings/settings_def_quit_restart.h"
#include "settings/settings_def_menu_frame_rate.h"
#include "settings/settings_def_video_ctx_scaling.h"
#include "settings/settings_def_input_sensors_extra.h"
#ifdef HAVE_NETWORKING
#include "settings/settings_def_netplay_advanced.h"
#endif
#include "settings/settings_def_menu_main_state.h"
#include "settings/settings_def_playlist_management.h"
#ifdef HAVE_MENU
#include "settings/settings_def_menu_privacy.h"
#endif
#ifdef HAVE_MENU
#ifdef HAVE_RGUI
#include "settings/settings_def_menu_landscape.h"
#endif
#endif
#include "settings/settings_def_cloud_sync_general.h"
#ifdef HAVE_OVERLAY
#include "settings/settings_def_overlay_appearance.h"
#endif
#include "settings/settings_def_notification_views.h"
#ifdef HAVE_MENU
#ifdef HAVE_OZONE
#include "settings/settings_def_ozone_typography.h"
#endif
#endif
#include "settings/settings_def_saving.h"
#include "settings/settings_def_notification_positions.h"
#include "settings/settings_def_menu_main_lists_4.h"
#include "settings/settings_def_menu_main_lists_3.h"
#ifdef HAVE_MENU
#ifdef HAVE_MATERIALUI
#include "settings/settings_def_ozone_extras.h"
#endif
#endif
#include "settings/settings_def_menu_main_lists_2.h"
#ifdef HAVE_OVERLAY
#include "settings/settings_def_overlay_mouse.h"
#endif
#ifdef HAVE_OVERLAY
#include "settings/settings_def_overlay_lightgun.h"
#endif
#include "settings/settings_def_input_turbo_fire.h"
#ifdef _3DS
#include "settings/settings_def_ui_appearance.h"
#endif
#include "settings/settings_def_menu_entry_display.h"
#include "settings/settings_def_crt_switchres.h"
#include "settings/settings_def_video_sdl_display_server.h"
#include "settings/settings_def_audio_state.h"
#include "settings/settings_def_analog_deadzone.h"
#include "settings/settings_def_desktop_menu.h"
#include "settings/settings_def_audio_device.h"
#include "settings/settings_def_ai_service_options.h"
#include "settings/settings_def_video_output_misc.h"
#ifdef HAVE_NETWORKING
#include "settings/settings_def_netplay_visibility.h"
#endif
#ifdef HAVE_MICROPHONE
#include "settings/settings_def_microphone_general.h"
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_startup.h"
#endif
#include "settings/settings_def_accessibility.h"
#include "settings/settings_def_video_refresh_rate.h"
#ifdef HAVE_MENU
#if defined(HAVE_MATERIALUI) || defined(HAVE_XMB) || defined(HAVE_OZONE)
#include "settings/settings_def_menu_header_footer.h"
#endif
#endif
#include "settings/settings_def_logging.h"
#include "settings/settings_def_frame_throttle_general.h"
#include "settings/settings_def_refresh_autoswitch.h"
#include "settings/settings_def_audio_skew.h"
#include "settings/settings_def_wifi.h"
#ifdef HAVE_MIST
#include "settings/settings_def_steam_presence.h"
#endif
#include "settings/settings_def_playlist_sorting.h"
#ifdef HAVE_MENU
#if defined(HAVE_OZONE) || defined(HAVE_XMB)
#include "settings/settings_def_playlist_flags.h"
#endif
#endif
#include "settings/settings_def_notification_enable.h"
#ifdef HAVE_MENU
#include "settings/settings_def_rgui_particle_effect.h"
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_savestate_resume.h"
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_framebuffer_opacity.h"
#endif
#include "settings/settings_def_input_haptics.h"
#include "settings/settings_def_input_general.h"
#ifdef HAVE_MENU
#include "settings/settings_def_ozone_appearance.h"
#endif
#ifdef HAVE_MENU
#ifdef HAVE_XMB
#include "settings/settings_def_rgui_appearance.h"
#endif
#endif
#include "settings/settings_def_playlist_display.h"
#ifdef HAVE_CHEEVOS
#include "settings/settings_def_cheevos_general.h"
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_appearance.h"
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_visibility.h"
#endif
#ifdef HAVE_NETWORKING
#include "settings/settings_def_netplay_sync.h"
#endif
#ifdef HAVE_MICROPHONE
#ifdef HAVE_WASAPI
#include "settings/settings_def_mic_wasapi.h"
#endif
#endif
#ifdef HAVE_MENU
#ifdef HAVE_OZONE
#include "settings/settings_def_ozone_sidebar.h"
#endif
#endif
#include "settings/settings_def_input_bind_timeouts.h"
#include "settings/settings_def_video_hdr_toggles.h"
#include "settings/settings_def_video_stereo.h"
#include "settings/settings_def_video_headset.h"
#include "settings/settings_def_rewind.h"
#include "settings/settings_def_playlist_history.h"
#ifdef HAVE_MENU
#include "settings/settings_def_menu_scroll.h"
#endif
#ifdef HAVE_MENU
#ifdef HAVE_XMB
#include "settings/settings_def_menu_thumbnails.h"
#endif
#endif
#include "settings/settings_def_input_turbo.h"
#include "settings/settings_def_frame_delay.h"
#ifdef HAVE_WASAPI
#include "settings/settings_def_audio_wasapi.h"
#endif
#include "settings/settings_def_audio_resampler_quality.h"
#ifdef HAVE_MENU
#include "settings/settings_def_wallpaper_opacity.h"
#endif
#ifdef HAVE_OVERLAY
#include "settings/settings_def_overlay_opacity.h"
#endif
#ifdef HAVE_MENU
#if !(defined(RARCH_CONSOLE) || defined(RARCH_MOBILE))
#include "settings/settings_def_widget_scale_windowed.h"
#endif
#endif
#include "settings/settings_def_video_hdr.h"
#ifdef HAVE_WINDOW_OFFSET
#include "settings/settings_def_video_window_offset.h"
#endif
#include "settings/settings_def_vulkan_gpu_index.h"
#ifdef HAVE_SMBCLIENT
#include "settings/settings_def_smb_client_auth.h"
#endif
#include "settings/settings_def_midi_volume.h"
#ifdef HAVE_NETWORKING
#include "settings/settings_def_netplay_ports.h"
#endif
#ifdef HAVE_MENU
#ifdef HAVE_RGUI
#include "settings/settings_def_rgui_thumbnail_downscale.h"
#endif
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_thumbnail_upscale.h"
#endif
#ifdef HAVE_MENU
#ifdef HAVE_XMB
#include "settings/settings_def_xmb_color_theme.h"
#endif
#endif
#include "settings/settings_def_xmb_shader_pipeline.h"
#include "settings/settings_def_xmb_animations.h"
#ifdef HAVE_MENU
#ifdef HAVE_RGUI
#include "settings/settings_def_rgui_color_theme.h"
#endif
#endif
#ifdef HAVE_MENU
#ifdef HAVE_RGUI
#include "settings/settings_def_rgui_aspect.h"
#endif
#endif
#include "settings/settings_def_record_threads.h"
#include "settings/settings_def_stream_quality.h"
#include "settings/settings_def_record_quality.h"
#include "settings/settings_def_input_touch_scale.h"
#ifdef GEKKO
#include "settings/settings_def_input_mouse_scale.h"
#endif
#include "settings/settings_def_black_frame_insertion.h"
#include "settings/settings_def_shader_delay.h"
#include "settings/settings_def_shader_simulated_resolution.h"
#include "settings/settings_def_screen_brightness.h"
#include "settings/settings_def_video_rotation.h"
#include "settings/settings_def_video_monitor_index.h"
#include "settings/settings_def_rewind_step.h"
#ifdef ANDROID
#include "settings/settings_def_frame_throttle_slowmotion.h"
#endif
#include "settings/settings_def_frame_throttle_fastforward.h"
#if defined(DINGUX)
#if defined(RS90) || defined(MIYOO)
#include "settings/settings_def_dingux_rs90.h"
#endif
#endif
#if defined(DINGUX)
#if defined(DINGUX_BETA)
#include "settings/settings_def_dingux_refresh_rate.h"
#endif
#endif
#if defined(DINGUX)
#include "settings/settings_def_dingux_ipu.h"
#endif
#include "settings/settings_def_ai_service.h"
#include "settings/settings_def_video_window_custom_size.h"
#include "settings/settings_def_video_window_save_position.h"
#include "settings/settings_def_user_language_action.h"
#ifdef _3DS
#include "settings/settings_def_3ds_bottom_lcd.h"
#endif
#ifdef HAVE_OVERLAY
#include "settings/settings_def_overlay_auto_scale.h"
#endif
#include "settings/settings_def_notification_widgets.h"
#ifdef HAVE_SMBCLIENT
#include "settings/settings_def_smb_client.h"
#endif
#ifdef HAVE_NETWORKING
#ifdef HAVE_NETWORKGAMEPAD
#include "settings/settings_def_netplay_stateless.h"
#endif
#endif
#include "settings/settings_def_audio_format.h"
#include "settings/settings_def_menu_main_actions_12.h"
#include "settings/settings_def_menu_main_actions_11.h"
#include "settings/settings_def_menu_main_actions_10.h"
#include "settings/settings_def_audio_asio_action.h"
#ifdef HAVE_COMMAND
#include "settings/settings_def_netplay_nat.h"
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_ex_pilot.h"
#endif
#include "settings/settings_def_accounts_streaming.h"
#include "settings/settings_def_accounts_cheevos.h"
#include "settings/settings_def_power_action.h"
#include "settings/settings_def_netplay_action.h"
#include "settings/settings_def_video_actions_5.h"
#include "settings/settings_def_video_actions_3.h"
#include "settings/settings_def_input_actions.h"
#include "settings/settings_def_video_actions_2.h"
#include "settings/settings_def_video_actions_1.h"
#include "settings/settings_def_saving_actions.h"
#include "settings/settings_def_menu_main_actions_9.h"
#include "settings/settings_def_menu_main_actions_8.h"
#include "settings/settings_def_menu_main_actions_7.h"
#include "settings/settings_def_menu_main_actions_6.h"
#include "settings/settings_def_menu_main_actions_5.h"
#include "settings/settings_def_menu_main_actions_4.h"
#include "settings/settings_def_menu_main_actions_2.h"
#include "settings/settings_def_menu_main_actions_3.h"
#include "settings/settings_def_menu_main_actions_1.h"
#include "settings/settings_def_user_identity.h"
#include "settings/settings_def_netplay_passwords.h"
#include "settings/settings_def_netplay_server.h"
#include "settings/settings_def_recording_paths.h"
#include "settings/settings_def_streaming_paths.h"
#include "settings/settings_def_settings_password.h"
#include "settings/settings_def_kiosk_password.h"
#include "settings/settings_def_ozone_font_path.h"
#include "settings/settings_def_xmb_font_path.h"
#include "settings/settings_def_rgui_theme_path.h"
#include "settings/settings_def_overlay_preset_path.h"
#include "settings/settings_def_notification_font_path.h"
#include "settings/settings_def_menu_wallpaper_path.h"
#include "settings/settings_def_audio_dsp_path.h"
#include "settings/settings_def_video_filter_path.h"
#include "settings/settings_def_dir_user.h"
#include "settings/settings_def_dir_core.h"
#include "settings/settings_def_dir_cache_log.h"
#include "settings/settings_def_cloud_sync_s3.h"
#include "settings/settings_def_cloud_sync_webdav.h"
#ifdef HAVE_MICROPHONE
#include "settings/settings_def_microphone_block.h"
#endif
#include "settings/settings_def_updater_backup.h"
#include "settings/settings_def_updater_experimental.h"
#include "settings/settings_def_updater_extract.h"
#include "settings/settings_def_gamemode.h"
#include "settings/settings_def_sustained_performance.h"
#include "settings/settings_def_power_plan.h"
#ifdef HAVE_MENU
#include "settings/settings_def_quick_menu_shaders_view.h"
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_online_updater_view.h"
#endif
#if defined(HAVE_MENU) && defined(HAVE_SMBCLIENT)
#include "settings/settings_def_settings_show_smb.h"
#endif
#ifdef HAVE_MENU
#ifdef HAVE_MIST
#include "settings/settings_def_settings_show_steam.h"
#endif
#endif
#ifdef HAVE_NETWORKING
#include "settings/settings_def_network_ondemand_thumbnails.h"
#endif
#include "settings/settings_def_network_stdin_cmd.h"
#include "settings/settings_def_privacy_discord.h"
#include "settings/settings_def_privacy_location.h"
#include "settings/settings_def_privacy_camera.h"
#ifdef HAVE_MENU
#include "settings/settings_def_menu_core_updater_view.h"
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_restart_view.h"
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_thumbnail_background.h"
#endif
#ifdef HAVE_MENU
#ifdef HAVE_RGUI
#include "settings/settings_def_menu_start_screen.h"
#endif
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_content_settings_view.h"
#endif
#ifdef HAVE_THREADS
#include "settings/settings_def_menu_threaded_data.h"
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_wraparound.h"
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_horizontal_animation.h"
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_show_full_paths.h"
#endif
#ifdef HAVE_MENU
#ifdef HAVE_RGUI
#include "settings/settings_def_menu_rgui_transparency.h"
#endif
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_wallpaper.h"
#endif
#include "settings/settings_def_runahead_warnings.h"
#include "settings/settings_def_input_auto_mouse_grab.h"
#if defined(HAVE_DINPUT) || defined(HAVE_WINRAWINPUT)
#include "settings/settings_def_input_nowinkey.h"
#endif
#include "settings/settings_def_overlay_enable.h"
#ifdef HAVE_MICROPHONE
#include "settings/settings_def_microphone.h"
#endif
#include "settings/settings_def_audio_sync.h"
#include "settings/settings_def_audio_enable.h"
#include "settings/settings_def_ui_menubar.h"
#include "settings/settings_def_video_window_decorations.h"
#include "settings/settings_def_video_srgb.h"
#ifdef WIIU
#include "settings/settings_def_video_wiiu_drc.h"
#endif
#include "settings/settings_def_shader_watch.h"
#if defined(DINGUX)
#include "settings/settings_def_video_dingux_ipu.h"
#endif
#include "settings/settings_def_video_notch.h"
#ifdef HAVE_MENU
#ifdef HAVE_MIST
#include "settings/settings_def_menu_steam.h"
#endif
#endif
#ifdef ANDROID
#include "settings/settings_def_input_android_workaround.h"
#endif
#include "settings/settings_def_video_frame_time_sample.h"
#include "settings/settings_def_video_adaptive_vsync.h"
#include "settings/settings_def_video_gl_direct_spirv.h"
#include "settings/settings_def_shader_compiler.h"
#include "settings/settings_def_video_smooth.h"
#include "settings/settings_def_frame_time_counter.h"
#include "settings/settings_def_menu_filebrowser.h"
#include "settings/settings_def_video_filter_rotation.h"
#ifdef HAVE_CHEEVOS
#include "settings/settings_def_cheevos.h"
#endif
#include "settings/settings_def_video_suspend_screensaver.h"
#ifdef HAVE_CHEEVOS
#include "settings/settings_def_cheevos_visibility.h"
#endif
#include "settings/settings_def_ui_focus.h"
#include "settings/settings_def_multimedia.h"
#ifdef HAVE_MENU
#ifdef HAVE_RGUI
#include "settings/settings_def_menu_rgui_thumbnails.h"
#endif
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_power_views.h"
#endif
#include "settings/settings_def_recording_video.h"
#include "settings/settings_def_input_backtouch.h"
#ifdef HAVE_MENU
#ifdef HAVE_RGUI
#include "settings/settings_def_menu_rgui_layout.h"
#endif
#endif
#include "settings/settings_def_cheats_apply.h"
#include "settings/settings_def_shader_preset.h"
#ifdef UDEV_TOUCH_SUPPORT
#include "settings/settings_def_input_vmouse.h"
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_desktop.h"
#endif
#ifdef GEKKO
#include "settings/settings_def_video_gamecube.h"
#endif
#include "settings/settings_def_menu_sounds.h"
#ifdef HAVE_MENU
#include "settings/settings_def_menu_main_views.h"
#include "settings/settings_def_menu_quick_views.h"
#include "settings/settings_def_menu_settings_views.h"
#endif
#include "settings/settings_def_video_bias.h"
#include "settings/settings_def_video_window.h"
#undef SETTINGS_DEF_CONFIG_PASS
#undef S_BOOL
#undef S_BOOL_NS
#undef S_BOOL_H
#undef S_BOOL_NS_H
#undef S_UINT
#undef S_UINT_NS
#undef S_UINT_H
#undef S_UINT_NS_H
#undef S_INT
#undef S_INT_NS
#undef S_INT_H
#undef S_INT_NS_H
#undef S_FLOAT
#undef S_FLOAT_NS
#undef S_FLOAT_H
#undef S_FLOAT_NS_H
#undef S_STRING
#undef S_STRING_NS
#undef S_STRING_H
#undef S_STRING_NS_H
#undef S_DIR
#undef S_DIR_NS
#undef S_DIR_H
#undef S_DIR_NS_H
#undef S_STRING_P
#undef S_STRING_P_NS
#undef S_STRING_P_H
#undef S_STRING_P_NS_H
#undef S_PATH
#undef S_PATH_NS
#undef S_PATH_H
#undef S_PATH_NS_H
#undef S_PATH_DS
#undef S_PATH_DS_NS
#undef S_PATH_DS_H
#undef S_PATH_DS_NS_H
#undef S_ACTION
#undef S_ACTION_NS
#undef S_ACTION_H
#undef S_ACTION_NS_H
#undef S_BOOL_EX
#undef S_BOOL_EX_NS
#undef S_BOOL_EX_H
#undef S_BOOL_EX_NS_H
#undef S_UINT_EX
#undef S_UINT_EX_NS
#undef S_UINT_EX_H
#undef S_UINT_EX_NS_H
#undef S_INT_EX
#undef S_INT_EX_NS
#undef S_INT_EX_H
#undef S_INT_EX_NS_H
#undef S_FLOAT_EX
#undef S_FLOAT_EX_NS
#undef S_FLOAT_EX_H
#undef S_FLOAT_EX_NS_H
#undef S_ACTION_EX
#undef S_ACTION_EX_NS
#undef S_ACTION_EX_H
#undef S_ACTION_EX_NS_H
#undef S_BOOL_LV
#undef S_BOOL_LV_NS
#undef S_BOOL_LV_H
#undef S_BOOL_LV_NS_H
#undef S_FLOAT_LV
#undef S_FLOAT_LV_NS
#undef S_FLOAT_LV_H
#undef S_FLOAT_LV_NS_H
#undef S_STRING_LV
#undef S_STRING_LV_NS
#undef S_STRING_LV_H
#undef S_STRING_LV_NS_H
#undef S_ACTION_LV
#undef S_ACTION_LV_NS
#undef S_ACTION_LV_H
#undef S_ACTION_LV_NS_H
#undef S_INT_AT
#undef S_INT_AT_NS
#undef S_INT_AT_H
#undef S_INT_AT_NS_H
#undef S_UINT_AT_EX
#undef S_UINT_AT_EX_NS
#undef S_UINT_AT_EX_H
#undef S_UINT_AT_EX_NS_H
{ 0 }
};
CONFIG_ROWS_ADD(float, float)
static struct config_float_setting *populate_settings_float(
settings_t *settings, int *size)
{
unsigned count = 0;
unsigned cap = SETTINGS_FLOAT_COUNT_MAX;
struct config_float_setting *tmp = (struct config_float_setting*)calloc(SETTINGS_FLOAT_COUNT_MAX, sizeof(struct config_float_setting));
if (!tmp)
return NULL;
count = config_float_rows_add(tmp, count, cap, settings);
#ifdef HAVE_MENU
SETTING_FLOAT("menu_footer_opacity", &settings->floats.menu_footer_opacity, true, DEFAULT_MENU_FOOTER_OPACITY, false);
SETTING_FLOAT("menu_header_opacity", &settings->floats.menu_header_opacity, true, DEFAULT_MENU_HEADER_OPACITY, false);
#ifdef HAVE_OZONE
SETTING_FLOAT("ozone_thumbnail_scale_factor", &settings->floats.ozone_thumbnail_scale_factor, true, DEFAULT_OZONE_THUMBNAIL_SCALE_FACTOR, false);
#endif
#endif /* HAVE_MENU */
#ifdef HAVE_CHEEVOS
SETTING_FLOAT("cheevos_appearance_padding_h", &settings->floats.cheevos_appearance_padding_h, true, DEFAULT_CHEEVOS_APPEARANCE_PADDING_H, false);
SETTING_FLOAT("cheevos_appearance_padding_v", &settings->floats.cheevos_appearance_padding_v, true, DEFAULT_CHEEVOS_APPEARANCE_PADDING_V, false);
#endif
SETTING_FLOAT("audio_rate_control_delta", &settings->floats.audio_rate_control_delta, true, DEFAULT_RATE_CONTROL_DELTA, false);
SETTING_FLOAT("crt_video_refresh_rate", &settings->floats.crt_video_refresh_rate, true, DEFAULT_CRT_REFRESH_RATE, false);
#ifdef HAVE_OVERLAY
SETTING_FLOAT("input_osk_overlay_opacity", &settings->floats.input_osk_overlay_opacity, true, DEFAULT_INPUT_OVERLAY_OPACITY, false);
#endif
*size = count;
return tmp;
}
static const struct config_uint_row config_uint_rows[] = {
/* GENERATED: single-source setting rows (uint 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)
#define S_UINT(f, T, n, d, sd, df, c, mn, mx, st, ob, ok, rp, us, sub) \
CFG_ROW(uints.f, T, d),
#define S_UINT_NS(f, T, n, d, sd, df, c, mn, mx, st, ob, ok, rp, us) \
CFG_ROW(uints.f, T, d),
#define S_INT(f, T, n, d, sd, df, c, mn, mx, st, ob, ok, rp, us, sub)
#define S_INT_NS(f, T, n, d, sd, df, c, mn, mx, st, ob, ok, rp, us)
#define S_FLOAT(f, T, n, d, rnd, sd, df, c, mn, mx, st, ok, rp, us, sub)
#define S_FLOAT_NS(f, T, n, d, rnd, sd, df, c, mn, mx, st, ok, rp, us)
#define S_STRING(f, T, n, d, sd, c, ok, rp, sta, sel, lf, rt, ui, us, sub)
#define S_STRING_NS(f, T, n, d, sd, c, ok, rp, sta, sel, lf, rt, ui, us)
#define S_DIR(f, T, n, d, el, sd, c, sta, us, sub)
#define S_DIR_NS(f, T, n, d, el, sd, c, sta, us)
#define S_STRING_P(f, T, n, d, sd, c, ok, rp, sta, sel, lf, rt, ui, us, sub)
#define S_STRING_P_NS(f, T, n, d, sd, c, ok, rp, sta, sel, lf, rt, ui, us)
#define S_PATH(f, T, n, d, sd, c, vals, rp, ui, us, sub)
#define S_PATH_NS(f, T, n, d, sd, c, vals, rp, ui, us)
#define S_PATH_DS(f, T, n, df2, sd, c, vals, rp, ui, us, sub)
#define S_PATH_DS_NS(f, T, n, df2, sd, c, vals, rp, ui, us)
#define S_ACTION(T, n, us, sub)
#define S_ACTION_NS(T, n, us)
#define S_BOOL_EX(f, T, n, d, sd, df, c, ok, rp, sta, sel, lf, rt, ui, us, sub)
#define S_BOOL_EX_NS(f, T, n, d, sd, df, c, ok, rp, sta, sel, lf, rt, ui, us)
#define S_UINT_EX(f, T, n, d, sd, df, c, mn, mx, st, ob, ok, rp, sta, sel, lf, rt, ui, us, sub) \
CFG_ROW(uints.f, T, d),
#define S_UINT_EX_NS(f, T, n, d, sd, df, c, mn, mx, st, ob, ok, rp, sta, sel, lf, rt, ui, us) \
CFG_ROW(uints.f, T, d),
#define S_INT_EX(f, T, n, d, sd, df, c, mn, mx, st, ob, ok, rp, sta, sel, lf, rt, ui, us, sub)
#define S_INT_EX_NS(f, T, n, d, sd, df, c, mn, mx, st, ob, ok, rp, sta, sel, lf, rt, ui, us)
#define S_FLOAT_EX(f, T, n, d, rnd, sd, df, c, mn, mx, st, ok, rp, sta, sel, lf, rt, ui, us, sub)
#define S_FLOAT_EX_NS(f, T, n, d, rnd, sd, df, c, mn, mx, st, ok, rp, sta, sel, lf, rt, ui, us)
#define S_ACTION_EX(T, n, sd, ok, rp, c, us, sub)
#define S_ACTION_EX_NS(T, n, sd, ok, rp, c, us)
#define S_BOOL_LV(f, T, TV, n, d, sd, df, c, us, sub)
#define S_BOOL_LV_NS(f, T, TV, n, d, sd, df, c, us)
#define S_FLOAT_LV(f, T, TV, n, d, rnd, sd, df, c, us, sub)
#define S_FLOAT_LV_NS(f, T, TV, n, d, rnd, sd, df, c, us)
#define S_STRING_LV(f, T, TV, n, d, sd, c, ok, rp, sta, sel, lf, rt, ui, us, sub)
#define S_STRING_LV_NS(f, T, TV, n, d, sd, c, ok, rp, sta, sel, lf, rt, ui, us)
#define S_ACTION_LV(T, TV, n, sd, ok, rp, c, us, sub)
#define S_ACTION_LV_NS(T, TV, n, sd, ok, rp, c, us)
#define S_INT_AT(offs, T, n, d, sd, df, c, mn, mx, st, ob, ok, rp, us, sub)
#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)
#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"
#endif
#include "settings/settings_def_services_actions.h"
#include "settings/settings_def_video_driver_actions.h"
#include "settings/settings_def_gpu_index_metal.h"
#include "settings/settings_def_gpu_index_d3d12.h"
#include "settings/settings_def_gpu_index_d3d11.h"
#include "settings/settings_def_gpu_index_d3d10.h"
#include "settings/settings_def_gpu_index_egl_gl.h"
#include "settings/settings_def_aspect_ratio.h"
#include "settings/settings_def_viewport_size.h"
#include "settings/settings_def_quit_visibility.h"
#include "settings/settings_def_widget_scale_fullscreen.h"
#ifdef HAVE_MENU
#include "settings/settings_def_widget_scale.h"
#endif
#include "settings/settings_def_cheevos_account.h"
#include "settings/settings_def_menu_show_restart.h"
#include "settings/settings_def_quit_restart.h"
#include "settings/settings_def_menu_frame_rate.h"
#include "settings/settings_def_video_ctx_scaling.h"
#include "settings/settings_def_input_sensors_extra.h"
#ifdef HAVE_NETWORKING
#include "settings/settings_def_netplay_advanced.h"
#endif
#include "settings/settings_def_menu_main_state.h"
#include "settings/settings_def_playlist_management.h"
#ifdef HAVE_MENU
#include "settings/settings_def_menu_privacy.h"
#endif
#ifdef HAVE_MENU
#ifdef HAVE_RGUI
#include "settings/settings_def_menu_landscape.h"
#endif
#endif
#include "settings/settings_def_cloud_sync_general.h"
#ifdef HAVE_OVERLAY
#include "settings/settings_def_overlay_appearance.h"
#endif
#include "settings/settings_def_notification_views.h"
#ifdef HAVE_MENU
#ifdef HAVE_OZONE
#include "settings/settings_def_ozone_typography.h"
#endif
#endif
#include "settings/settings_def_saving.h"
#include "settings/settings_def_notification_positions.h"
#include "settings/settings_def_menu_main_lists_4.h"
#include "settings/settings_def_menu_main_lists_3.h"
#ifdef HAVE_MENU
#ifdef HAVE_MATERIALUI
#include "settings/settings_def_ozone_extras.h"
#endif
#endif
#include "settings/settings_def_menu_main_lists_2.h"
#ifdef HAVE_OVERLAY
#include "settings/settings_def_overlay_mouse.h"
#endif
#ifdef HAVE_OVERLAY
#include "settings/settings_def_overlay_lightgun.h"
#endif
#include "settings/settings_def_input_turbo_fire.h"
#ifdef _3DS
#include "settings/settings_def_ui_appearance.h"
#endif
#include "settings/settings_def_menu_entry_display.h"
#include "settings/settings_def_crt_switchres.h"
#include "settings/settings_def_video_sdl_display_server.h"
#include "settings/settings_def_audio_state.h"
#include "settings/settings_def_analog_deadzone.h"
#include "settings/settings_def_desktop_menu.h"
#include "settings/settings_def_audio_device.h"
#include "settings/settings_def_ai_service_options.h"
#include "settings/settings_def_video_output_misc.h"
#ifdef HAVE_NETWORKING
#include "settings/settings_def_netplay_visibility.h"
#endif
#ifdef HAVE_MICROPHONE
#include "settings/settings_def_microphone_general.h"
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_startup.h"
#endif
#include "settings/settings_def_accessibility.h"
#include "settings/settings_def_video_refresh_rate.h"
#ifdef HAVE_MENU
#if defined(HAVE_MATERIALUI) || defined(HAVE_XMB) || defined(HAVE_OZONE)
#include "settings/settings_def_menu_header_footer.h"
#endif
#endif
#include "settings/settings_def_logging.h"
#include "settings/settings_def_frame_throttle_general.h"
#include "settings/settings_def_refresh_autoswitch.h"
#include "settings/settings_def_audio_skew.h"
#include "settings/settings_def_wifi.h"
#ifdef HAVE_MIST
#include "settings/settings_def_steam_presence.h"
#endif
#include "settings/settings_def_playlist_sorting.h"
#ifdef HAVE_MENU
#if defined(HAVE_OZONE) || defined(HAVE_XMB)
#include "settings/settings_def_playlist_flags.h"
#endif
#endif
#include "settings/settings_def_notification_enable.h"
#ifdef HAVE_MENU
#include "settings/settings_def_rgui_particle_effect.h"
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_savestate_resume.h"
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_framebuffer_opacity.h"
#endif
#include "settings/settings_def_input_haptics.h"
#include "settings/settings_def_input_general.h"
#ifdef HAVE_MENU
#include "settings/settings_def_ozone_appearance.h"
#endif
#ifdef HAVE_MENU
#ifdef HAVE_XMB
#include "settings/settings_def_rgui_appearance.h"
#endif
#endif
#include "settings/settings_def_playlist_display.h"
#ifdef HAVE_CHEEVOS
#include "settings/settings_def_cheevos_general.h"
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_appearance.h"
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_visibility.h"
#endif
#ifdef HAVE_NETWORKING
#include "settings/settings_def_netplay_sync.h"
#endif
#ifdef HAVE_MICROPHONE
#ifdef HAVE_WASAPI
#include "settings/settings_def_mic_wasapi.h"
#endif
#endif
#ifdef HAVE_MENU
#ifdef HAVE_OZONE
#include "settings/settings_def_ozone_sidebar.h"
#endif
#endif
#include "settings/settings_def_input_bind_timeouts.h"
#include "settings/settings_def_video_hdr_toggles.h"
#include "settings/settings_def_video_stereo.h"
#include "settings/settings_def_video_headset.h"
#include "settings/settings_def_rewind.h"
#include "settings/settings_def_playlist_history.h"
#ifdef HAVE_MENU
#include "settings/settings_def_menu_scroll.h"
#endif
#ifdef HAVE_MENU
#ifdef HAVE_XMB
#include "settings/settings_def_menu_thumbnails.h"
#endif
#endif
#include "settings/settings_def_input_turbo.h"
#include "settings/settings_def_frame_delay.h"
#ifdef HAVE_WASAPI
#include "settings/settings_def_audio_wasapi.h"
#endif
#include "settings/settings_def_audio_resampler_quality.h"
#ifdef HAVE_MENU
#include "settings/settings_def_wallpaper_opacity.h"
#endif
#ifdef HAVE_OVERLAY
#include "settings/settings_def_overlay_opacity.h"
#endif
#ifdef HAVE_MENU
#if !(defined(RARCH_CONSOLE) || defined(RARCH_MOBILE))
#include "settings/settings_def_widget_scale_windowed.h"
#endif
#endif
#include "settings/settings_def_video_hdr.h"
#ifdef HAVE_WINDOW_OFFSET
#include "settings/settings_def_video_window_offset.h"
#endif
#include "settings/settings_def_vulkan_gpu_index.h"
#ifdef HAVE_SMBCLIENT
#include "settings/settings_def_smb_client_auth.h"
#endif
#include "settings/settings_def_midi_volume.h"
#ifdef HAVE_NETWORKING
#include "settings/settings_def_netplay_ports.h"
#endif
#ifdef HAVE_MENU
#ifdef HAVE_RGUI
#include "settings/settings_def_rgui_thumbnail_downscale.h"
#endif
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_thumbnail_upscale.h"
#endif
#ifdef HAVE_MENU
#ifdef HAVE_XMB
#include "settings/settings_def_xmb_color_theme.h"
#endif
#endif
#include "settings/settings_def_xmb_shader_pipeline.h"
#include "settings/settings_def_xmb_animations.h"
#ifdef HAVE_MENU
#ifdef HAVE_RGUI
#include "settings/settings_def_rgui_color_theme.h"
#endif
#endif
#ifdef HAVE_MENU
#ifdef HAVE_RGUI
#include "settings/settings_def_rgui_aspect.h"
#endif
#endif
#include "settings/settings_def_record_threads.h"
#include "settings/settings_def_stream_quality.h"
#include "settings/settings_def_record_quality.h"
#include "settings/settings_def_input_touch_scale.h"
#ifdef GEKKO
#include "settings/settings_def_input_mouse_scale.h"
#endif
#include "settings/settings_def_black_frame_insertion.h"
#include "settings/settings_def_shader_delay.h"
#include "settings/settings_def_shader_simulated_resolution.h"
#include "settings/settings_def_screen_brightness.h"
#include "settings/settings_def_video_rotation.h"
#include "settings/settings_def_video_monitor_index.h"
#include "settings/settings_def_rewind_step.h"
#ifdef ANDROID
#include "settings/settings_def_frame_throttle_slowmotion.h"
#endif
#include "settings/settings_def_frame_throttle_fastforward.h"
#if defined(DINGUX)
#if defined(RS90) || defined(MIYOO)
#include "settings/settings_def_dingux_rs90.h"
#endif
#endif
#if defined(DINGUX)
#if defined(DINGUX_BETA)
#include "settings/settings_def_dingux_refresh_rate.h"
#endif
#endif
#if defined(DINGUX)
#include "settings/settings_def_dingux_ipu.h"
#endif
#include "settings/settings_def_ai_service.h"
#include "settings/settings_def_video_window_custom_size.h"
#include "settings/settings_def_video_window_save_position.h"
#include "settings/settings_def_user_language_action.h"
#ifdef _3DS
#include "settings/settings_def_3ds_bottom_lcd.h"
#endif
#ifdef HAVE_OVERLAY
#include "settings/settings_def_overlay_auto_scale.h"
#endif
#include "settings/settings_def_notification_widgets.h"
#ifdef HAVE_SMBCLIENT
#include "settings/settings_def_smb_client.h"
#endif
#ifdef HAVE_NETWORKING
#ifdef HAVE_NETWORKGAMEPAD
#include "settings/settings_def_netplay_stateless.h"
#endif
#endif
#include "settings/settings_def_audio_format.h"
#include "settings/settings_def_menu_main_actions_12.h"
#include "settings/settings_def_menu_main_actions_11.h"
#include "settings/settings_def_menu_main_actions_10.h"
#include "settings/settings_def_audio_asio_action.h"
#ifdef HAVE_COMMAND
#include "settings/settings_def_netplay_nat.h"
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_ex_pilot.h"
#endif
#include "settings/settings_def_accounts_streaming.h"
#include "settings/settings_def_accounts_cheevos.h"
#include "settings/settings_def_power_action.h"
#include "settings/settings_def_netplay_action.h"
#include "settings/settings_def_video_actions_5.h"
#include "settings/settings_def_video_actions_3.h"
#include "settings/settings_def_input_actions.h"
#include "settings/settings_def_video_actions_2.h"
#include "settings/settings_def_video_actions_1.h"
#include "settings/settings_def_saving_actions.h"
#include "settings/settings_def_menu_main_actions_9.h"
#include "settings/settings_def_menu_main_actions_8.h"
#include "settings/settings_def_menu_main_actions_7.h"
#include "settings/settings_def_menu_main_actions_6.h"
#include "settings/settings_def_menu_main_actions_5.h"
#include "settings/settings_def_menu_main_actions_4.h"
#include "settings/settings_def_menu_main_actions_2.h"
#include "settings/settings_def_menu_main_actions_3.h"
#include "settings/settings_def_menu_main_actions_1.h"
#include "settings/settings_def_user_identity.h"
#include "settings/settings_def_netplay_passwords.h"
#include "settings/settings_def_netplay_server.h"
#include "settings/settings_def_recording_paths.h"
#include "settings/settings_def_streaming_paths.h"
#include "settings/settings_def_settings_password.h"
#include "settings/settings_def_kiosk_password.h"
#include "settings/settings_def_ozone_font_path.h"
#include "settings/settings_def_xmb_font_path.h"
#include "settings/settings_def_rgui_theme_path.h"
#include "settings/settings_def_overlay_preset_path.h"
#include "settings/settings_def_notification_font_path.h"
#include "settings/settings_def_menu_wallpaper_path.h"
#include "settings/settings_def_audio_dsp_path.h"
#include "settings/settings_def_video_filter_path.h"
#include "settings/settings_def_dir_user.h"
#include "settings/settings_def_dir_core.h"
#include "settings/settings_def_dir_cache_log.h"
#include "settings/settings_def_cloud_sync_s3.h"
#include "settings/settings_def_cloud_sync_webdav.h"
#ifdef HAVE_MICROPHONE
#include "settings/settings_def_microphone_block.h"
#endif
#include "settings/settings_def_updater_backup.h"
#include "settings/settings_def_updater_experimental.h"
#include "settings/settings_def_updater_extract.h"
#include "settings/settings_def_gamemode.h"
#include "settings/settings_def_sustained_performance.h"
#include "settings/settings_def_power_plan.h"
#ifdef HAVE_MENU
#include "settings/settings_def_quick_menu_shaders_view.h"
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_online_updater_view.h"
#endif
#if defined(HAVE_MENU) && defined(HAVE_SMBCLIENT)
#include "settings/settings_def_settings_show_smb.h"
#endif
#ifdef HAVE_MENU
#ifdef HAVE_MIST
#include "settings/settings_def_settings_show_steam.h"
#endif
#endif
#ifdef HAVE_NETWORKING
#include "settings/settings_def_network_ondemand_thumbnails.h"
#endif
#include "settings/settings_def_network_stdin_cmd.h"
#include "settings/settings_def_privacy_discord.h"
#include "settings/settings_def_privacy_location.h"
#include "settings/settings_def_privacy_camera.h"
#ifdef HAVE_MENU
#include "settings/settings_def_menu_core_updater_view.h"
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_restart_view.h"
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_thumbnail_background.h"
#endif
#ifdef HAVE_MENU
#ifdef HAVE_RGUI
#include "settings/settings_def_menu_start_screen.h"
#endif
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_content_settings_view.h"
#endif
#ifdef HAVE_THREADS
#include "settings/settings_def_menu_threaded_data.h"
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_wraparound.h"
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_horizontal_animation.h"
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_show_full_paths.h"
#endif
#ifdef HAVE_MENU
#ifdef HAVE_RGUI
#include "settings/settings_def_menu_rgui_transparency.h"
#endif
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_wallpaper.h"
#endif
#include "settings/settings_def_runahead_warnings.h"
#include "settings/settings_def_input_auto_mouse_grab.h"
#if defined(HAVE_DINPUT) || defined(HAVE_WINRAWINPUT)
#include "settings/settings_def_input_nowinkey.h"
#endif
#include "settings/settings_def_overlay_enable.h"
#ifdef HAVE_MICROPHONE
#include "settings/settings_def_microphone.h"
#endif
#include "settings/settings_def_audio_sync.h"
#include "settings/settings_def_audio_enable.h"
#include "settings/settings_def_ui_menubar.h"
#include "settings/settings_def_video_window_decorations.h"
#include "settings/settings_def_video_srgb.h"
#ifdef WIIU
#include "settings/settings_def_video_wiiu_drc.h"
#endif
#include "settings/settings_def_shader_watch.h"
#if defined(DINGUX)
#include "settings/settings_def_video_dingux_ipu.h"
#endif
#include "settings/settings_def_video_notch.h"
#ifdef HAVE_MENU
#ifdef HAVE_MIST
#include "settings/settings_def_menu_steam.h"
#endif
#endif
#ifdef ANDROID
#include "settings/settings_def_input_android_workaround.h"
#endif
#include "settings/settings_def_video_frame_time_sample.h"
#include "settings/settings_def_video_adaptive_vsync.h"
#include "settings/settings_def_video_gl_direct_spirv.h"
#include "settings/settings_def_shader_compiler.h"
#include "settings/settings_def_video_smooth.h"
#include "settings/settings_def_frame_time_counter.h"
#include "settings/settings_def_menu_filebrowser.h"
#include "settings/settings_def_video_filter_rotation.h"
#ifdef HAVE_CHEEVOS
#include "settings/settings_def_cheevos.h"
#endif
#include "settings/settings_def_video_suspend_screensaver.h"
#ifdef HAVE_CHEEVOS
#include "settings/settings_def_cheevos_visibility.h"
#endif
#include "settings/settings_def_ui_focus.h"
#include "settings/settings_def_multimedia.h"
#ifdef HAVE_MENU
#ifdef HAVE_RGUI
#include "settings/settings_def_menu_rgui_thumbnails.h"
#endif
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_power_views.h"
#endif
#include "settings/settings_def_recording_video.h"
#include "settings/settings_def_input_backtouch.h"
#ifdef HAVE_MENU
#ifdef HAVE_RGUI
#include "settings/settings_def_menu_rgui_layout.h"
#endif
#endif
#include "settings/settings_def_cheats_apply.h"
#include "settings/settings_def_shader_preset.h"
#ifdef UDEV_TOUCH_SUPPORT
#include "settings/settings_def_input_vmouse.h"
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_desktop.h"
#endif
#ifdef GEKKO
#include "settings/settings_def_video_gamecube.h"
#endif
#include "settings/settings_def_menu_sounds.h"
#ifdef HAVE_MENU
#include "settings/settings_def_menu_main_views.h"
#include "settings/settings_def_menu_quick_views.h"
#include "settings/settings_def_menu_settings_views.h"
#endif
#include "settings/settings_def_video_bias.h"
#include "settings/settings_def_video_window.h"
#undef SETTINGS_DEF_CONFIG_PASS
#undef S_BOOL
#undef S_BOOL_NS
#undef S_BOOL_H
#undef S_BOOL_NS_H
#undef S_UINT
#undef S_UINT_NS
#undef S_UINT_H
#undef S_UINT_NS_H
#undef S_INT
#undef S_INT_NS
#undef S_INT_H
#undef S_INT_NS_H
#undef S_FLOAT
#undef S_FLOAT_NS
#undef S_FLOAT_H
#undef S_FLOAT_NS_H
#undef S_STRING
#undef S_STRING_NS
#undef S_STRING_H
#undef S_STRING_NS_H
#undef S_DIR
#undef S_DIR_NS
#undef S_DIR_H
#undef S_DIR_NS_H
#undef S_STRING_P
#undef S_STRING_P_NS
#undef S_STRING_P_H
#undef S_STRING_P_NS_H
#undef S_PATH
#undef S_PATH_NS
#undef S_PATH_H
#undef S_PATH_NS_H
#undef S_PATH_DS
#undef S_PATH_DS_NS
#undef S_PATH_DS_H
#undef S_PATH_DS_NS_H
#undef S_ACTION
#undef S_ACTION_NS
#undef S_ACTION_H
#undef S_ACTION_NS_H
#undef S_BOOL_EX
#undef S_BOOL_EX_NS
#undef S_BOOL_EX_H
#undef S_BOOL_EX_NS_H
#undef S_UINT_EX
#undef S_UINT_EX_NS
#undef S_UINT_EX_H
#undef S_UINT_EX_NS_H
#undef S_INT_EX
#undef S_INT_EX_NS
#undef S_INT_EX_H
#undef S_INT_EX_NS_H
#undef S_FLOAT_EX
#undef S_FLOAT_EX_NS
#undef S_FLOAT_EX_H
#undef S_FLOAT_EX_NS_H
#undef S_ACTION_EX
#undef S_ACTION_EX_NS
#undef S_ACTION_EX_H
#undef S_ACTION_EX_NS_H
#undef S_BOOL_LV
#undef S_BOOL_LV_NS
#undef S_BOOL_LV_H
#undef S_BOOL_LV_NS_H
#undef S_FLOAT_LV
#undef S_FLOAT_LV_NS
#undef S_FLOAT_LV_H
#undef S_FLOAT_LV_NS_H
#undef S_STRING_LV
#undef S_STRING_LV_NS
#undef S_STRING_LV_H
#undef S_STRING_LV_NS_H
#undef S_ACTION_LV
#undef S_ACTION_LV_NS
#undef S_ACTION_LV_H
#undef S_ACTION_LV_NS_H
#undef S_INT_AT
#undef S_INT_AT_NS
#undef S_INT_AT_H
#undef S_INT_AT_NS_H
#undef S_UINT_AT_EX
#undef S_UINT_AT_EX_NS
#undef S_UINT_AT_EX_H
#undef S_UINT_AT_EX_NS_H
CFG_ROW(uints.audio_latency_floor, AUDIO_LATENCY_FLOOR, DEFAULT_AUDIO_LATENCY_FLOOR),
CFG_ROW(uints.core_updater_auto_backup_history_size, CORE_UPDATER_AUTO_BACKUP_HISTORY_SIZE, DEFAULT_CORE_UPDATER_AUTO_BACKUP_HISTORY_SIZE),
CFG_ROW(uints.frontend_log_level, FRONTEND_LOG_LEVEL, DEFAULT_FRONTEND_LOG_LEVEL),
CFG_ROW(uints.run_ahead_frames, RUN_AHEAD_FRAMES, DEFAULT_RUN_AHEAD_FRAMES),
#ifdef HAVE_MENU
#ifdef HAVE_XMB
CFG_ROW(uints.menu_xmb_thumbnail_scale_factor, MENU_XMB_THUMBNAIL_SCALE_FACTOR, DEFAULT_XMB_THUMBNAIL_SCALE_FACTOR),
#endif
#endif
#ifdef HAVE_NETWORKING
CFG_ROW(uints.netplay_input_latency_frames_min, NETPLAY_INPUT_LATENCY_FRAMES_MIN, 0),
CFG_ROW(uints.netplay_input_latency_frames_range, NETPLAY_INPUT_LATENCY_FRAMES_RANGE, 0),
CFG_ROW(uints.streaming_mode, STREAMING_MODE, STREAMING_MODE_TWITCH),
#endif
#if defined(HAVE_OVERLAY)
CFG_ROW(uints.input_overlay_abxy_diagonal_sensitivity, INPUT_OVERLAY_ABXY_DIAGONAL_SENSITIVITY, DEFAULT_OVERLAY_ABXY_DIAGONAL_SENSITIVITY),
CFG_ROW(uints.input_overlay_analog_recenter_zone, INPUT_OVERLAY_ANALOG_RECENTER_ZONE, DEFAULT_INPUT_OVERLAY_ANALOG_RECENTER_ZONE),
CFG_ROW(uints.input_overlay_dpad_diagonal_sensitivity, INPUT_OVERLAY_DPAD_DIAGONAL_SENSITIVITY, DEFAULT_OVERLAY_DPAD_DIAGONAL_SENSITIVITY),
CFG_ROW(uints.input_overlay_show_inputs, INPUT_OVERLAY_SHOW_INPUTS, DEFAULT_OVERLAY_SHOW_INPUTS),
CFG_ROW(uints.input_overlay_show_inputs_port, INPUT_OVERLAY_SHOW_INPUTS_PORT, DEFAULT_OVERLAY_SHOW_INPUTS_PORT),
#endif
#ifdef HAVE_COMMAND
CFG_ROW(uints.network_cmd_port, NETWORK_CMD_PORT, DEFAULT_NETWORK_CMD_PORT),
#endif
#ifdef HAVE_NETWORKGAMEPAD
CFG_ROW(uints.network_remote_base_port, NETWORK_REMOTE_PORT, DEFAULT_NETWORK_REMOTE_BASE_PORT),
#endif
#ifdef HAVE_CHEEVOS
CFG_ROW(uints.cheevos_appearance_anchor, CHEEVOS_APPEARANCE_ANCHOR, DEFAULT_CHEEVOS_APPEARANCE_ANCHOR),
#endif
{ 0 }
};
CONFIG_ROWS_ADD(uint, unsigned)
static struct config_uint_setting *populate_settings_uint(
settings_t *settings, int *size)
{
unsigned count = 0;
unsigned cap = SETTINGS_UINT_COUNT_MAX;
struct config_uint_setting *tmp = (struct config_uint_setting*)calloc(SETTINGS_UINT_COUNT_MAX, sizeof(struct config_uint_setting));
if (!tmp)
return NULL;
#ifdef HAVE_NFSCLIENT
SETTING_UINT("nfs_timeout", &settings->uints.nfs_timeout, true, DEFAULT_NFS_TIMEOUT, false);
SETTING_UINT("nfs_num_contexts", &settings->uints.nfs_num_contexts, true, DEFAULT_NFS_NUM_CONTEXTS, false);
SETTING_UINT("nfs_port", &settings->uints.nfs_port, true, DEFAULT_NFS_PORT, false);
SETTING_UINT("nfs_mount_port", &settings->uints.nfs_mount_port, true, DEFAULT_NFS_MOUNT_PORT, false);
SETTING_UINT("nfs_version", &settings->uints.nfs_version, true, DEFAULT_NFS_VERSION, false);
SETTING_UINT("nfs_readahead", &settings->uints.nfs_readahead, true, DEFAULT_NFS_READAHEAD, false);
#endif
#ifdef HAVE_MENU
SETTING_UINT("menu_thumbnails", &settings->uints.gfx_thumbnails, true, DEFAULT_GFX_THUMBNAILS_DEFAULT, false);
SETTING_UINT("menu_left_thumbnails", &settings->uints.menu_left_thumbnails, true, DEFAULT_MENU_LEFT_THUMBNAILS_DEFAULT, false);
SETTING_UINT("menu_icon_thumbnails", &settings->uints.menu_icon_thumbnails, true, DEFAULT_MENU_ICON_THUMBNAILS_DEFAULT, false);
#ifdef HAVE_XMB
SETTING_UINT("menu_xmb_animation_opening_main_menu", &settings->uints.menu_xmb_animation_opening_main_menu, true, DEFAULT_XMB_ANIMATION, false);
SETTING_UINT("menu_xmb_animation_horizontal_highlight", &settings->uints.menu_xmb_animation_horizontal_highlight, true, DEFAULT_XMB_ANIMATION, false);
SETTING_UINT("menu_xmb_animation_move_up_down", &settings->uints.menu_xmb_animation_move_up_down, true, DEFAULT_XMB_ANIMATION, false);
SETTING_UINT("menu_shader_pipeline", &settings->uints.menu_xmb_shader_pipeline, true, DEFAULT_MENU_SHADER_PIPELINE, false);
#endif
#endif /* HAVE_MENU */
SETTING_UINT("audio_out_rate", &settings->uints.audio_output_sample_rate, true, DEFAULT_OUTPUT_RATE, false);
SETTING_UINT("audio_latency", &settings->uints.audio_latency, false, 0 /* TODO */, false);
#ifdef HAVE_MICROPHONE
SETTING_UINT("microphone_latency", &settings->uints.microphone_latency, false, 0 /* TODO */, false);
SETTING_UINT("microphone_rate", &settings->uints.microphone_sample_rate, true, DEFAULT_INPUT_RATE, false);
#endif
SETTING_UINT_HALF("custom_viewport_width", &settings->video_vp_custom.dims, CFG_HALF_HI, false, 0 /* TODO */, false);
SETTING_UINT_HALF("custom_viewport_height", &settings->video_vp_custom.dims, CFG_HALF_LO, false, 0 /* TODO */, false);
SETTING_UINT_HALF("video_windowed_position_width", &settings->uints.window_position_dims, CFG_HALF_HI, true, DEFAULT_WINDOW_WIDTH, false);
SETTING_UINT_HALF("video_windowed_position_height", &settings->uints.window_position_dims, CFG_HALF_LO, true, DEFAULT_WINDOW_HEIGHT, false);
/* The auto-resize ceiling was config-bound through the S_UINT pass,
* which binds &settings->uints.<field> by name; its pair is one
* word now, so these two rows are literal like the pair above. */
SETTING_UINT_HALF("video_window_auto_width_max", &settings->uints.window_auto_dims_max, CFG_HALF_HI, true, DEFAULT_WINDOW_AUTO_WIDTH_MAX, false);
SETTING_UINT_HALF("video_window_auto_height_max", &settings->uints.window_auto_dims_max, CFG_HALF_LO, true, DEFAULT_WINDOW_AUTO_HEIGHT_MAX, false);
#if (defined(HAVE_QT) || defined(HAVE_COCOA) || (defined(_WIN32) && !defined(_XBOX) && !defined(__WINRT__)))
/* The desktop companion's saved geometry, bound through the
* S_UINT_EX pass until its two pairs became two words. The four
* keys are unchanged -- tools/companion_qt_persist_test.sh reads
* them out of the written retroarch.cfg by name. */
SETTING_UINT_HALF("desktop_menu_window_x", &settings->uints.desktop_menu_window_pos, CFG_HALF_HI, true, 0, false);
SETTING_UINT_HALF("desktop_menu_window_y", &settings->uints.desktop_menu_window_pos, CFG_HALF_LO, true, 0, false);
SETTING_UINT_HALF("desktop_menu_window_width", &settings->uints.desktop_menu_window_dims, CFG_HALF_HI, true, 0, false);
SETTING_UINT_HALF("desktop_menu_window_height", &settings->uints.desktop_menu_window_dims, CFG_HALF_LO, true, 0, false);
#endif
#ifdef GEKKO
SETTING_UINT("video_viwidth", &settings->uints.video_viwidth, true, DEFAULT_VIDEO_VI_WIDTH, false);
#endif
#if defined(GEKKO) || defined(_XBOX360)
SETTING_UINT("gamma_correction", &settings->uints.video_gamma, true, DEFAULT_GAMMA, false);
#endif
#ifdef PS2
/* An entry of the PS2 driver's mode table: its modes are told apart
* by more than their size. */
SETTING_UINT("current_resolution_id", &settings->uints.video_ps2_mode, true, 0, false);
#endif
#ifdef _XBOX1
SETTING_UINT("flicker_filter_index", &settings->uints.video_flicker_filter, true, DEFAULT_FLICKER_FILTER, false);
#endif
#if defined(HAVE_MICROPHONE) && !defined(RARCH_MOBILE)
/* Its label exists on mobile only, so its def row does too. */
SETTING_UINT("microphone_block_frames", &settings->uints.microphone_block_frames, true, 0, false);
#endif
count = config_uint_rows_add(tmp, count, cap, settings);
SETTING_UINT("video_stream_port", &settings->uints.video_stream_port, true, RARCH_STREAM_DEFAULT_PORT, false);
SETTING_UINT("video_record_scale_factor", &settings->uints.video_record_scale_factor, true, 1, false);
SETTING_UINT("video_stream_scale_factor", &settings->uints.video_stream_scale_factor, true, 1, false);
SETTING_UINT("video_hdr_mode", &settings->uints.video_hdr_mode, true, DEFAULT_VIDEO_HDR_MODE, false);
SETTING_UINT("video_swapchain_bit_depth", &settings->uints.video_swapchain_bit_depth, true, DEFAULT_VIDEO_SWAPCHAIN_BIT_DEPTH, false);
#ifdef ANDROID
SETTING_UINT("input_stylus_pressure_sensitivity", &settings->uints.input_stylus_pressure_sensitivity, true, DEFAULT_INPUT_STYLUS_PRESSURE_SENSITIVITY, false);
SETTING_UINT("input_sensor_orientation", &settings->uints.input_sensor_orientation, true, 0, false);
#else
SETTING_UINT("input_sensor_orientation", &settings->uints.input_sensor_orientation, true, 1, false);
#endif
#ifdef HAVE_LIBNX
SETTING_UINT("split_joycon_p1", &settings->uints.input_split_joycon[0], true, 0, false);
SETTING_UINT("split_joycon_p2", &settings->uints.input_split_joycon[1], true, 0, false);
SETTING_UINT("split_joycon_p3", &settings->uints.input_split_joycon[2], true, 0, false);
SETTING_UINT("split_joycon_p4", &settings->uints.input_split_joycon[3], true, 0, false);
SETTING_UINT("split_joycon_p5", &settings->uints.input_split_joycon[4], true, 0, false);
SETTING_UINT("split_joycon_p6", &settings->uints.input_split_joycon[5], true, 0, false);
SETTING_UINT("split_joycon_p7", &settings->uints.input_split_joycon[6], true, 0, false);
SETTING_UINT("split_joycon_p8", &settings->uints.input_split_joycon[7], true, 0, false);
#endif
#ifdef HAVE_NETWORKING
SETTING_UINT("netplay_ip_port", &settings->uints.netplay_port, true, RARCH_DEFAULT_PORT, false);
SETTING_OVERRIDE(RARCH_OVERRIDE_SETTING_NETPLAY_IP_PORT);
#endif
#ifdef HAVE_LANGEXTRA
SETTING_UINT("user_language", msg_hash_get_uint(MSG_HASH_USER_LANGUAGE), true, frontend_driver_get_user_language(), false);
#endif
#if !defined(__APPLE__) && !defined(ANDROID)
SETTING_UINT("bundle_assets_extract_version_current", &settings->uints.bundle_assets_extract_version_current, true, 0, false);
#endif
SETTING_UINT("bundle_assets_extract_last_version", &settings->uints.bundle_assets_extract_last_version, true, 0, false);
#ifdef HAVE_LIBNX
SETTING_UINT("libnx_overclock", &settings->uints.libnx_overclock, true, SWITCH_DEFAULT_CPU_PROFILE, false);
#endif
#ifdef _3DS
SETTING_UINT("video_3ds_display_mode", &settings->uints.video_3ds_display_mode, true, DEFAULT_VIDEO_3DS_DISPLAY_MODE, false);
#endif
#ifdef HAVE_LAKKA
SETTING_UINT("cpu_scaling_mode", &settings->uints.cpu_scaling_mode, true, 0, false);
SETTING_UINT("cpu_min_freq", &settings->uints.cpu_min_freq, true, 1, false);
SETTING_UINT("cpu_max_freq", &settings->uints.cpu_max_freq, true, ~0U, false);
#endif
#ifdef HAVE_LAKKA_SWITCH
SETTING_UINT("reboot_payload_kind", &settings->uints.reboot_payload_kind, true, 0, false);
#endif
*size = count;
return tmp;
}
static struct config_size_setting *populate_settings_size(
settings_t *settings, int *size)
{
unsigned count = 0;
unsigned cap = SETTINGS_SIZE_COUNT_MAX;
struct config_size_setting *tmp = (struct config_size_setting*)calloc(SETTINGS_SIZE_COUNT_MAX, sizeof(struct config_size_setting));
if (!tmp)
return NULL;
SETTING_SIZE("rewind_buffer_size", &settings->sizes.rewind_buffer_size, true, DEFAULT_REWIND_BUFFER_SIZE, false);
*size = count;
return tmp;
}
static const struct config_int_row config_int_rows[] = {
/* 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)
#define S_UINT(f, T, n, d, sd, df, c, mn, mx, st, ob, ok, rp, us, sub)
#define S_UINT_NS(f, T, n, d, sd, df, c, mn, mx, st, ob, ok, rp, us)
#define S_INT(f, T, n, d, sd, df, c, mn, mx, st, ob, ok, rp, us, sub) \
CFG_ROW(ints.f, T, d),
#define S_INT_NS(f, T, n, d, sd, df, c, mn, mx, st, ob, ok, rp, us) \
CFG_ROW(ints.f, T, d),
#define S_FLOAT(f, T, n, d, rnd, sd, df, c, mn, mx, st, ok, rp, us, sub)
#define S_FLOAT_NS(f, T, n, d, rnd, sd, df, c, mn, mx, st, ok, rp, us)
#define S_STRING(f, T, n, d, sd, c, ok, rp, sta, sel, lf, rt, ui, us, sub)
#define S_STRING_NS(f, T, n, d, sd, c, ok, rp, sta, sel, lf, rt, ui, us)
#define S_DIR(f, T, n, d, el, sd, c, sta, us, sub)
#define S_DIR_NS(f, T, n, d, el, sd, c, sta, us)
#define S_STRING_P(f, T, n, d, sd, c, ok, rp, sta, sel, lf, rt, ui, us, sub)
#define S_STRING_P_NS(f, T, n, d, sd, c, ok, rp, sta, sel, lf, rt, ui, us)
#define S_PATH(f, T, n, d, sd, c, vals, rp, ui, us, sub)
#define S_PATH_NS(f, T, n, d, sd, c, vals, rp, ui, us)
#define S_PATH_DS(f, T, n, df2, sd, c, vals, rp, ui, us, sub)
#define S_PATH_DS_NS(f, T, n, df2, sd, c, vals, rp, ui, us)
#define S_ACTION(T, n, us, sub)
#define S_ACTION_NS(T, n, us)
#define S_BOOL_EX(f, T, n, d, sd, df, c, ok, rp, sta, sel, lf, rt, ui, us, sub)
#define S_BOOL_EX_NS(f, T, n, d, sd, df, c, ok, rp, sta, sel, lf, rt, ui, us)
#define S_UINT_EX(f, T, n, d, sd, df, c, mn, mx, st, ob, ok, rp, sta, sel, lf, rt, ui, us, sub)
#define S_UINT_EX_NS(f, T, n, d, sd, df, c, mn, mx, st, ob, ok, rp, sta, sel, lf, rt, ui, us)
#define S_INT_EX(f, T, n, d, sd, df, c, mn, mx, st, ob, ok, rp, sta, sel, lf, rt, ui, us, sub) \
CFG_ROW(ints.f, T, d),
#define S_INT_EX_NS(f, T, n, d, sd, df, c, mn, mx, st, ob, ok, rp, sta, sel, lf, rt, ui, us) \
CFG_ROW(ints.f, T, d),
#define S_FLOAT_EX(f, T, n, d, rnd, sd, df, c, mn, mx, st, ok, rp, sta, sel, lf, rt, ui, us, sub)
#define S_FLOAT_EX_NS(f, T, n, d, rnd, sd, df, c, mn, mx, st, ok, rp, sta, sel, lf, rt, ui, us)
#define S_ACTION_EX(T, n, sd, ok, rp, c, us, sub)
#define S_ACTION_EX_NS(T, n, sd, ok, rp, c, us)
#define S_BOOL_LV(f, T, TV, n, d, sd, df, c, us, sub)
#define S_BOOL_LV_NS(f, T, TV, n, d, sd, df, c, us)
#define S_FLOAT_LV(f, T, TV, n, d, rnd, sd, df, c, us, sub)
#define S_FLOAT_LV_NS(f, T, TV, n, d, rnd, sd, df, c, us)
#define S_STRING_LV(f, T, TV, n, d, sd, c, ok, rp, sta, sel, lf, rt, ui, us, sub)
#define S_STRING_LV_NS(f, T, TV, n, d, sd, c, ok, rp, sta, sel, lf, rt, ui, us)
#define S_ACTION_LV(T, TV, n, sd, ok, rp, c, us, sub)
#define S_ACTION_LV_NS(T, TV, n, sd, ok, rp, c, us)
#define S_INT_AT(offs, T, n, d, sd, df, c, mn, mx, st, ob, ok, rp, us, sub)
#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)
#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"
#endif
#include "settings/settings_def_services_actions.h"
#include "settings/settings_def_video_driver_actions.h"
#include "settings/settings_def_gpu_index_metal.h"
#include "settings/settings_def_gpu_index_d3d12.h"
#include "settings/settings_def_gpu_index_d3d11.h"
#include "settings/settings_def_gpu_index_d3d10.h"
#include "settings/settings_def_gpu_index_egl_gl.h"
#include "settings/settings_def_aspect_ratio.h"
#include "settings/settings_def_viewport_size.h"
#include "settings/settings_def_quit_visibility.h"
#include "settings/settings_def_widget_scale_fullscreen.h"
#ifdef HAVE_MENU
#include "settings/settings_def_widget_scale.h"
#endif
#include "settings/settings_def_cheevos_account.h"
#include "settings/settings_def_menu_show_restart.h"
#include "settings/settings_def_quit_restart.h"
#include "settings/settings_def_menu_frame_rate.h"
#include "settings/settings_def_video_ctx_scaling.h"
#include "settings/settings_def_input_sensors_extra.h"
#ifdef HAVE_NETWORKING
#include "settings/settings_def_netplay_advanced.h"
#endif
#include "settings/settings_def_menu_main_state.h"
#include "settings/settings_def_playlist_management.h"
#ifdef HAVE_MENU
#include "settings/settings_def_menu_privacy.h"
#endif
#ifdef HAVE_MENU
#ifdef HAVE_RGUI
#include "settings/settings_def_menu_landscape.h"
#endif
#endif
#include "settings/settings_def_cloud_sync_general.h"
#ifdef HAVE_OVERLAY
#include "settings/settings_def_overlay_appearance.h"
#endif
#include "settings/settings_def_notification_views.h"
#ifdef HAVE_MENU
#ifdef HAVE_OZONE
#include "settings/settings_def_ozone_typography.h"
#endif
#endif
#include "settings/settings_def_saving.h"
#include "settings/settings_def_notification_positions.h"
#include "settings/settings_def_menu_main_lists_4.h"
#include "settings/settings_def_menu_main_lists_3.h"
#ifdef HAVE_MENU
#ifdef HAVE_MATERIALUI
#include "settings/settings_def_ozone_extras.h"
#endif
#endif
#include "settings/settings_def_menu_main_lists_2.h"
#ifdef HAVE_OVERLAY
#include "settings/settings_def_overlay_mouse.h"
#endif
#ifdef HAVE_OVERLAY
#include "settings/settings_def_overlay_lightgun.h"
#endif
#include "settings/settings_def_input_turbo_fire.h"
#ifdef _3DS
#include "settings/settings_def_ui_appearance.h"
#endif
#include "settings/settings_def_menu_entry_display.h"
#include "settings/settings_def_crt_switchres.h"
#include "settings/settings_def_video_sdl_display_server.h"
#include "settings/settings_def_audio_state.h"
#include "settings/settings_def_analog_deadzone.h"
#include "settings/settings_def_desktop_menu.h"
#include "settings/settings_def_audio_device.h"
#include "settings/settings_def_ai_service_options.h"
#include "settings/settings_def_video_output_misc.h"
#ifdef HAVE_NETWORKING
#include "settings/settings_def_netplay_visibility.h"
#endif
#ifdef HAVE_MICROPHONE
#include "settings/settings_def_microphone_general.h"
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_startup.h"
#endif
#include "settings/settings_def_accessibility.h"
#include "settings/settings_def_video_refresh_rate.h"
#ifdef HAVE_MENU
#if defined(HAVE_MATERIALUI) || defined(HAVE_XMB) || defined(HAVE_OZONE)
#include "settings/settings_def_menu_header_footer.h"
#endif
#endif
#include "settings/settings_def_logging.h"
#include "settings/settings_def_frame_throttle_general.h"
#include "settings/settings_def_refresh_autoswitch.h"
#include "settings/settings_def_audio_skew.h"
#include "settings/settings_def_wifi.h"
#ifdef HAVE_MIST
#include "settings/settings_def_steam_presence.h"
#endif
#include "settings/settings_def_playlist_sorting.h"
#ifdef HAVE_MENU
#if defined(HAVE_OZONE) || defined(HAVE_XMB)
#include "settings/settings_def_playlist_flags.h"
#endif
#endif
#include "settings/settings_def_notification_enable.h"
#ifdef HAVE_MENU
#include "settings/settings_def_rgui_particle_effect.h"
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_savestate_resume.h"
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_framebuffer_opacity.h"
#endif
#include "settings/settings_def_input_haptics.h"
#include "settings/settings_def_input_general.h"
#ifdef HAVE_MENU
#include "settings/settings_def_ozone_appearance.h"
#endif
#ifdef HAVE_MENU
#ifdef HAVE_XMB
#include "settings/settings_def_rgui_appearance.h"
#endif
#endif
#include "settings/settings_def_playlist_display.h"
#ifdef HAVE_CHEEVOS
#include "settings/settings_def_cheevos_general.h"
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_appearance.h"
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_visibility.h"
#endif
#ifdef HAVE_NETWORKING
#include "settings/settings_def_netplay_sync.h"
#endif
#ifdef HAVE_MICROPHONE
#ifdef HAVE_WASAPI
#include "settings/settings_def_mic_wasapi.h"
#endif
#endif
#ifdef HAVE_MENU
#ifdef HAVE_OZONE
#include "settings/settings_def_ozone_sidebar.h"
#endif
#endif
#include "settings/settings_def_input_bind_timeouts.h"
#include "settings/settings_def_video_hdr_toggles.h"
#include "settings/settings_def_video_stereo.h"
#include "settings/settings_def_video_headset.h"
#include "settings/settings_def_rewind.h"
#include "settings/settings_def_playlist_history.h"
#ifdef HAVE_MENU
#include "settings/settings_def_menu_scroll.h"
#endif
#ifdef HAVE_MENU
#ifdef HAVE_XMB
#include "settings/settings_def_menu_thumbnails.h"
#endif
#endif
#include "settings/settings_def_input_turbo.h"
#include "settings/settings_def_frame_delay.h"
#ifdef HAVE_WASAPI
#include "settings/settings_def_audio_wasapi.h"
#endif
#include "settings/settings_def_audio_resampler_quality.h"
#ifdef HAVE_MENU
#include "settings/settings_def_wallpaper_opacity.h"
#endif
#ifdef HAVE_OVERLAY
#include "settings/settings_def_overlay_opacity.h"
#endif
#ifdef HAVE_MENU
#if !(defined(RARCH_CONSOLE) || defined(RARCH_MOBILE))
#include "settings/settings_def_widget_scale_windowed.h"
#endif
#endif
#include "settings/settings_def_video_hdr.h"
#ifdef HAVE_WINDOW_OFFSET
#include "settings/settings_def_video_window_offset.h"
#endif
#include "settings/settings_def_vulkan_gpu_index.h"
#ifdef HAVE_SMBCLIENT
#include "settings/settings_def_smb_client_auth.h"
#endif
#include "settings/settings_def_midi_volume.h"
#ifdef HAVE_NETWORKING
#include "settings/settings_def_netplay_ports.h"
#endif
#ifdef HAVE_MENU
#ifdef HAVE_RGUI
#include "settings/settings_def_rgui_thumbnail_downscale.h"
#endif
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_thumbnail_upscale.h"
#endif
#ifdef HAVE_MENU
#ifdef HAVE_XMB
#include "settings/settings_def_xmb_color_theme.h"
#endif
#endif
#include "settings/settings_def_xmb_shader_pipeline.h"
#include "settings/settings_def_xmb_animations.h"
#ifdef HAVE_MENU
#ifdef HAVE_RGUI
#include "settings/settings_def_rgui_color_theme.h"
#endif
#endif
#ifdef HAVE_MENU
#ifdef HAVE_RGUI
#include "settings/settings_def_rgui_aspect.h"
#endif
#endif
#include "settings/settings_def_record_threads.h"
#include "settings/settings_def_stream_quality.h"
#include "settings/settings_def_record_quality.h"
#include "settings/settings_def_input_touch_scale.h"
#ifdef GEKKO
#include "settings/settings_def_input_mouse_scale.h"
#endif
#include "settings/settings_def_black_frame_insertion.h"
#include "settings/settings_def_shader_delay.h"
#include "settings/settings_def_shader_simulated_resolution.h"
#include "settings/settings_def_screen_brightness.h"
#include "settings/settings_def_video_rotation.h"
#include "settings/settings_def_video_monitor_index.h"
#include "settings/settings_def_rewind_step.h"
#ifdef ANDROID
#include "settings/settings_def_frame_throttle_slowmotion.h"
#endif
#include "settings/settings_def_frame_throttle_fastforward.h"
#if defined(DINGUX)
#if defined(RS90) || defined(MIYOO)
#include "settings/settings_def_dingux_rs90.h"
#endif
#endif
#if defined(DINGUX)
#if defined(DINGUX_BETA)
#include "settings/settings_def_dingux_refresh_rate.h"
#endif
#endif
#if defined(DINGUX)
#include "settings/settings_def_dingux_ipu.h"
#endif
#include "settings/settings_def_ai_service.h"
#include "settings/settings_def_video_window_custom_size.h"
#include "settings/settings_def_video_window_save_position.h"
#include "settings/settings_def_user_language_action.h"
#ifdef _3DS
#include "settings/settings_def_3ds_bottom_lcd.h"
#endif
#ifdef HAVE_OVERLAY
#include "settings/settings_def_overlay_auto_scale.h"
#endif
#include "settings/settings_def_notification_widgets.h"
#ifdef HAVE_SMBCLIENT
#include "settings/settings_def_smb_client.h"
#endif
#ifdef HAVE_NETWORKING
#ifdef HAVE_NETWORKGAMEPAD
#include "settings/settings_def_netplay_stateless.h"
#endif
#endif
#include "settings/settings_def_audio_format.h"
#include "settings/settings_def_menu_main_actions_12.h"
#include "settings/settings_def_menu_main_actions_11.h"
#include "settings/settings_def_menu_main_actions_10.h"
#include "settings/settings_def_audio_asio_action.h"
#ifdef HAVE_COMMAND
#include "settings/settings_def_netplay_nat.h"
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_ex_pilot.h"
#endif
#include "settings/settings_def_accounts_streaming.h"
#include "settings/settings_def_accounts_cheevos.h"
#include "settings/settings_def_power_action.h"
#include "settings/settings_def_netplay_action.h"
#include "settings/settings_def_video_actions_5.h"
#include "settings/settings_def_video_actions_3.h"
#include "settings/settings_def_input_actions.h"
#include "settings/settings_def_video_actions_2.h"
#include "settings/settings_def_video_actions_1.h"
#include "settings/settings_def_saving_actions.h"
#include "settings/settings_def_menu_main_actions_9.h"
#include "settings/settings_def_menu_main_actions_8.h"
#include "settings/settings_def_menu_main_actions_7.h"
#include "settings/settings_def_menu_main_actions_6.h"
#include "settings/settings_def_menu_main_actions_5.h"
#include "settings/settings_def_menu_main_actions_4.h"
#include "settings/settings_def_menu_main_actions_2.h"
#include "settings/settings_def_menu_main_actions_3.h"
#include "settings/settings_def_menu_main_actions_1.h"
#include "settings/settings_def_user_identity.h"
#include "settings/settings_def_netplay_passwords.h"
#include "settings/settings_def_netplay_server.h"
#include "settings/settings_def_recording_paths.h"
#include "settings/settings_def_streaming_paths.h"
#include "settings/settings_def_settings_password.h"
#include "settings/settings_def_kiosk_password.h"
#include "settings/settings_def_ozone_font_path.h"
#include "settings/settings_def_xmb_font_path.h"
#include "settings/settings_def_rgui_theme_path.h"
#include "settings/settings_def_overlay_preset_path.h"
#include "settings/settings_def_notification_font_path.h"
#include "settings/settings_def_menu_wallpaper_path.h"
#include "settings/settings_def_audio_dsp_path.h"
#include "settings/settings_def_video_filter_path.h"
#include "settings/settings_def_dir_user.h"
#include "settings/settings_def_dir_core.h"
#include "settings/settings_def_dir_cache_log.h"
#include "settings/settings_def_cloud_sync_s3.h"
#include "settings/settings_def_cloud_sync_webdav.h"
#ifdef HAVE_MICROPHONE
#include "settings/settings_def_microphone_block.h"
#endif
#include "settings/settings_def_updater_backup.h"
#include "settings/settings_def_updater_experimental.h"
#include "settings/settings_def_updater_extract.h"
#include "settings/settings_def_gamemode.h"
#include "settings/settings_def_sustained_performance.h"
#include "settings/settings_def_power_plan.h"
#ifdef HAVE_MENU
#include "settings/settings_def_quick_menu_shaders_view.h"
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_online_updater_view.h"
#endif
#if defined(HAVE_MENU) && defined(HAVE_SMBCLIENT)
#include "settings/settings_def_settings_show_smb.h"
#endif
#ifdef HAVE_MENU
#ifdef HAVE_MIST
#include "settings/settings_def_settings_show_steam.h"
#endif
#endif
#ifdef HAVE_NETWORKING
#include "settings/settings_def_network_ondemand_thumbnails.h"
#endif
#include "settings/settings_def_network_stdin_cmd.h"
#include "settings/settings_def_privacy_discord.h"
#include "settings/settings_def_privacy_location.h"
#include "settings/settings_def_privacy_camera.h"
#ifdef HAVE_MENU
#include "settings/settings_def_menu_core_updater_view.h"
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_restart_view.h"
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_thumbnail_background.h"
#endif
#ifdef HAVE_MENU
#ifdef HAVE_RGUI
#include "settings/settings_def_menu_start_screen.h"
#endif
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_content_settings_view.h"
#endif
#ifdef HAVE_THREADS
#include "settings/settings_def_menu_threaded_data.h"
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_wraparound.h"
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_horizontal_animation.h"
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_show_full_paths.h"
#endif
#ifdef HAVE_MENU
#ifdef HAVE_RGUI
#include "settings/settings_def_menu_rgui_transparency.h"
#endif
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_wallpaper.h"
#endif
#include "settings/settings_def_runahead_warnings.h"
#include "settings/settings_def_input_auto_mouse_grab.h"
#if defined(HAVE_DINPUT) || defined(HAVE_WINRAWINPUT)
#include "settings/settings_def_input_nowinkey.h"
#endif
#include "settings/settings_def_overlay_enable.h"
#ifdef HAVE_MICROPHONE
#include "settings/settings_def_microphone.h"
#endif
#include "settings/settings_def_audio_sync.h"
#include "settings/settings_def_audio_enable.h"
#include "settings/settings_def_ui_menubar.h"
#include "settings/settings_def_video_window_decorations.h"
#include "settings/settings_def_video_srgb.h"
#ifdef WIIU
#include "settings/settings_def_video_wiiu_drc.h"
#endif
#include "settings/settings_def_shader_watch.h"
#if defined(DINGUX)
#include "settings/settings_def_video_dingux_ipu.h"
#endif
#include "settings/settings_def_video_notch.h"
#ifdef HAVE_MENU
#ifdef HAVE_MIST
#include "settings/settings_def_menu_steam.h"
#endif
#endif
#ifdef ANDROID
#include "settings/settings_def_input_android_workaround.h"
#endif
#include "settings/settings_def_video_frame_time_sample.h"
#include "settings/settings_def_video_adaptive_vsync.h"
#include "settings/settings_def_video_gl_direct_spirv.h"
#include "settings/settings_def_shader_compiler.h"
#include "settings/settings_def_video_smooth.h"
#include "settings/settings_def_frame_time_counter.h"
#include "settings/settings_def_menu_filebrowser.h"
#include "settings/settings_def_video_filter_rotation.h"
#ifdef HAVE_CHEEVOS
#include "settings/settings_def_cheevos.h"
#endif
#include "settings/settings_def_video_suspend_screensaver.h"
#ifdef HAVE_CHEEVOS
#include "settings/settings_def_cheevos_visibility.h"
#endif
#include "settings/settings_def_ui_focus.h"
#include "settings/settings_def_multimedia.h"
#ifdef HAVE_MENU
#ifdef HAVE_RGUI
#include "settings/settings_def_menu_rgui_thumbnails.h"
#endif
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_power_views.h"
#endif
#include "settings/settings_def_recording_video.h"
#include "settings/settings_def_input_backtouch.h"
#ifdef HAVE_MENU
#ifdef HAVE_RGUI
#include "settings/settings_def_menu_rgui_layout.h"
#endif
#endif
#include "settings/settings_def_cheats_apply.h"
#include "settings/settings_def_shader_preset.h"
#ifdef UDEV_TOUCH_SUPPORT
#include "settings/settings_def_input_vmouse.h"
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_desktop.h"
#endif
#ifdef GEKKO
#include "settings/settings_def_video_gamecube.h"
#endif
#include "settings/settings_def_menu_sounds.h"
#ifdef HAVE_MENU
#include "settings/settings_def_menu_main_views.h"
#include "settings/settings_def_menu_quick_views.h"
#include "settings/settings_def_menu_settings_views.h"
#endif
#include "settings/settings_def_video_bias.h"
#include "settings/settings_def_video_window.h"
#undef SETTINGS_DEF_CONFIG_PASS
#undef S_BOOL
#undef S_BOOL_NS
#undef S_BOOL_H
#undef S_BOOL_NS_H
#undef S_UINT
#undef S_UINT_NS
#undef S_UINT_H
#undef S_UINT_NS_H
#undef S_INT
#undef S_INT_NS
#undef S_INT_H
#undef S_INT_NS_H
#undef S_FLOAT
#undef S_FLOAT_NS
#undef S_FLOAT_H
#undef S_FLOAT_NS_H
#undef S_STRING
#undef S_STRING_NS
#undef S_STRING_H
#undef S_STRING_NS_H
#undef S_DIR
#undef S_DIR_NS
#undef S_DIR_H
#undef S_DIR_NS_H
#undef S_STRING_P
#undef S_STRING_P_NS
#undef S_STRING_P_H
#undef S_STRING_P_NS_H
#undef S_PATH
#undef S_PATH_NS
#undef S_PATH_H
#undef S_PATH_NS_H
#undef S_PATH_DS
#undef S_PATH_DS_NS
#undef S_PATH_DS_H
#undef S_PATH_DS_NS_H
#undef S_ACTION
#undef S_ACTION_NS
#undef S_ACTION_H
#undef S_ACTION_NS_H
#undef S_BOOL_EX
#undef S_BOOL_EX_NS
#undef S_BOOL_EX_H
#undef S_BOOL_EX_NS_H
#undef S_UINT_EX
#undef S_UINT_EX_NS
#undef S_UINT_EX_H
#undef S_UINT_EX_NS_H
#undef S_INT_EX
#undef S_INT_EX_NS
#undef S_INT_EX_H
#undef S_INT_EX_NS_H
#undef S_FLOAT_EX
#undef S_FLOAT_EX_NS
#undef S_FLOAT_EX_H
#undef S_FLOAT_EX_NS_H
#undef S_ACTION_EX
#undef S_ACTION_EX_NS
#undef S_ACTION_EX_H
#undef S_ACTION_EX_NS_H
#undef S_BOOL_LV
#undef S_BOOL_LV_NS
#undef S_BOOL_LV_H
#undef S_BOOL_LV_NS_H
#undef S_FLOAT_LV
#undef S_FLOAT_LV_NS
#undef S_FLOAT_LV_H
#undef S_FLOAT_LV_NS_H
#undef S_STRING_LV
#undef S_STRING_LV_NS
#undef S_STRING_LV_H
#undef S_STRING_LV_NS_H
#undef S_ACTION_LV
#undef S_ACTION_LV_NS
#undef S_ACTION_LV_H
#undef S_ACTION_LV_NS_H
#undef S_INT_AT
#undef S_INT_AT_NS
#undef S_INT_AT_H
#undef S_INT_AT_NS_H
#undef S_UINT_AT_EX
#undef S_UINT_AT_EX_NS
#undef S_UINT_AT_EX_H
#undef S_UINT_AT_EX_NS_H
{ 0 }
};
CONFIG_ROWS_ADD(int, int)
static struct config_int_setting *populate_settings_int(
settings_t *settings, int *size)
{
unsigned count = 0;
unsigned cap = SETTINGS_INT_COUNT_MAX;
struct config_int_setting *tmp = (struct config_int_setting*)calloc(SETTINGS_INT_COUNT_MAX, sizeof(struct config_int_setting));
if (!tmp)
return NULL;
/* The custom viewport's origin. Signed, so it rides
* VIDEO_POS_PACK's layout in one word with its partner axis and
* the half accessors sign-extend it back out; a uint row would
* clamp a negative x to zero. */
SETTING_INT_HALF("custom_viewport_x", (int*)&settings->video_vp_custom.pos,
CFG_HALF_HI, false, 0, false);
SETTING_INT_HALF("custom_viewport_y", (int*)&settings->video_vp_custom.pos,
CFG_HALF_LO, false, 0, false);
/* The window's origin, signed for the same reason: a display
* left of or above the primary one puts an axis negative. */
SETTING_INT_HALF("video_windowed_position_x",
(int*)&settings->uints.window_position_pos,
CFG_HALF_HI, true, 0, false);
SETTING_INT_HALF("video_windowed_position_y",
(int*)&settings->uints.window_position_pos,
CFG_HALF_LO, true, 0, false);
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
count = config_int_rows_add(tmp, count, cap, settings);
/* GENERATED: single-source setting rows (string 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)
#define S_UINT(f, T, n, d, sd, df, c, mn, mx, st, ob, ok, rp, us, sub)
#define S_UINT_NS(f, T, n, d, sd, df, c, mn, mx, st, ob, ok, rp, us)
#define S_INT(f, T, n, d, sd, df, c, mn, mx, st, ob, ok, rp, us, sub)
#define S_INT_NS(f, T, n, d, sd, df, c, mn, mx, st, ob, ok, rp, us)
#define S_FLOAT(f, T, n, d, rnd, sd, df, c, mn, mx, st, ok, rp, us, sub)
#define S_FLOAT_NS(f, T, n, d, rnd, sd, df, c, mn, mx, st, ok, rp, us)
#define S_STRING(f, T, n, d, sd, c, ok, rp, sta, sel, lf, rt, ui, us, sub) \
SETTING_ARRAY(MENU_ENUM_LABEL_##T##_STR, settings->arrays.f, false, NULL, true);
#define S_STRING_NS(f, T, n, d, sd, c, ok, rp, sta, sel, lf, rt, ui, us) \
SETTING_ARRAY(MENU_ENUM_LABEL_##T##_STR, settings->arrays.f, false, NULL, true);
#define S_DIR(f, T, n, d, el, sd, c, sta, us, sub)
#define S_DIR_NS(f, T, n, d, el, sd, c, sta, us)
#define S_STRING_P(f, T, n, d, sd, c, ok, rp, sta, sel, lf, rt, ui, us, sub)
#define S_STRING_P_NS(f, T, n, d, sd, c, ok, rp, sta, sel, lf, rt, ui, us)
#define S_PATH(f, T, n, d, sd, c, vals, rp, ui, us, sub)
#define S_PATH_NS(f, T, n, d, sd, c, vals, rp, ui, us)
#define S_PATH_DS(f, T, n, df2, sd, c, vals, rp, ui, us, sub)
#define S_PATH_DS_NS(f, T, n, df2, sd, c, vals, rp, ui, us)
#define S_ACTION(T, n, us, sub)
#define S_ACTION_NS(T, n, us)
#define S_BOOL_EX(f, T, n, d, sd, df, c, ok, rp, sta, sel, lf, rt, ui, us, sub)
#define S_BOOL_EX_NS(f, T, n, d, sd, df, c, ok, rp, sta, sel, lf, rt, ui, us)
#define S_UINT_EX(f, T, n, d, sd, df, c, mn, mx, st, ob, ok, rp, sta, sel, lf, rt, ui, us, sub)
#define S_UINT_EX_NS(f, T, n, d, sd, df, c, mn, mx, st, ob, ok, rp, sta, sel, lf, rt, ui, us)
#define S_INT_EX(f, T, n, d, sd, df, c, mn, mx, st, ob, ok, rp, sta, sel, lf, rt, ui, us, sub)
#define S_INT_EX_NS(f, T, n, d, sd, df, c, mn, mx, st, ob, ok, rp, sta, sel, lf, rt, ui, us)
#define S_FLOAT_EX(f, T, n, d, rnd, sd, df, c, mn, mx, st, ok, rp, sta, sel, lf, rt, ui, us, sub)
#define S_FLOAT_EX_NS(f, T, n, d, rnd, sd, df, c, mn, mx, st, ok, rp, sta, sel, lf, rt, ui, us)
#define S_ACTION_EX(T, n, sd, ok, rp, c, us, sub)
#define S_ACTION_EX_NS(T, n, sd, ok, rp, c, us)
#define S_BOOL_LV(f, T, TV, n, d, sd, df, c, us, sub)
#define S_BOOL_LV_NS(f, T, TV, n, d, sd, df, c, us)
#define S_FLOAT_LV(f, T, TV, n, d, rnd, sd, df, c, us, sub)
#define S_FLOAT_LV_NS(f, T, TV, n, d, rnd, sd, df, c, us)
#define S_STRING_LV(f, T, TV, n, d, sd, c, ok, rp, sta, sel, lf, rt, ui, us, sub) \
SETTING_ARRAY(MENU_ENUM_LABEL_##T##_STR, settings->arrays.f, false, NULL, true);
#define S_STRING_LV_NS(f, T, TV, n, d, sd, c, ok, rp, sta, sel, lf, rt, ui, us) \
SETTING_ARRAY(MENU_ENUM_LABEL_##T##_STR, settings->arrays.f, false, NULL, true);
#define S_ACTION_LV(T, TV, n, sd, ok, rp, c, us, sub)
#define S_ACTION_LV_NS(T, TV, n, sd, ok, rp, c, us)
#define S_INT_AT(offs, T, n, d, sd, df, c, mn, mx, st, ob, ok, rp, us, sub)
#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)
#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"
#endif
#include "settings/settings_def_services_actions.h"
#include "settings/settings_def_video_driver_actions.h"
#include "settings/settings_def_gpu_index_metal.h"
#include "settings/settings_def_gpu_index_d3d12.h"
#include "settings/settings_def_gpu_index_d3d11.h"
#include "settings/settings_def_gpu_index_d3d10.h"
#include "settings/settings_def_gpu_index_egl_gl.h"
#include "settings/settings_def_aspect_ratio.h"
#include "settings/settings_def_viewport_size.h"
#include "settings/settings_def_quit_visibility.h"
#include "settings/settings_def_widget_scale_fullscreen.h"
#ifdef HAVE_MENU
#include "settings/settings_def_widget_scale.h"
#endif
#include "settings/settings_def_cheevos_account.h"
#include "settings/settings_def_menu_show_restart.h"
#include "settings/settings_def_quit_restart.h"
#include "settings/settings_def_menu_frame_rate.h"
#include "settings/settings_def_video_ctx_scaling.h"
#include "settings/settings_def_input_sensors_extra.h"
#ifdef HAVE_NETWORKING
#include "settings/settings_def_netplay_advanced.h"
#endif
#include "settings/settings_def_menu_main_state.h"
#include "settings/settings_def_playlist_management.h"
#ifdef HAVE_MENU
#include "settings/settings_def_menu_privacy.h"
#endif
#ifdef HAVE_MENU
#ifdef HAVE_RGUI
#include "settings/settings_def_menu_landscape.h"
#endif
#endif
#include "settings/settings_def_cloud_sync_general.h"
#ifdef HAVE_OVERLAY
#include "settings/settings_def_overlay_appearance.h"
#endif
#include "settings/settings_def_notification_views.h"
#ifdef HAVE_MENU
#ifdef HAVE_OZONE
#include "settings/settings_def_ozone_typography.h"
#endif
#endif
#include "settings/settings_def_saving.h"
#include "settings/settings_def_notification_positions.h"
#include "settings/settings_def_menu_main_lists_4.h"
#include "settings/settings_def_menu_main_lists_3.h"
#ifdef HAVE_MENU
#ifdef HAVE_MATERIALUI
#include "settings/settings_def_ozone_extras.h"
#endif
#endif
#include "settings/settings_def_menu_main_lists_2.h"
#ifdef HAVE_OVERLAY
#include "settings/settings_def_overlay_mouse.h"
#endif
#ifdef HAVE_OVERLAY
#include "settings/settings_def_overlay_lightgun.h"
#endif
#include "settings/settings_def_input_turbo_fire.h"
#ifdef _3DS
#include "settings/settings_def_ui_appearance.h"
#endif
#include "settings/settings_def_menu_entry_display.h"
#include "settings/settings_def_crt_switchres.h"
#include "settings/settings_def_video_sdl_display_server.h"
#include "settings/settings_def_audio_state.h"
#include "settings/settings_def_analog_deadzone.h"
#include "settings/settings_def_desktop_menu.h"
#include "settings/settings_def_audio_device.h"
#include "settings/settings_def_ai_service_options.h"
#include "settings/settings_def_video_output_misc.h"
#ifdef HAVE_NETWORKING
#include "settings/settings_def_netplay_visibility.h"
#endif
#ifdef HAVE_MICROPHONE
#include "settings/settings_def_microphone_general.h"
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_startup.h"
#endif
#include "settings/settings_def_accessibility.h"
#include "settings/settings_def_video_refresh_rate.h"
#ifdef HAVE_MENU
#if defined(HAVE_MATERIALUI) || defined(HAVE_XMB) || defined(HAVE_OZONE)
#include "settings/settings_def_menu_header_footer.h"
#endif
#endif
#include "settings/settings_def_logging.h"
#include "settings/settings_def_frame_throttle_general.h"
#include "settings/settings_def_refresh_autoswitch.h"
#include "settings/settings_def_audio_skew.h"
#include "settings/settings_def_wifi.h"
#ifdef HAVE_MIST
#include "settings/settings_def_steam_presence.h"
#endif
#include "settings/settings_def_playlist_sorting.h"
#ifdef HAVE_MENU
#if defined(HAVE_OZONE) || defined(HAVE_XMB)
#include "settings/settings_def_playlist_flags.h"
#endif
#endif
#include "settings/settings_def_notification_enable.h"
#ifdef HAVE_MENU
#include "settings/settings_def_rgui_particle_effect.h"
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_savestate_resume.h"
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_framebuffer_opacity.h"
#endif
#include "settings/settings_def_input_haptics.h"
#include "settings/settings_def_input_general.h"
#ifdef HAVE_MENU
#include "settings/settings_def_ozone_appearance.h"
#endif
#ifdef HAVE_MENU
#ifdef HAVE_XMB
#include "settings/settings_def_rgui_appearance.h"
#endif
#endif
#include "settings/settings_def_playlist_display.h"
#ifdef HAVE_CHEEVOS
#include "settings/settings_def_cheevos_general.h"
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_appearance.h"
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_visibility.h"
#endif
#ifdef HAVE_NETWORKING
#include "settings/settings_def_netplay_sync.h"
#endif
#ifdef HAVE_MICROPHONE
#ifdef HAVE_WASAPI
#include "settings/settings_def_mic_wasapi.h"
#endif
#endif
#ifdef HAVE_MENU
#ifdef HAVE_OZONE
#include "settings/settings_def_ozone_sidebar.h"
#endif
#endif
#include "settings/settings_def_input_bind_timeouts.h"
#include "settings/settings_def_video_hdr_toggles.h"
#include "settings/settings_def_video_stereo.h"
#include "settings/settings_def_video_headset.h"
#include "settings/settings_def_rewind.h"
#include "settings/settings_def_playlist_history.h"
#ifdef HAVE_MENU
#include "settings/settings_def_menu_scroll.h"
#endif
#ifdef HAVE_MENU
#ifdef HAVE_XMB
#include "settings/settings_def_menu_thumbnails.h"
#endif
#endif
#include "settings/settings_def_input_turbo.h"
#include "settings/settings_def_frame_delay.h"
#ifdef HAVE_WASAPI
#include "settings/settings_def_audio_wasapi.h"
#endif
#include "settings/settings_def_audio_resampler_quality.h"
#ifdef HAVE_MENU
#include "settings/settings_def_wallpaper_opacity.h"
#endif
#ifdef HAVE_OVERLAY
#include "settings/settings_def_overlay_opacity.h"
#endif
#ifdef HAVE_MENU
#if !(defined(RARCH_CONSOLE) || defined(RARCH_MOBILE))
#include "settings/settings_def_widget_scale_windowed.h"
#endif
#endif
#include "settings/settings_def_video_hdr.h"
#ifdef HAVE_WINDOW_OFFSET
#include "settings/settings_def_video_window_offset.h"
#endif
#include "settings/settings_def_vulkan_gpu_index.h"
#ifdef HAVE_SMBCLIENT
#include "settings/settings_def_smb_client_auth.h"
#endif
#include "settings/settings_def_midi_volume.h"
#ifdef HAVE_NETWORKING
#include "settings/settings_def_netplay_ports.h"
#endif
#ifdef HAVE_MENU
#ifdef HAVE_RGUI
#include "settings/settings_def_rgui_thumbnail_downscale.h"
#endif
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_thumbnail_upscale.h"
#endif
#ifdef HAVE_MENU
#ifdef HAVE_XMB
#include "settings/settings_def_xmb_color_theme.h"
#endif
#endif
#include "settings/settings_def_xmb_shader_pipeline.h"
#include "settings/settings_def_xmb_animations.h"
#ifdef HAVE_MENU
#ifdef HAVE_RGUI
#include "settings/settings_def_rgui_color_theme.h"
#endif
#endif
#ifdef HAVE_MENU
#ifdef HAVE_RGUI
#include "settings/settings_def_rgui_aspect.h"
#endif
#endif
#include "settings/settings_def_record_threads.h"
#include "settings/settings_def_stream_quality.h"
#include "settings/settings_def_record_quality.h"
#include "settings/settings_def_input_touch_scale.h"
#ifdef GEKKO
#include "settings/settings_def_input_mouse_scale.h"
#endif
#include "settings/settings_def_black_frame_insertion.h"
#include "settings/settings_def_shader_delay.h"
#include "settings/settings_def_shader_simulated_resolution.h"
#include "settings/settings_def_screen_brightness.h"
#include "settings/settings_def_video_rotation.h"
#include "settings/settings_def_video_monitor_index.h"
#include "settings/settings_def_rewind_step.h"
#ifdef ANDROID
#include "settings/settings_def_frame_throttle_slowmotion.h"
#endif
#include "settings/settings_def_frame_throttle_fastforward.h"
#if defined(DINGUX)
#if defined(RS90) || defined(MIYOO)
#include "settings/settings_def_dingux_rs90.h"
#endif
#endif
#if defined(DINGUX)
#if defined(DINGUX_BETA)
#include "settings/settings_def_dingux_refresh_rate.h"
#endif
#endif
#if defined(DINGUX)
#include "settings/settings_def_dingux_ipu.h"
#endif
#include "settings/settings_def_ai_service.h"
#include "settings/settings_def_video_window_custom_size.h"
#include "settings/settings_def_video_window_save_position.h"
#include "settings/settings_def_user_language_action.h"
#ifdef _3DS
#include "settings/settings_def_3ds_bottom_lcd.h"
#endif
#ifdef HAVE_OVERLAY
#include "settings/settings_def_overlay_auto_scale.h"
#endif
#include "settings/settings_def_notification_widgets.h"
#ifdef HAVE_SMBCLIENT
#include "settings/settings_def_smb_client.h"
#endif
#ifdef HAVE_NETWORKING
#ifdef HAVE_NETWORKGAMEPAD
#include "settings/settings_def_netplay_stateless.h"
#endif
#endif
#include "settings/settings_def_audio_format.h"
#include "settings/settings_def_menu_main_actions_12.h"
#include "settings/settings_def_menu_main_actions_11.h"
#include "settings/settings_def_menu_main_actions_10.h"
#include "settings/settings_def_audio_asio_action.h"
#ifdef HAVE_COMMAND
#include "settings/settings_def_netplay_nat.h"
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_ex_pilot.h"
#endif
#include "settings/settings_def_accounts_streaming.h"
#include "settings/settings_def_accounts_cheevos.h"
#include "settings/settings_def_power_action.h"
#include "settings/settings_def_netplay_action.h"
#include "settings/settings_def_video_actions_5.h"
#include "settings/settings_def_video_actions_3.h"
#include "settings/settings_def_input_actions.h"
#include "settings/settings_def_video_actions_2.h"
#include "settings/settings_def_video_actions_1.h"
#include "settings/settings_def_saving_actions.h"
#include "settings/settings_def_menu_main_actions_9.h"
#include "settings/settings_def_menu_main_actions_8.h"
#include "settings/settings_def_menu_main_actions_7.h"
#include "settings/settings_def_menu_main_actions_6.h"
#include "settings/settings_def_menu_main_actions_5.h"
#include "settings/settings_def_menu_main_actions_4.h"
#include "settings/settings_def_menu_main_actions_2.h"
#include "settings/settings_def_menu_main_actions_3.h"
#include "settings/settings_def_menu_main_actions_1.h"
#include "settings/settings_def_user_identity.h"
#include "settings/settings_def_netplay_passwords.h"
#include "settings/settings_def_netplay_server.h"
#include "settings/settings_def_recording_paths.h"
#include "settings/settings_def_streaming_paths.h"
#include "settings/settings_def_settings_password.h"
#include "settings/settings_def_kiosk_password.h"
#include "settings/settings_def_ozone_font_path.h"
#include "settings/settings_def_xmb_font_path.h"
#include "settings/settings_def_rgui_theme_path.h"
#include "settings/settings_def_overlay_preset_path.h"
#include "settings/settings_def_notification_font_path.h"
#include "settings/settings_def_menu_wallpaper_path.h"
#include "settings/settings_def_audio_dsp_path.h"
#include "settings/settings_def_video_filter_path.h"
#include "settings/settings_def_dir_user.h"
#include "settings/settings_def_dir_core.h"
#include "settings/settings_def_dir_cache_log.h"
#include "settings/settings_def_cloud_sync_s3.h"
#include "settings/settings_def_cloud_sync_webdav.h"
#ifdef HAVE_MICROPHONE
#include "settings/settings_def_microphone_block.h"
#endif
#include "settings/settings_def_updater_backup.h"
#include "settings/settings_def_updater_experimental.h"
#include "settings/settings_def_updater_extract.h"
#include "settings/settings_def_gamemode.h"
#include "settings/settings_def_sustained_performance.h"
#include "settings/settings_def_power_plan.h"
#ifdef HAVE_MENU
#include "settings/settings_def_quick_menu_shaders_view.h"
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_online_updater_view.h"
#endif
#if defined(HAVE_MENU) && defined(HAVE_SMBCLIENT)
#include "settings/settings_def_settings_show_smb.h"
#endif
#ifdef HAVE_MENU
#ifdef HAVE_MIST
#include "settings/settings_def_settings_show_steam.h"
#endif
#endif
#ifdef HAVE_NETWORKING
#include "settings/settings_def_network_ondemand_thumbnails.h"
#endif
#include "settings/settings_def_network_stdin_cmd.h"
#include "settings/settings_def_privacy_discord.h"
#include "settings/settings_def_privacy_location.h"
#include "settings/settings_def_privacy_camera.h"
#ifdef HAVE_MENU
#include "settings/settings_def_menu_core_updater_view.h"
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_restart_view.h"
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_thumbnail_background.h"
#endif
#ifdef HAVE_MENU
#ifdef HAVE_RGUI
#include "settings/settings_def_menu_start_screen.h"
#endif
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_content_settings_view.h"
#endif
#ifdef HAVE_THREADS
#include "settings/settings_def_menu_threaded_data.h"
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_wraparound.h"
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_horizontal_animation.h"
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_show_full_paths.h"
#endif
#ifdef HAVE_MENU
#ifdef HAVE_RGUI
#include "settings/settings_def_menu_rgui_transparency.h"
#endif
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_wallpaper.h"
#endif
#include "settings/settings_def_runahead_warnings.h"
#include "settings/settings_def_input_auto_mouse_grab.h"
#if defined(HAVE_DINPUT) || defined(HAVE_WINRAWINPUT)
#include "settings/settings_def_input_nowinkey.h"
#endif
#include "settings/settings_def_overlay_enable.h"
#ifdef HAVE_MICROPHONE
#include "settings/settings_def_microphone.h"
#endif
#include "settings/settings_def_audio_sync.h"
#include "settings/settings_def_audio_enable.h"
#include "settings/settings_def_ui_menubar.h"
#include "settings/settings_def_video_window_decorations.h"
#include "settings/settings_def_video_srgb.h"
#ifdef WIIU
#include "settings/settings_def_video_wiiu_drc.h"
#endif
#include "settings/settings_def_shader_watch.h"
#if defined(DINGUX)
#include "settings/settings_def_video_dingux_ipu.h"
#endif
#include "settings/settings_def_video_notch.h"
#ifdef HAVE_MENU
#ifdef HAVE_MIST
#include "settings/settings_def_menu_steam.h"
#endif
#endif
#ifdef ANDROID
#include "settings/settings_def_input_android_workaround.h"
#endif
#include "settings/settings_def_video_frame_time_sample.h"
#include "settings/settings_def_video_adaptive_vsync.h"
#include "settings/settings_def_video_gl_direct_spirv.h"
#include "settings/settings_def_shader_compiler.h"
#include "settings/settings_def_video_smooth.h"
#include "settings/settings_def_frame_time_counter.h"
#include "settings/settings_def_menu_filebrowser.h"
#include "settings/settings_def_video_filter_rotation.h"
#ifdef HAVE_CHEEVOS
#include "settings/settings_def_cheevos.h"
#endif
#include "settings/settings_def_video_suspend_screensaver.h"
#ifdef HAVE_CHEEVOS
#include "settings/settings_def_cheevos_visibility.h"
#endif
#include "settings/settings_def_ui_focus.h"
#include "settings/settings_def_multimedia.h"
#ifdef HAVE_MENU
#ifdef HAVE_RGUI
#include "settings/settings_def_menu_rgui_thumbnails.h"
#endif
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_power_views.h"
#endif
#include "settings/settings_def_recording_video.h"
#include "settings/settings_def_input_backtouch.h"
#ifdef HAVE_MENU
#ifdef HAVE_RGUI
#include "settings/settings_def_menu_rgui_layout.h"
#endif
#endif
#include "settings/settings_def_cheats_apply.h"
#include "settings/settings_def_shader_preset.h"
#ifdef UDEV_TOUCH_SUPPORT
#include "settings/settings_def_input_vmouse.h"
#endif
#ifdef HAVE_MENU
#include "settings/settings_def_menu_desktop.h"
#endif
#ifdef GEKKO
#include "settings/settings_def_video_gamecube.h"
#endif
#include "settings/settings_def_menu_sounds.h"
#ifdef HAVE_MENU
#include "settings/settings_def_menu_main_views.h"
#include "settings/settings_def_menu_quick_views.h"
#include "settings/settings_def_menu_settings_views.h"
#endif
#include "settings/settings_def_video_bias.h"
#include "settings/settings_def_video_window.h"
#undef SETTINGS_DEF_CONFIG_PASS
#undef S_BOOL
#undef S_BOOL_NS
#undef S_BOOL_H
#undef S_BOOL_NS_H
#undef S_UINT
#undef S_UINT_NS
#undef S_UINT_H
#undef S_UINT_NS_H
#undef S_INT
#undef S_INT_NS
#undef S_INT_H
#undef S_INT_NS_H
#undef S_FLOAT
#undef S_FLOAT_NS
#undef S_FLOAT_H
#undef S_FLOAT_NS_H
#undef S_STRING
#undef S_STRING_NS
#undef S_STRING_H
#undef S_STRING_NS_H
#undef S_DIR
#undef S_DIR_NS
#undef S_DIR_H
#undef S_DIR_NS_H
#undef S_STRING_P
#undef S_STRING_P_NS
#undef S_STRING_P_H
#undef S_STRING_P_NS_H
#undef S_PATH
#undef S_PATH_NS
#undef S_PATH_H
#undef S_PATH_NS_H
#undef S_PATH_DS
#undef S_PATH_DS_NS
#undef S_PATH_DS_H
#undef S_PATH_DS_NS_H
#undef S_ACTION
#undef S_ACTION_NS
#undef S_ACTION_H
#undef S_ACTION_NS_H
#undef S_BOOL_EX
#undef S_BOOL_EX_NS
#undef S_BOOL_EX_H
#undef S_BOOL_EX_NS_H
#undef S_UINT_EX
#undef S_UINT_EX_NS
#undef S_UINT_EX_H
#undef S_UINT_EX_NS_H
#undef S_INT_EX
#undef S_INT_EX_NS
#undef S_INT_EX_H
#undef S_INT_EX_NS_H
#undef S_FLOAT_EX
#undef S_FLOAT_EX_NS
#undef S_FLOAT_EX_H
#undef S_FLOAT_EX_NS_H
#undef S_ACTION_EX
#undef S_ACTION_EX_NS
#undef S_ACTION_EX_H
#undef S_ACTION_EX_NS_H
#undef S_BOOL_LV
#undef S_BOOL_LV_NS
#undef S_BOOL_LV_H
#undef S_BOOL_LV_NS_H
#undef S_FLOAT_LV
#undef S_FLOAT_LV_NS
#undef S_FLOAT_LV_H
#undef S_FLOAT_LV_NS_H
#undef S_STRING_LV
#undef S_STRING_LV_NS
#undef S_STRING_LV_H
#undef S_STRING_LV_NS_H
#undef S_ACTION_LV
#undef S_ACTION_LV_NS
#undef S_ACTION_LV_H
#undef S_ACTION_LV_NS_H
#undef S_INT_AT
#undef S_INT_AT_NS
#undef S_INT_AT_H
#undef S_INT_AT_NS_H
#undef S_UINT_AT_EX
#undef S_UINT_AT_EX_NS
#undef S_UINT_AT_EX_H
#undef S_UINT_AT_EX_NS_H
#ifdef HAVE_D3D10
SETTING_INT("d3d10_gpu_index", &settings->ints.d3d10_gpu_index, true, DEFAULT_D3D10_GPU_INDEX, false);
#endif
#ifdef HAVE_D3D11
SETTING_INT("d3d11_gpu_index", &settings->ints.d3d11_gpu_index, true, DEFAULT_D3D11_GPU_INDEX, false);
#endif
#ifdef HAVE_D3D12
SETTING_INT("d3d12_gpu_index", &settings->ints.d3d12_gpu_index, true, DEFAULT_D3D12_GPU_INDEX, false);
#endif
#ifdef HAVE_VULKAN
SETTING_INT("vulkan_gpu_index", &settings->ints.vulkan_gpu_index, true, DEFAULT_VULKAN_GPU_INDEX, false);
#endif
#ifdef HAVE_EGL
SETTING_INT("gl_gpu_index", &settings->ints.gl_gpu_index, true, DEFAULT_GL_GPU_INDEX, false);
#endif
#ifdef HAVE_METAL
SETTING_INT("metal_gpu_index", &settings->ints.metal_gpu_index, true, DEFAULT_METAL_GPU_INDEX, false);
#endif
#ifdef HAVE_NETWORKING
SETTING_OVERRIDE_FOR(ints.netplay_check_frames,
RARCH_OVERRIDE_SETTING_NETPLAY_CHECK_FRAMES);
#endif
*size = count;
return tmp;
}
/* Moves built-in playlists from legacy location to 'playlists/builtin' */
#define CONFIG_PLAYLIST_MIGRATION(playlist_path, playlist_tag) \
{ \
char new_file[PATH_MAX_LENGTH]; \
fill_pathname_resolve_relative( \
playlist_path, \
path_config, \
playlist_tag, \
sizeof(playlist_path)); \
fill_pathname_join_special( \
new_file, \
new_path, \
playlist_tag, \
sizeof(tmp_str)); \
if (path_is_valid(playlist_path) && !path_is_valid(new_file)) \
{ \
if (!filestream_copy(playlist_path, new_file)) \
RARCH_LOG("[Config] Copied file \"%s\" to \"%s\".\n", playlist_path, new_file); \
if (path_is_valid(new_file) && !filestream_cmp(playlist_path, new_file)) \
{ \
if (!filestream_delete(playlist_path)) \
RARCH_LOG("[Config] Deleted file \"%s\".\n", playlist_path); \
} \
else \
new_file[0] = '\0'; \
} \
if (*new_file) \
strlcpy(playlist_path, new_file, sizeof(playlist_path)); \
} \
/**
* config_set_defaults:
*
* Set 'default' configuration values.
**/
void config_set_defaults(settings_t *target)
{
size_t i;
#ifdef HAVE_MENU
static bool first_initialized = true;
#endif
settings_t *settings = target;
recording_state_t *recording_st = recording_state_get_ptr();
int bool_settings_size = SETTINGS_BOOL_COUNT_MAX;
int float_settings_size = SETTINGS_FLOAT_COUNT_MAX;
int int_settings_size = SETTINGS_INT_COUNT_MAX;
int uint_settings_size = SETTINGS_UINT_COUNT_MAX;
int size_settings_size = SETTINGS_SIZE_COUNT_MAX;
const char *def_video = config_get_default_video();
const char *def_audio = config_get_default_audio();
#ifdef HAVE_MICROPHONE
const char *def_microphone = config_get_default_microphone();
#endif
const char *def_audio_resampler = config_get_default_audio_resampler();
const char *def_input = config_get_default_input();
const char *def_joypad = config_get_default_joypad();
#ifdef HAVE_MENU
const char *def_menu = config_get_default_menu();
#endif
const char *def_camera = config_get_default_camera();
const char *def_ui_companion = config_get_default_ui_companion();
const char *def_bluetooth = config_get_default_bluetooth();
const char *def_wifi = config_get_default_wifi();
const char *def_led = config_get_default_led();
const char *def_cloudsync = config_get_default_cloudsync();
const char *def_location = config_get_default_location();
const char *def_record = config_get_default_record();
const char *def_midi = config_get_default_midi();
#ifdef HAVE_TRANSLATE
const char *def_ai_service_backend = config_get_default_ai_service_backend();
#endif
const char *def_mitm = DEFAULT_NETPLAY_MITM_SERVER;
video_viewport_settings_t *custom_vp = &settings->video_vp_custom;
struct config_float_setting *float_settings = populate_settings_float (settings, &float_settings_size);
struct config_bool_setting *bool_settings = populate_settings_bool (settings, &bool_settings_size);
struct config_int_setting *int_settings = populate_settings_int (settings, &int_settings_size);
struct config_uint_setting *uint_settings = populate_settings_uint (settings, &uint_settings_size);
struct config_size_setting *size_settings = populate_settings_size (settings, &size_settings_size);
if (bool_settings && (bool_settings_size > 0))
{
for (i = 0; i < (unsigned)bool_settings_size; i++)
{
if (bool_settings[i].flags & CFG_BOOL_FLG_DEF_ENABLE)
*bool_settings[i].ptr = bool_settings[i].def;
}
free(bool_settings);
}
if (int_settings && (int_settings_size > 0))
{
for (i = 0; i < (unsigned)int_settings_size; i++)
{
if (int_settings[i].flags & CFG_BOOL_FLG_DEF_ENABLE)
cfg_int_set(&int_settings[i], int_settings[i].def);
}
free(int_settings);
}
if (uint_settings && (uint_settings_size > 0))
{
for (i = 0; i < (unsigned)uint_settings_size; i++)
{
if (uint_settings[i].flags & CFG_BOOL_FLG_DEF_ENABLE)
cfg_uint_set(&uint_settings[i], uint_settings[i].def);
}
free(uint_settings);
}
if (size_settings && (size_settings_size > 0))
{
for (i = 0; i < (unsigned)size_settings_size; i++)
{
if (size_settings[i].flags & CFG_BOOL_FLG_DEF_ENABLE)
*size_settings[i].ptr = size_settings[i].def;
}
free(size_settings);
}
if (float_settings && (float_settings_size > 0))
{
for (i = 0; i < (unsigned)float_settings_size; i++)
{
if (float_settings[i].flags & CFG_BOOL_FLG_DEF_ENABLE)
*float_settings[i].ptr = float_settings[i].def;
}
free(float_settings);
}
if (def_camera)
configuration_set_string(settings,
settings->arrays.camera_driver,
def_camera);
if (def_ui_companion)
configuration_set_string(settings,
settings->arrays.ui_companion_driver,
def_ui_companion);
if (def_bluetooth)
configuration_set_string(settings,
settings->arrays.bluetooth_driver,
def_bluetooth);
if (def_wifi)
configuration_set_string(settings,
settings->arrays.wifi_driver,
def_wifi);
if (def_led)
configuration_set_string(settings,
settings->arrays.led_driver,
def_led);
if (def_cloudsync)
configuration_set_string(settings,
settings->arrays.cloud_sync_driver,
def_cloudsync);
#ifdef HAVE_TRANSLATE
if (def_ai_service_backend)
configuration_set_string(settings,
settings->arrays.ai_service_backend,
def_ai_service_backend);
#endif
if (def_location)
configuration_set_string(settings,
settings->arrays.location_driver,
def_location);
if (def_video)
configuration_set_string(settings,
settings->arrays.video_driver,
def_video);
if (def_audio)
configuration_set_string(settings,
settings->arrays.audio_driver,
def_audio);
#ifdef HAVE_MICROPHONE
if (def_microphone)
configuration_set_string(settings,
settings->arrays.microphone_driver,
def_microphone);
if (def_audio_resampler) /* not a typo, microphone's default sampler is the same as audio's */
configuration_set_string(settings,
settings->arrays.microphone_resampler,
def_audio_resampler);
#endif
if (def_audio_resampler)
configuration_set_string(settings,
settings->arrays.audio_resampler,
def_audio_resampler);
if (def_input)
configuration_set_string(settings,
settings->arrays.input_driver,
def_input);
if (def_joypad)
configuration_set_string(settings,
settings->arrays.input_joypad_driver,
def_joypad);
if (def_record)
configuration_set_string(settings,
settings->arrays.record_driver,
def_record);
if (def_midi)
configuration_set_string(settings,
settings->arrays.midi_driver,
def_midi);
if (def_mitm)
configuration_set_string(settings,
settings->arrays.netplay_mitm_server,
def_mitm);
/* Empty: bind on every interface, as before the setting existed. */
*settings->arrays.network_cmd_bind_address = '\0';
strlcpy(settings->arrays.mcp_server_bind_address, "127.0.0.1",
sizeof(settings->arrays.mcp_server_bind_address));
*settings->arrays.mcp_server_token = '\0';
#ifdef HAVE_MENU
if (def_menu)
configuration_set_string(settings,
settings->arrays.menu_driver,
def_menu);
#ifdef HAVE_XMB
*settings->paths.path_menu_xmb_font = '\0';
#endif
#ifdef HAVE_OZONE
*settings->paths.path_menu_ozone_font = '\0';
configuration_set_string(settings,
settings->arrays.menu_ozone_color_theme,
DEFAULT_OZONE_COLOR_THEME);
#endif
configuration_set_string(settings,
settings->arrays.discord_app_id,
DEFAULT_DISCORD_APP_ID);
configuration_set_string(settings,
settings->arrays.ai_service_url,
DEFAULT_AI_SERVICE_URL);
#ifdef HAVE_MATERIALUI
if (g_defaults.menu_materialui_menu_color_theme_enable)
settings->uints.menu_materialui_color_theme = g_defaults.menu_materialui_menu_color_theme;
#endif
#endif
settings->uints.video_scale = DEFAULT_SCALE;
video_driver_set_threaded(DEFAULT_VIDEO_THREADED);
settings->floats.video_msg_color_r = ((DEFAULT_MESSAGE_COLOR >> 16) & 0xff) / 255.0f;
settings->floats.video_msg_color_g = ((DEFAULT_MESSAGE_COLOR >> 8) & 0xff) / 255.0f;
settings->floats.video_msg_color_b = ((DEFAULT_MESSAGE_COLOR >> 0) & 0xff) / 255.0f;
if (g_defaults.settings_video_refresh_rate > 0.0 &&
g_defaults.settings_video_refresh_rate != DEFAULT_REFRESH_RATE)
settings->floats.video_refresh_rate = g_defaults.settings_video_refresh_rate;
if (DEFAULT_AUDIO_DEVICE)
configuration_set_string(settings,
settings->arrays.audio_device,
DEFAULT_AUDIO_DEVICE);
if (!g_defaults.settings_out_latency)
g_defaults.settings_out_latency = DEFAULT_OUT_LATENCY;
settings->uints.audio_latency = g_defaults.settings_out_latency;
settings->uints.audio_latency_floor = DEFAULT_AUDIO_LATENCY_FLOOR;
if (!g_defaults.settings_in_latency)
g_defaults.settings_in_latency = DEFAULT_IN_LATENCY;
/* Device-optimal audio parameters supplied by the frontend.
* Values saved in the config file still override these on
* load. */
if (g_defaults.settings_out_sample_rate > 0)
settings->uints.audio_output_sample_rate =
(unsigned)g_defaults.settings_out_sample_rate;
audio_set_float(AUDIO_ACTION_VOLUME_GAIN, settings->floats.audio_volume);
#ifdef HAVE_AUDIOMIXER
audio_set_float(AUDIO_ACTION_MIXER_VOLUME_GAIN, settings->floats.audio_mixer_volume);
#endif
audio_set_float(AUDIO_ACTION_RATE_CONTROL_DELTA, settings->floats.audio_rate_control_delta);
#ifdef HAVE_MICROPHONE
if (DEFAULT_MICROPHONE_DEVICE)
configuration_set_string(settings,
settings->arrays.microphone_device,
DEFAULT_MICROPHONE_DEVICE);
settings->uints.microphone_latency = g_defaults.settings_in_latency;
#endif
configuration_set_string(settings,
settings->arrays.midi_input,
DEFAULT_MIDI_INPUT);
configuration_set_string(settings,
settings->arrays.midi_output,
DEFAULT_MIDI_OUTPUT);
#ifdef HAVE_LAKKA
configuration_set_bool(settings,
settings->bools.ssh_enable, filestream_exists(LAKKA_SSH_PATH));
configuration_set_bool(settings,
settings->bools.samba_enable, !filestream_exists(LAKKA_SAMBA_DISABLED_FILE_PATH));
configuration_set_bool(settings,
settings->bools.bluetooth_enable, filestream_exists(LAKKA_BLUETOOTH_PATH));
configuration_set_bool(settings, settings->bools.localap_enable, false);
load_timezone(settings->arrays.timezone, TIMEZONE_LENGTH);
#ifdef HAVE_RETROFLAG
configuration_set_bool(settings,
settings->bools.safeshutdown_enable, filestream_exists(LAKKA_SAFESHUTDOWN_PATH));
#endif
#endif
#if __APPLE__
configuration_set_bool(settings,
settings->bools.accessibility_enable, RAIsVoiceOverRunning());
#endif
#ifdef ANDROID
configuration_set_bool(settings,
settings->bools.accessibility_enable, is_screen_reader_enabled());
#endif
#ifdef HAVE_MENU
if (first_initialized)
configuration_set_bool(settings,
settings->bools.menu_show_start_screen,
DEFAULT_MENU_SHOW_START_SCREEN);
#endif
#ifdef HAVE_CHEEVOS
*settings->arrays.cheevos_username = '\0';
*settings->arrays.cheevos_password = '\0';
*settings->arrays.cheevos_token = '\0';
#endif
/* The input's own state - the binds, the active remap, what a
* controller's profile gave - is reset with the settings in use,
* and only with them. Filling a copy with the defaults, which the
* save does to write only what differs, reset all of it for a user
* in the middle of a game: the remap gone, each port's kind of
* device and analog-to-digital setting put back, and every bind and
* profile copied aside and copied back to survive it. A copy gets
* its remap defaults written into it, and nothing in use is
* touched. */
if (settings == config_st)
{
/* The binds; not the controllers that are connected, which are
* no setting - forgetting them as well is for whoever is about
* to start the joypad driver again (config_load(), and the
* menu's reset to defaults). */
input_config_reset_binds();
input_remapping_deinit(false);
input_remapping_set_defaults(false);
}
else
input_remapping_defaults_into(settings);
configuration_set_string(settings,
settings->paths.network_buildbot_url, DEFAULT_BUILDBOT_SERVER_URL);
configuration_set_string(settings,
settings->paths.network_buildbot_assets_url,
DEFAULT_BUILDBOT_ASSETS_SERVER_URL);
*settings->arrays.input_keyboard_layout = '\0';
for (i = 0; i < MAX_USERS; i++)
{
settings->uints.input_joypad_index[i] = (unsigned)i;
settings->uints.input_analog_dpad_mode[i] = ANALOG_DPAD_LSTICK;
if (settings == config_st)
input_config_set_device((unsigned)i, RETRO_DEVICE_JOYPAD);
else
settings->uints.input_libretro_device[i] = RETRO_DEVICE_JOYPAD;
settings->uints.input_mouse_index[i] = (unsigned)i;
settings->uints.input_keyboard_index[i] = 0;
settings->uints.input_aim_stick[i] = INPUT_AIM_STICK_NONE;
settings->uints.input_touchpad[i] = INPUT_TOUCHPAD_POINTER;
}
#ifdef HAVE_VIDEO_WINDOWS
for (i = 0; i < RETRO_VIDEO_VIEWS_MAX; i++)
{
settings->uints.video_screen_window_mode[i] = i
? VIDEO_WINDOW_SEPARATE : VIDEO_WINDOW_ATTACHED;
settings->uints.video_screen_window_pos[i] = 0;
settings->uints.video_screen_window_dims[i] = 0;
settings->uints.video_screen_window_monitor[i] = 0;
settings->bools.video_screen_window_fullscreen[i] = false;
}
#endif
custom_vp->dims = 0;
custom_vp->pos = 0;
/* Make sure settings from other configs carry over into defaults
* for another config. */
if (!retroarch_override_setting_is_set(RARCH_OVERRIDE_SETTING_SAVE_PATH, NULL))
dir_clear(RARCH_DIR_SAVEFILE);
if (!retroarch_override_setting_is_set(RARCH_OVERRIDE_SETTING_STATE_PATH, NULL))
dir_clear(RARCH_DIR_SAVESTATE);
*settings->paths.path_libretro_info = '\0';
*settings->paths.directory_libretro = '\0';
*settings->paths.directory_screenshot = '\0';
*settings->paths.directory_system = '\0';
*settings->paths.directory_cache = '\0';
*settings->paths.directory_input_remapping = '\0';
*settings->paths.directory_core_assets = '\0';
*settings->paths.directory_assets = '\0';
*settings->paths.directory_dynamic_wallpapers = '\0';
*settings->paths.directory_thumbnails = '\0';
*settings->paths.directory_playlist = '\0';
*settings->paths.directory_content_favorites = '\0';
*settings->paths.directory_content_history = '\0';
*settings->paths.directory_content_image_history = '\0';
*settings->paths.directory_content_music_history = '\0';
*settings->paths.directory_content_video_history = '\0';
*settings->paths.directory_runtime_log = '\0';
*settings->paths.directory_autoconfig = '\0';
#ifdef HAVE_MENU
*settings->paths.directory_menu_content = '\0';
*settings->paths.directory_menu_config = '\0';
#endif
*settings->paths.directory_video_shader = '\0';
*settings->paths.directory_video_filter = '\0';
*settings->paths.directory_audio_filter = '\0';
retroarch_ctl(RARCH_CTL_UNSET_UPS_PREF, NULL);
retroarch_ctl(RARCH_CTL_UNSET_BPS_PREF, NULL);
retroarch_ctl(RARCH_CTL_UNSET_IPS_PREF, NULL);
retroarch_ctl(RARCH_CTL_UNSET_XDELTA_PREF, NULL);
*recording_st->output_dir = '\0';
*recording_st->config_dir = '\0';
*settings->paths.path_core_options = '\0';
*settings->paths.path_content_favorites = '\0';
*settings->paths.path_content_history = '\0';
*settings->paths.path_content_image_history = '\0';
*settings->paths.path_content_music_history = '\0';
*settings->paths.path_content_video_history = '\0';
*settings->paths.path_cheat_settings = '\0';
#if !defined(__APPLE__) && !defined(ANDROID)
*settings->paths.bundle_assets_src = '\0';
*settings->paths.bundle_assets_dst = '\0';
*settings->paths.bundle_assets_dst_subdir = '\0';
#endif
*settings->paths.path_cheat_database = '\0';
*settings->paths.path_menu_wallpaper = '\0';
*settings->paths.path_rgui_theme_preset = '\0';
*settings->paths.path_content_database = '\0';
*settings->paths.path_overlay = '\0';
*settings->paths.path_osk_overlay = '\0';
*settings->paths.path_record_config = '\0';
*settings->paths.path_stream_config = '\0';
*settings->paths.path_stream_url = '\0';
*settings->paths.path_softfilter_plugin = '\0';
*settings->paths.path_audio_dsp_plugin = '\0';
*settings->paths.log_dir = '\0';
if (*g_defaults.dirs[DEFAULT_DIR_WALLPAPERS])
configuration_set_string(settings,
settings->paths.directory_dynamic_wallpapers,
g_defaults.dirs[DEFAULT_DIR_WALLPAPERS]);
if (*g_defaults.dirs[DEFAULT_DIR_THUMBNAILS])
configuration_set_string(settings,
settings->paths.directory_thumbnails,
g_defaults.dirs[DEFAULT_DIR_THUMBNAILS]);
if (*g_defaults.dirs[DEFAULT_DIR_REMAP])
configuration_set_string(settings,
settings->paths.directory_input_remapping,
g_defaults.dirs[DEFAULT_DIR_REMAP]);
if (*g_defaults.dirs[DEFAULT_DIR_CACHE])
configuration_set_string(settings,
settings->paths.directory_cache,
g_defaults.dirs[DEFAULT_DIR_CACHE]);
if (*g_defaults.dirs[DEFAULT_DIR_ASSETS])
configuration_set_string(settings,
settings->paths.directory_assets,
g_defaults.dirs[DEFAULT_DIR_ASSETS]);
if (*g_defaults.dirs[DEFAULT_DIR_CORE_ASSETS])
configuration_set_string(settings,
settings->paths.directory_core_assets,
g_defaults.dirs[DEFAULT_DIR_CORE_ASSETS]);
if (*g_defaults.dirs[DEFAULT_DIR_PLAYLIST])
configuration_set_string(settings,
settings->paths.directory_playlist,
g_defaults.dirs[DEFAULT_DIR_PLAYLIST]);
if (*g_defaults.dirs[DEFAULT_DIR_CONTENT_FAVORITES])
configuration_set_string(settings,
settings->paths.directory_content_favorites,
g_defaults.dirs[DEFAULT_DIR_CONTENT_FAVORITES]);
if (*g_defaults.dirs[DEFAULT_DIR_CONTENT_HISTORY])
configuration_set_string(settings,
settings->paths.directory_content_history,
g_defaults.dirs[DEFAULT_DIR_CONTENT_HISTORY]);
if (*g_defaults.dirs[DEFAULT_DIR_CONTENT_IMAGE_HISTORY])
configuration_set_string(settings,
settings->paths.directory_content_image_history,
g_defaults.dirs[DEFAULT_DIR_CONTENT_IMAGE_HISTORY]);
if (*g_defaults.dirs[DEFAULT_DIR_CONTENT_MUSIC_HISTORY])
configuration_set_string(settings,
settings->paths.directory_content_music_history,
g_defaults.dirs[DEFAULT_DIR_CONTENT_MUSIC_HISTORY]);
if (*g_defaults.dirs[DEFAULT_DIR_CONTENT_VIDEO_HISTORY])
configuration_set_string(settings,
settings->paths.directory_content_video_history,
g_defaults.dirs[DEFAULT_DIR_CONTENT_VIDEO_HISTORY]);
if (*g_defaults.dirs[DEFAULT_DIR_CORE])
fill_pathname_expand_special(settings->paths.directory_libretro,
g_defaults.dirs[DEFAULT_DIR_CORE],
sizeof(settings->paths.directory_libretro));
if (*g_defaults.dirs[DEFAULT_DIR_AUDIO_FILTER])
configuration_set_string(settings,
settings->paths.directory_audio_filter,
g_defaults.dirs[DEFAULT_DIR_AUDIO_FILTER]);
if (*g_defaults.dirs[DEFAULT_DIR_VIDEO_FILTER])
configuration_set_string(settings,
settings->paths.directory_video_filter,
g_defaults.dirs[DEFAULT_DIR_VIDEO_FILTER]);
if (*g_defaults.dirs[DEFAULT_DIR_SHADER])
fill_pathname_expand_special(settings->paths.directory_video_shader,
g_defaults.dirs[DEFAULT_DIR_SHADER],
sizeof(settings->paths.directory_video_shader));
if (*g_defaults.path_buildbot_server_url)
configuration_set_string(settings,
settings->paths.network_buildbot_url,
g_defaults.path_buildbot_server_url);
if (*g_defaults.dirs[DEFAULT_DIR_DATABASE])
configuration_set_string(settings,
settings->paths.path_content_database,
g_defaults.dirs[DEFAULT_DIR_DATABASE]);
if (*g_defaults.dirs[DEFAULT_DIR_CHEATS])
configuration_set_string(settings,
settings->paths.path_cheat_database,
g_defaults.dirs[DEFAULT_DIR_CHEATS]);
if (*g_defaults.dirs[DEFAULT_DIR_CORE_INFO])
fill_pathname_expand_special(settings->paths.path_libretro_info,
g_defaults.dirs[DEFAULT_DIR_CORE_INFO],
sizeof(settings->paths.path_libretro_info));
#ifdef HAVE_OVERLAY
if (*g_defaults.dirs[DEFAULT_DIR_OVERLAY])
{
fill_pathname_expand_special(settings->paths.directory_overlay,
g_defaults.dirs[DEFAULT_DIR_OVERLAY],
sizeof(settings->paths.directory_overlay));
#ifdef RARCH_MOBILE
if (!*settings->paths.path_overlay)
fill_pathname_join_special(settings->paths.path_overlay,
settings->paths.directory_overlay,
FILE_PATH_DEFAULT_OVERLAY,
sizeof(settings->paths.path_overlay));
if (!*settings->paths.path_osk_overlay)
fill_pathname_join_special(settings->paths.path_osk_overlay,
settings->paths.directory_overlay,
FILE_PATH_DEFAULT_OSK_OVERLAY,
sizeof(settings->paths.path_osk_overlay));
#endif
}
if (*g_defaults.dirs[DEFAULT_DIR_OSK_OVERLAY])
fill_pathname_expand_special(settings->paths.directory_osk_overlay,
g_defaults.dirs[DEFAULT_DIR_OSK_OVERLAY],
sizeof(settings->paths.directory_osk_overlay));
#endif
if (*g_defaults.dirs[DEFAULT_DIR_MENU_CONFIG])
{
configuration_set_string(settings,
settings->paths.directory_menu_config,
g_defaults.dirs[DEFAULT_DIR_MENU_CONFIG]);
#if TARGET_OS_IPHONE
{
char config_file_path[PATH_MAX_LENGTH];
fill_pathname_join_special(config_file_path,
settings->paths.directory_menu_config,
FILE_PATH_MAIN_CONFIG,
sizeof(config_file_path));
path_set(RARCH_PATH_CONFIG,
config_file_path);
}
#endif
}
if (*g_defaults.dirs[DEFAULT_DIR_MENU_CONTENT])
configuration_set_string(settings,
settings->paths.directory_menu_content,
g_defaults.dirs[DEFAULT_DIR_MENU_CONTENT]);
if (*g_defaults.dirs[DEFAULT_DIR_AUTOCONFIG])
configuration_set_string(settings,
settings->paths.directory_autoconfig,
g_defaults.dirs[DEFAULT_DIR_AUTOCONFIG]);
if (*g_defaults.dirs[DEFAULT_DIR_SAVESTATE])
dir_set(RARCH_DIR_SAVESTATE, g_defaults.dirs[DEFAULT_DIR_SAVESTATE]);
if (*g_defaults.dirs[DEFAULT_DIR_SRAM])
dir_set(RARCH_DIR_SAVEFILE, g_defaults.dirs[DEFAULT_DIR_SRAM]);
if (*g_defaults.dirs[DEFAULT_DIR_SYSTEM])
configuration_set_string(settings,
settings->paths.directory_system,
g_defaults.dirs[DEFAULT_DIR_SYSTEM]);
if (*g_defaults.dirs[DEFAULT_DIR_SCREENSHOT])
configuration_set_string(settings,
settings->paths.directory_screenshot,
g_defaults.dirs[DEFAULT_DIR_SCREENSHOT]);
if (*g_defaults.dirs[DEFAULT_DIR_LOGS])
configuration_set_string(settings,
settings->paths.log_dir,
g_defaults.dirs[DEFAULT_DIR_LOGS]);
if (*g_defaults.dirs[DEFAULT_DIR_RECORD_OUTPUT])
fill_pathname_expand_special(recording_st->output_dir,
g_defaults.dirs[DEFAULT_DIR_RECORD_OUTPUT],
sizeof(recording_st->output_dir));
if (*g_defaults.dirs[DEFAULT_DIR_RECORD_CONFIG])
fill_pathname_expand_special(recording_st->config_dir,
g_defaults.dirs[DEFAULT_DIR_RECORD_CONFIG],
sizeof(recording_st->config_dir));
if (*g_defaults.path_config)
{
char temp_str[PATH_MAX_LENGTH];
temp_str[0] = '\0';
fill_pathname_expand_special(temp_str,
g_defaults.path_config,
sizeof(temp_str));
path_set(RARCH_PATH_CONFIG, temp_str);
}
/* Built-in playlist default paths,
* needed when creating a new cfg from scratch */
{
char new_path[PATH_MAX_LENGTH];
fill_pathname_join_special(
new_path,
settings->paths.directory_playlist,
FILE_PATH_BUILTIN,
sizeof(new_path));
if ( !(retroarch_get_flags() & RARCH_FLAGS_USER_DIRS_HELD)
&& !path_is_directory(new_path))
path_mkdir(new_path);
if (!*settings->paths.path_content_favorites)
strlcpy_lit(settings->paths.directory_content_favorites, "default",
sizeof(settings->paths.directory_content_favorites));
if ( !*settings->paths.directory_content_favorites
|| string_is_equal(settings->paths.directory_content_favorites, "default"))
fill_pathname_join_special(
settings->paths.path_content_favorites,
new_path,
FILE_PATH_CONTENT_FAVORITES,
sizeof(settings->paths.path_content_favorites));
else
fill_pathname_join_special(
settings->paths.path_content_favorites,
settings->paths.directory_content_favorites,
FILE_PATH_CONTENT_FAVORITES,
sizeof(settings->paths.path_content_favorites));
if (!*settings->paths.path_content_history)
strlcpy_lit(settings->paths.directory_content_history, "default",
sizeof(settings->paths.directory_content_history));
if ( !*settings->paths.directory_content_history
|| string_is_equal(settings->paths.directory_content_history, "default"))
fill_pathname_join_special(
settings->paths.path_content_history,
new_path,
FILE_PATH_CONTENT_HISTORY,
sizeof(settings->paths.path_content_history));
else
fill_pathname_join_special(
settings->paths.path_content_history,
settings->paths.directory_content_history,
FILE_PATH_CONTENT_HISTORY,
sizeof(settings->paths.path_content_history));
if (!*settings->paths.path_content_image_history)
strlcpy_lit(settings->paths.directory_content_image_history, "default",
sizeof(settings->paths.directory_content_image_history));
if ( !*settings->paths.directory_content_image_history
|| string_is_equal(settings->paths.directory_content_image_history, "default"))
fill_pathname_join_special(
settings->paths.path_content_image_history,
new_path,
FILE_PATH_CONTENT_IMAGE_HISTORY,
sizeof(settings->paths.path_content_image_history));
else
fill_pathname_join_special(
settings->paths.path_content_image_history,
settings->paths.directory_content_image_history,
FILE_PATH_CONTENT_IMAGE_HISTORY,
sizeof(settings->paths.path_content_image_history));
if (!*settings->paths.path_content_music_history)
strlcpy_lit(settings->paths.directory_content_music_history, "default",
sizeof(settings->paths.directory_content_music_history));
if ( !*settings->paths.directory_content_music_history
|| string_is_equal(settings->paths.directory_content_music_history, "default"))
fill_pathname_join_special(
settings->paths.path_content_music_history,
new_path,
FILE_PATH_CONTENT_MUSIC_HISTORY,
sizeof(settings->paths.path_content_music_history));
else
fill_pathname_join_special(
settings->paths.path_content_music_history,
settings->paths.directory_content_music_history,
FILE_PATH_CONTENT_MUSIC_HISTORY,
sizeof(settings->paths.path_content_music_history));
if (!*settings->paths.path_content_video_history)
strlcpy_lit(settings->paths.directory_content_video_history, "default",
sizeof(settings->paths.directory_content_video_history));
if ( !*settings->paths.directory_content_video_history
|| string_is_equal(settings->paths.directory_content_video_history, "default"))
fill_pathname_join_special(
settings->paths.path_content_video_history,
new_path,
FILE_PATH_CONTENT_VIDEO_HISTORY,
sizeof(settings->paths.path_content_video_history));
else
fill_pathname_join_special(
settings->paths.path_content_video_history,
settings->paths.directory_content_video_history,
FILE_PATH_CONTENT_VIDEO_HISTORY,
sizeof(settings->paths.path_content_video_history));
}
#ifdef HAVE_CONFIGFILE
/* Avoid reloading config on every content load */
if (DEFAULT_BLOCK_CONFIG_READ)
retroarch_ctl(RARCH_CTL_SET_BLOCK_CONFIG_READ, NULL);
else
retroarch_ctl(RARCH_CTL_UNSET_BLOCK_CONFIG_READ, NULL);
#endif
#ifdef HAVE_MENU
first_initialized = false;
#endif
}
/**
* config_load:
*
* Loads a config file and reads all the values into memory.
*
*/
void config_load(void)
{
config_set_defaults(config_st);
/* a load is followed by the drivers starting: the controllers are
* found again then, and start from nothing here, as they did when
* the defaults forgot them */
input_config_forget_controllers();
#ifdef HAVE_CONFIGFILE
config_parse_file();
#endif
}
#ifdef HAVE_CONFIGFILE
#if defined(HAVE_MENU) && defined(HAVE_RGUI)
static bool check_menu_driver_compatibility(settings_t *settings)
{
char *video_driver = settings->arrays.video_driver;
char *menu_driver = settings->arrays.menu_driver;
if ( (memcmp(menu_driver, "rgui", 4) == 0 && menu_driver[4] == '\0')
|| (memcmp(menu_driver, "null", 4) == 0 && menu_driver[4] == '\0')
|| (memcmp(video_driver, "null", 4) == 0 && video_driver[4] == '\0'))
return true;
switch (video_driver[0])
{
case 'd':
return (memcmp(video_driver, "d3d8", 4) == 0 && video_driver[4] == '\0')
|| (memcmp(video_driver, "d3d9_hlsl", 9) == 0 && video_driver[9] == '\0')
|| (memcmp(video_driver, "d3d9_cg", 7) == 0 && video_driver[7] == '\0')
|| (memcmp(video_driver, "d3d10", 5) == 0 && video_driver[5] == '\0')
|| (memcmp(video_driver, "d3d11", 5) == 0 && video_driver[5] == '\0')
|| (memcmp(video_driver, "d3d12", 5) == 0 && video_driver[5] == '\0');
case 'g':
if (video_driver[1] == 'l')
return (memcmp(video_driver, "gl", 2) == 0 && video_driver[2] == '\0')
|| (memcmp(video_driver, "gl1", 3) == 0 && video_driver[3] == '\0')
|| (memcmp(video_driver, "glcore", 6) == 0 && video_driver[6] == '\0');
if (video_driver[1] == 'x')
return (memcmp(video_driver, "gx2", 3) == 0 && video_driver[3] == '\0');
if (video_driver[1] == 'd')
return (memcmp(video_driver, "gdi", 3) == 0 && video_driver[3] == '\0');
return false;
case 'v':
return (memcmp(video_driver, "vulkan", 6) == 0 && video_driver[6] == '\0')
|| (memcmp(video_driver, "vita2d", 6) == 0 && video_driver[6] == '\0');
case 'm':
return (memcmp(video_driver, "metal", 5) == 0 && video_driver[5] == '\0');
case 'r':
return (memcmp(video_driver, "rsx", 3) == 0 && video_driver[3] == '\0');
case 's':
/* sdl2/sdl3 support the full menu set (XMB/Ozone/MaterialUI/
* RGUI) via their gfx_display + raster-font backends, built
* on SDL_RenderGeometry. For sdl2 that entry point needs
* SDL >= 2.0.18; on older SDL builds the driver self-disables
* the gfx_display backend and only RGUI's bitmap path is
* functional - which already returned true via the rgui
* early-out above, so allowing sdl2 here is safe regardless
* of the runtime SDL version. sdl3 always has
* SDL_RenderGeometry. */
return (memcmp(video_driver, "sdl2", 4) == 0 && video_driver[4] == '\0')
|| (memcmp(video_driver, "sdl3", 4) == 0 && video_driver[4] == '\0');
case 'c':
return (memcmp(video_driver, "ctr", 3) == 0 && video_driver[3] == '\0');
default:
break;
}
return false;
}
#endif
/**
* open_default_config_file
*
* Open a default config file. Platform-specific.
*
* Returns: handle to config file if found, otherwise NULL.
**/
static config_file_t *open_default_config_file(void)
{
char conf_path[PATH_MAX_LENGTH];
config_file_t *conf = NULL;
#ifndef RARCH_CONSOLE
char application_data[PATH_MAX_LENGTH] = {0};
#endif
#if defined(_WIN32) && !defined(_XBOX)
char app_path[PATH_MAX_LENGTH] = {0};
#if defined(__WINRT__) || defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP
/* On UWP, the app install directory is not writable so use the writable LocalState dir instead */
fill_pathname_home_dir(app_path, sizeof(app_path));
#else
fill_pathname_application_dir(app_path, sizeof(app_path));
#endif
fill_pathname_resolve_relative(conf_path, app_path,
FILE_PATH_MAIN_CONFIG, sizeof(conf_path));
conf = config_file_new_from_path_to_string(conf_path);
if (!conf)
{
if (fill_pathname_application_data(application_data,
sizeof(application_data)))
{
fill_pathname_join_special(conf_path, application_data,
FILE_PATH_MAIN_CONFIG, sizeof(conf_path));
conf = config_file_new_from_path_to_string(conf_path);
}
}
if (!conf)
{
bool saved = false;
/* Try to create a new config file. */
conf = config_file_new_alloc();
if (conf)
{
/* Since this is a clean config file, we can
* safely use config_save_on_exit. */
fill_pathname_resolve_relative(conf_path, app_path,
FILE_PATH_MAIN_CONFIG, sizeof(conf_path));
config_set_string(conf, "config_save_on_exit", "true");
saved = config_file_write(conf, conf_path, true);
}
if (!saved)
{
/* WARN here to make sure user has a good chance of seeing it. */
RARCH_ERR("[Config] Failed to create new config file in: \"%s\".\n",
conf_path);
if (conf)
config_file_free(conf);
return NULL;
}
RARCH_LOG("[Config] Created new config file in: \"%s\".\n", conf_path);
}
#elif TARGET_OS_OSX
if (!fill_pathname_application_data(application_data,
sizeof(application_data)))
{
if (conf)
config_file_free(conf);
return NULL;
}
/* Group config file with menu configs, remaps, etc: */
strlcat(application_data, "/config", sizeof(application_data));
path_mkdir(application_data);
fill_pathname_join_special(conf_path, application_data,
FILE_PATH_MAIN_CONFIG, sizeof(conf_path));
if (!(conf = config_file_new_from_path_to_string(conf_path)))
{
bool saved = false;
if ((conf = config_file_new_alloc()))
{
config_set_string(conf, "config_save_on_exit", "true");
saved = config_file_write(conf, conf_path, true);
}
if (!saved)
{
/* WARN here to make sure user has a good chance of seeing it. */
RARCH_ERR("[Config] Failed to create new config file in: \"%s\".\n",
conf_path);
if (conf)
config_file_free(conf);
return NULL;
}
RARCH_LOG("[Config] Created new config file in: \"%s\".\n", conf_path);
}
#elif !defined(RARCH_CONSOLE)
bool has_application_data =
fill_pathname_application_data(application_data,
sizeof(application_data));
if (has_application_data)
{
fill_pathname_join_special(conf_path, application_data,
FILE_PATH_MAIN_CONFIG, sizeof(conf_path));
RARCH_LOG("[Config] Looking for config in: \"%s\".\n", conf_path);
conf = config_file_new_from_path_to_string(conf_path);
}
/* Fallback to $HOME/.retroarch.cfg. */
if (!conf && getenv("HOME"))
{
fill_pathname_join_special(conf_path, getenv("HOME"),
"." FILE_PATH_MAIN_CONFIG, sizeof(conf_path));
RARCH_LOG("[Config] Looking for config in: \"%s\".\n", conf_path);
conf = config_file_new_from_path_to_string(conf_path);
}
if (!conf && has_application_data)
{
char basedir[DIR_MAX_LENGTH];
/* Try to create a new config file. */
fill_pathname_basedir(basedir, application_data, sizeof(basedir));
fill_pathname_join_special(conf_path, application_data,
FILE_PATH_MAIN_CONFIG, sizeof(conf_path));
if ((path_mkdir(basedir)))
{
char skeleton_conf[PATH_MAX_LENGTH];
bool saved = false;
/* Build a retroarch.cfg path from the
* global config directory (/etc). */
fill_pathname_join_special(skeleton_conf, GLOBAL_CONFIG_DIR,
FILE_PATH_MAIN_CONFIG, sizeof(skeleton_conf));
if ((conf = config_file_new_from_path_to_string(skeleton_conf)))
RARCH_LOG("[Config] Using skeleton config \"%s\" as base for a new config file.\n", skeleton_conf);
else
conf = config_file_new_alloc();
if (conf)
{
/* Since this is a clean config file, we can
* safely use config_save_on_exit. */
config_set_string(conf, "config_save_on_exit", "true");
saved = config_file_write(conf, conf_path, true);
}
if (!saved)
{
/* WARN here to make sure user has a good chance of seeing it. */
RARCH_ERR("[Config] Failed to create new config file in: \"%s\".\n",
conf_path);
if (conf)
config_file_free(conf);
return NULL;
}
RARCH_LOG("[Config] Created new config file in: \"%s\".\n",
conf_path);
}
}
#endif
if (!conf)
return NULL;
path_set(RARCH_PATH_CONFIG, conf_path);
return conf;
}
static void check_verbosity_settings(config_file_t *conf,
settings_t *settings)
{
unsigned tmp_uint = 0;
bool tmp_bool = false;
/* Make sure log_to_file is true if 'log-file' command line argument was used. */
if (retroarch_override_setting_is_set(RARCH_OVERRIDE_SETTING_LOG_TO_FILE, NULL))
{
configuration_set_bool(settings, settings->bools.log_to_file, true);
}
else
{
/* Make sure current 'log_to_file' is effective */
if (config_get_bool(conf, "log_to_file", &tmp_bool))
configuration_set_bool(settings, settings->bools.log_to_file, tmp_bool);
}
/* Set frontend log level */
if (config_get_uint(conf, "frontend_log_level", &tmp_uint))
verbosity_set_log_level(tmp_uint);
/* Set verbosity according to config only if command line argument was not used. */
if (retroarch_override_setting_is_set(RARCH_OVERRIDE_SETTING_VERBOSITY, NULL))
{
verbosity_enable();
}
else
{
if (config_get_bool(conf, "log_verbosity", &tmp_bool))
{
if (tmp_bool)
verbosity_enable();
else
verbosity_disable();
}
}
}
/* Turbo Bind and Turbo Button index the remap and bind tables
* directly, so a value read from a config or remap file has to stay
* inside their menu ranges: Turbo Bind is -1 (empty) or a RetroPad
* ID up to the analog binds, Turbo Button a digital RetroPad ID. */
static void config_sanitize_turbo_binds(settings_t *settings)
{
if ( settings->ints.input_turbo_bind < -1
|| settings->ints.input_turbo_bind >= RARCH_ANALOG_BIND_LIST_END)
settings->ints.input_turbo_bind = DEFAULT_TURBO_BIND;
if (settings->uints.input_turbo_button >= RARCH_FIRST_CUSTOM_BIND)
settings->uints.input_turbo_button = DEFAULT_TURBO_BUTTON;
}
#ifdef HAVE_VIDEO_WINDOWS
/* Keep indexed-load scratch out of config_load_file's frame. */
#if defined(__OPTIMIZE_SIZE__)
#define CONFIG_NOINLINE
#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))
#define CONFIG_NOINLINE __attribute__((noinline))
#elif defined(_MSC_VER)
#define CONFIG_NOINLINE __declspec(noinline)
#else
#define CONFIG_NOINLINE
#endif
CONFIG_NOINLINE static void config_load_video_windows(settings_t *settings, config_file_t *conf)
{
unsigned i;
for (i = 0; i < RETRO_VIDEO_VIEWS_MAX; i++)
{
char cfg[64];
int x = 0, y = 0;
unsigned width = 0, height = 0;
size_t len = snprintf(cfg, sizeof(cfg), "video_screen%u_window_", i + 1);
settings->uints.video_screen_window_mode[i] = i
? VIDEO_WINDOW_SEPARATE : VIDEO_WINDOW_ATTACHED;
settings->uints.video_screen_window_monitor[i] = 0;
settings->bools.video_screen_window_fullscreen[i] = false;
strlcpy_lit(cfg + len, "mode", sizeof(cfg) - len);
config_get_uint(conf, cfg, &settings->uints.video_screen_window_mode[i]);
if (!i || settings->uints.video_screen_window_mode[i] > VIDEO_WINDOW_HIDDEN)
settings->uints.video_screen_window_mode[i] = i
? VIDEO_WINDOW_SEPARATE : VIDEO_WINDOW_ATTACHED;
strlcpy_lit(cfg + len, "x", sizeof(cfg) - len);
config_get_int(conf, cfg, &x);
strlcpy_lit(cfg + len, "y", sizeof(cfg) - len);
config_get_int(conf, cfg, &y);
strlcpy_lit(cfg + len, "width", sizeof(cfg) - len);
config_get_uint(conf, cfg, &width);
strlcpy_lit(cfg + len, "height", sizeof(cfg) - len);
config_get_uint(conf, cfg, &height);
strlcpy_lit(cfg + len, "monitor", sizeof(cfg) - len);
config_get_uint(conf, cfg, &settings->uints.video_screen_window_monitor[i]);
strlcpy_lit(cfg + len, "fullscreen", sizeof(cfg) - len);
config_get_bool(conf, cfg, &settings->bools.video_screen_window_fullscreen[i]);
settings->uints.video_screen_window_pos[i] =
x >= VIDEO_POS_MIN && x <= VIDEO_POS_MAX
&& y >= VIDEO_POS_MIN && y <= VIDEO_POS_MAX ? VIDEO_POS_PACK(x, y) : 0;
settings->uints.video_screen_window_dims[i] =
width && height && VIDEO_SCALE_FITS(width, height)
? VIDEO_SCALE_PACK(width, height) : 0;
}
}
#undef CONFIG_NOINLINE
#endif
/**
* config_load:
* @path : path to be read from.
* @set_defaults : set default values first before
* reading the values from the config file
*
* Loads a config file and reads all the values into memory.
*
*/
static bool config_load_file(const char *path, settings_t *settings)
{
unsigned i;
char tmp_str[PATH_MAX_LENGTH];
char* libretro_directory = NULL;
char* libretro_assets_directory = NULL;
char* libretro_autoconfig_directory = NULL;
char* libretro_cheats_directory = NULL;
char* libretro_database_directory = NULL;
char* libretro_system_directory = NULL;
char* libretro_video_filter_directory = NULL;
char* libretro_video_shader_directory = NULL;
static bool first_load = true;
bool without_overrides = false;
unsigned msg_color = 0;
char override_username[PATH_MAX_LENGTH];
bool override_username_set = false;
runloop_state_t *runloop_st = runloop_state_get_ptr();
int bool_settings_size = SETTINGS_BOOL_COUNT_MAX;
int float_settings_size = SETTINGS_FLOAT_COUNT_MAX;
int int_settings_size = SETTINGS_INT_COUNT_MAX;
int uint_settings_size = SETTINGS_UINT_COUNT_MAX;
int size_settings_size = SETTINGS_SIZE_COUNT_MAX;
int array_settings_size = SETTINGS_ARRAY_COUNT_MAX;
int path_settings_size = SETTINGS_PATH_COUNT_MAX;
struct config_bool_setting *bool_settings = NULL;
struct config_float_setting *float_settings = NULL;
struct config_int_setting *int_settings = NULL;
struct config_uint_setting *uint_settings = NULL;
struct config_size_setting *size_settings = NULL;
struct config_array_setting *array_settings = NULL;
struct config_path_setting *path_settings = NULL;
config_file_t *conf = NULL;
uint32_t rarch_flags = retroarch_get_flags();
tmp_str[0] = '\0';
/* Override config comparison must be compared to config before overrides */
if (string_is_equal(path, "without-overrides"))
{
path = path_get(RARCH_PATH_CONFIG);
without_overrides = true;
}
conf = (path) ? config_file_new_from_path_to_string(path) : open_default_config_file();
#if TARGET_OS_TV
if (!conf && path && string_is_equal(path, path_get(RARCH_PATH_CONFIG)))
{
/* Sometimes the OS decides it needs to reclaim disk space
* by emptying the cache, which is the only disk space we
* have access to, other than NSUserDefaults. */
conf = open_userdefaults_config_file();
}
#endif
if (!conf)
{
first_load = false;
if (!path)
return true;
return false;
}
bool_settings = populate_settings_bool (settings, &bool_settings_size);
float_settings = populate_settings_float (settings, &float_settings_size);
int_settings = populate_settings_int (settings, &int_settings_size);
uint_settings = populate_settings_uint (settings, &uint_settings_size);
size_settings = populate_settings_size (settings, &size_settings_size);
array_settings = populate_settings_array (settings, &array_settings_size);
path_settings = populate_settings_path (settings, &path_settings_size);
/* Initialize verbosity settings */
check_verbosity_settings(conf, settings);
if (!first_load)
{
if (!path)
RARCH_LOG("[Config] Loading default config.\n");
else
RARCH_LOG("[Config] Loading config: \"%s\".\n", path);
}
/* Merge credentials from separate file.
* Credentials are stored in retroarch-keychain.cfg alongside
* the main config to keep sensitive data (passwords,
* tokens, keys) out of retroarch.cfg.
* Merged before any --appendconfig files so that an
* explicit override on the command line still wins. */
{
char credentials_path[PATH_MAX_LENGTH];
credentials_path[0] = '\0';
config_get_credentials_path(credentials_path,
sizeof(credentials_path));
if (!string_is_empty(credentials_path)
&& path_is_valid(credentials_path))
{
bool result = config_append_file(conf, credentials_path);
#ifdef HAVE_KEYCHAIN
bool keychain_ok = result && config_keychain_init();
/* Run whether or not the keychain is ready: with no key to
* open them, sealed values are still taken out of what the
* loader sees, or a setting would take the blob itself as its
* value (a locked keychain would log in with it). */
unsigned unopened = result
? config_keychain_open_entries(conf) : 0;
#endif
/* The first load runs before file logging is up; logging
* here would go to the console. Same gate as the append
* blocks below. */
if (!first_load)
{
RARCH_LOG("[Config] Merging credentials from \"%s\".\n",
credentials_path);
if (!result)
RARCH_ERR("[Config] Failed to merge credentials from \"%s\".\n",
credentials_path);
#ifdef HAVE_KEYCHAIN
else if (!keychain_ok && keychain_is_locked())
RARCH_WARN("[Config] Keychain was moved from another machine "
"and is locked; enter its passphrase under "
"Settings > User.\n");
else if (!keychain_ok)
RARCH_WARN("[Config] Keychain key file unavailable, "
"credentials stay in the clear.\n");
else if (unopened)
RARCH_WARN("[Config] %u credential(s) were sealed on another "
"machine or install and could not be opened.\n",
unopened);
#endif
}
}
}
if (!path_is_empty(RARCH_PATH_CONFIG_APPEND))
{
char tmp_append_path[PATH_MAX_LENGTH];
const char *ptr = NULL;
strlcpy(tmp_append_path, path_get(RARCH_PATH_CONFIG_APPEND),
sizeof(tmp_append_path));
ptr = tmp_append_path;
while (ptr && *ptr)
{
char config_path[PATH_MAX_LENGTH];
const char *delim = strchr(ptr, '|');
if (delim)
{
size_t len = delim - ptr;
if (len >= sizeof(config_path))
len = sizeof(config_path) - 1;
memcpy(config_path, ptr, len);
config_path[len] = '\0';
ptr = delim + 1;
}
else
{
strlcpy(config_path, ptr, sizeof(config_path));
ptr = NULL;
}
if (*config_path)
{
bool result = config_append_file(conf, config_path);
if (!first_load)
{
RARCH_LOG("[Config] Appending config: \"%s\".\n", config_path);
if (!result)
RARCH_ERR("[Config] Failed to append config: \"%s\".\n", config_path);
}
}
}
/* Re-check verbosity settings */
check_verbosity_settings(conf, settings);
}
if (!path_is_empty(RARCH_PATH_CONFIG_OVERRIDE) && !without_overrides)
{
char tmp_append_path[PATH_MAX_LENGTH];
char *extra_path = NULL;
#ifdef HAVE_OVERLAY
char old_overlay_path[PATH_MAX_LENGTH], new_overlay_path[PATH_MAX_LENGTH];
config_get_path(conf, "input_overlay", old_overlay_path, sizeof(old_overlay_path));
#endif
strlcpy(tmp_append_path, path_get(RARCH_PATH_CONFIG_OVERRIDE),
sizeof(tmp_append_path));
extra_path = tmp_append_path;
while (extra_path && *extra_path)
{
char *next = strchr(extra_path, '|');
if (next)
*next++ = '\0';
{
bool result = config_append_file(conf, extra_path);
if (!first_load)
{
RARCH_LOG("[Config] Appending override config: \"%s\".\n", extra_path);
if (!result)
RARCH_ERR("[Config] Failed to append override config: \"%s\".\n", extra_path);
}
}
extra_path = next;
}
/* Re-check verbosity settings */
check_verbosity_settings(conf, settings);
#ifdef HAVE_OVERLAY
config_get_path(conf, "input_overlay", new_overlay_path, sizeof(new_overlay_path));
if (!string_is_equal(old_overlay_path, new_overlay_path))
retroarch_override_setting_set(RARCH_OVERRIDE_SETTING_OVERLAY_PRESET, NULL);
#endif
}
/* Special case for perfcnt_enable */
{
bool tmp = false;
config_get_bool(conf, "perfcnt_enable", &tmp);
if (tmp)
retroarch_ctl(RARCH_CTL_SET_PERFCNT_ENABLE, NULL);
}
/* Overrides */
if (rarch_flags & RARCH_FLAGS_HAS_SET_USERNAME)
{
strlcpy(override_username, settings->paths.username, sizeof(override_username));
override_username_set = true;
}
/* Boolean settings */
for (i = 0; i < (unsigned)bool_settings_size; i++)
{
bool tmp = false;
if (config_get_bool(conf, bool_settings[i].ident, &tmp))
*bool_settings[i].ptr = tmp;
}
/* audio_threaded_pipeline briefly held off/automatic/on rather than
* a plain bool, and wrote that as a number. A bool is always saved
* as "true" or "false", so a numeric value here is that older
* three-way one: automatic (1) means the pipeline was never asked
* for and reads as the default, on (2) means it was. The value is
* rewritten in the settings, so the next save records it as a
* bool and this stops applying. */
{
const struct config_entry_list *entry =
(const struct config_entry_list*)config_get_entry(conf,
"audio_threaded_pipeline");
if (entry && entry->value[0] >= '0' && entry->value[0] <= '9'
&& entry->value[1] == '\0')
configuration_set_bool(settings,
settings->bools.audio_threaded_pipeline,
(entry->value[0] == '2'));
}
#ifdef HAVE_NETWORKGAMEPAD
{
char tmp[64];
size_t _len = strlcpy_lit(tmp, "network_remote_enable_user_p", sizeof(tmp));
for (i = 0; i < MAX_USERS; i++)
{
bool tmp_bool = false;
snprintf(tmp + _len, sizeof(tmp) - _len, "%u", i + 1);
if (config_get_bool(conf, tmp, &tmp_bool))
configuration_set_bool(settings,
settings->bools.network_remote_enable_user[i], tmp_bool);
}
}
#endif
/* Integer settings */
for (i = 0; i < (unsigned)int_settings_size; i++)
{
int tmp = 0;
if (config_get_int(conf, int_settings[i].ident, &tmp))
cfg_int_set(&int_settings[i], tmp);
}
for (i = 0; i < (unsigned)uint_settings_size; i++)
{
int tmp = 0;
if (config_get_int(conf, uint_settings[i].ident, &tmp))
cfg_uint_set(&uint_settings[i], (unsigned)tmp);
}
for (i = 0; i < (unsigned)size_settings_size; i++)
{
size_t tmp = 0;
if (config_get_size_t(conf, size_settings[i].ident, &tmp))
*size_settings[i].ptr = tmp;
/* Special case for rewind_buffer_size - need to convert
* low values to what they were
* intended to be based on the default value in config.def.h
* If the value is less than 10000 then multiple by 1MB because if
* the retroarch.cfg
* file contains rewind_buffer_size = "100",
* then that ultimately gets interpreted as
* 100MB, so ensure the internal values represent that.*/
if (string_is_equal(size_settings[i].ident, "rewind_buffer_size"))
if (*size_settings[i].ptr < 10000)
*size_settings[i].ptr = *size_settings[i].ptr * 1024 * 1024;
}
#ifdef HAVE_VIDEO_WINDOWS
config_load_video_windows(settings, conf);
#endif
{
char prefix[64];
size_t _len = strlcpy_lit(prefix, "input_player", sizeof(prefix));
size_t old_len = _len;
for (i = 0; i < MAX_USERS; i++)
{
_len = old_len;
_len += snprintf(prefix + _len, sizeof(prefix) - _len, "%u", i + 1);
strlcpy_lit(prefix + _len, "_mouse_index", sizeof(prefix) - _len);
CONFIG_GET_INT_BASE(conf, settings, uints.input_mouse_index[i], prefix);
strlcpy_lit(prefix + _len, "_keyboard_index", sizeof(prefix) - _len);
CONFIG_GET_INT_BASE(conf, settings, uints.input_keyboard_index[i], prefix);
strlcpy_lit(prefix + _len, "_aim_stick", sizeof(prefix) - _len);
CONFIG_GET_INT_BASE(conf, settings, uints.input_aim_stick[i], prefix);
if (settings->uints.input_aim_stick[i] >= INPUT_AIM_STICK_LAST)
settings->uints.input_aim_stick[i] = INPUT_AIM_STICK_NONE;
strlcpy_lit(prefix + _len, "_touchpad", sizeof(prefix) - _len);
CONFIG_GET_INT_BASE(conf, settings, uints.input_touchpad[i], prefix);
if (settings->uints.input_touchpad[i] >= INPUT_TOUCHPAD_LAST)
settings->uints.input_touchpad[i] = INPUT_TOUCHPAD_POINTER;
strlcpy_lit(prefix + _len, "_joypad_index", sizeof(prefix) - _len);
CONFIG_GET_INT_BASE(conf, settings, uints.input_joypad_index[i], prefix);
strlcpy_lit(prefix + _len, "_analog_dpad_mode", sizeof(prefix) - _len);
CONFIG_GET_INT_BASE(conf, settings, uints.input_analog_dpad_mode[i], prefix);
strlcpy_lit(prefix + _len, "_device_reservation_type", sizeof(prefix) - _len);
CONFIG_GET_INT_BASE(conf, settings, uints.input_device_reservation_type[i], prefix);
}
/* Nothing keeps 'input_playerN_joypad_index' in range in the
* file. Two players on one pad is allowed. */
input_config_sanitize_joypad_indices();
}
/* LED map for use by the led driver */
for (i = 0; i < MAX_LEDS; i++)
{
char buf[64];
buf[0] = '\0';
snprintf(buf, sizeof(buf), "led%u_map", i + 1);
/* TODO/FIXME - change of sign - led_map is unsigned */
settings->uints.led_map[i] = -1;
CONFIG_GET_INT_BASE(conf, settings, uints.led_map[i], buf);
}
/* Hexadecimal settings */
if (config_get_hex(conf, "video_message_color", &msg_color))
{
settings->floats.video_msg_color_r = ((msg_color >> 16) & 0xff) / 255.0f;
settings->floats.video_msg_color_g = ((msg_color >> 8) & 0xff) / 255.0f;
settings->floats.video_msg_color_b = ((msg_color >> 0) & 0xff) / 255.0f;
}
/* Float settings */
for (i = 0; i < (unsigned)float_settings_size; i++)
{
float tmp = 0.0f;
if (config_get_float(conf, float_settings[i].ident, &tmp))
*float_settings[i].ptr = tmp;
}
/* Array settings */
for (i = 0; i < (unsigned)array_settings_size; i++)
{
if (array_settings[i].flags & CFG_BOOL_FLG_HANDLE)
config_get_array(conf, array_settings[i].ident,
array_settings[i].ptr, PATH_MAX_LENGTH);
}
/* Path settings */
for (i = 0; i < (unsigned)path_settings_size; i++)
{
if (!(path_settings[i].flags & CFG_BOOL_FLG_HANDLE))
continue;
if (config_get_path(conf, path_settings[i].ident, tmp_str, sizeof(tmp_str)))
strlcpy(path_settings[i].ptr, tmp_str, PATH_MAX_LENGTH);
}
#if !TARGET_OS_IPHONE
if (config_get_path(conf, "libretro_directory", tmp_str, sizeof(tmp_str)))
configuration_set_string(settings,
settings->paths.directory_libretro, tmp_str);
#endif
/* Post-settings load */
libretro_directory = getenv("LIBRETRO_DIRECTORY");
if (libretro_directory)
{
configuration_set_string(settings,
settings->paths.directory_libretro, libretro_directory);
configuration_set_string(settings,
settings->paths.path_libretro_info, libretro_directory);
}
libretro_autoconfig_directory = getenv("LIBRETRO_AUTOCONFIG_DIRECTORY");
if (libretro_autoconfig_directory) /* override configuration value */
configuration_set_string(settings,
settings->paths.directory_autoconfig,
libretro_autoconfig_directory);
libretro_cheats_directory = getenv("LIBRETRO_CHEATS_DIRECTORY");
if (libretro_cheats_directory) /* override configuration value */
configuration_set_string(settings,
settings->paths.path_cheat_database,
libretro_cheats_directory);
libretro_database_directory = getenv("LIBRETRO_DATABASE_DIRECTORY");
if (libretro_database_directory) /* override configuration value */
configuration_set_string(settings,
settings->paths.path_content_database,
libretro_database_directory);
libretro_system_directory = getenv("LIBRETRO_SYSTEM_DIRECTORY");
if (libretro_system_directory) /* override configuration value */
configuration_set_string(settings,
settings->paths.directory_system,
libretro_system_directory);
if ( (rarch_flags & RARCH_FLAGS_HAS_SET_USERNAME)
&& override_username_set)
{
configuration_set_string(settings,
settings->paths.username,
override_username);
}
if (settings->uints.video_hard_sync_frames > MAXIMUM_HARD_SYNC_FRAMES)
settings->uints.video_hard_sync_frames = MAXIMUM_HARD_SYNC_FRAMES;
if (settings->uints.video_max_swapchain_images < MINIMUM_MAX_SWAPCHAIN_IMAGES)
settings->uints.video_max_swapchain_images = MINIMUM_MAX_SWAPCHAIN_IMAGES;
if (settings->uints.video_max_swapchain_images > MAXIMUM_MAX_SWAPCHAIN_IMAGES)
settings->uints.video_max_swapchain_images = MAXIMUM_MAX_SWAPCHAIN_IMAGES;
if (settings->uints.video_frame_delay > MAXIMUM_FRAME_DELAY)
settings->uints.video_frame_delay = MAXIMUM_FRAME_DELAY;
settings->uints.video_swap_interval = MAX(settings->uints.video_swap_interval, 0);
settings->uints.video_swap_interval = MIN(settings->uints.video_swap_interval, 4);
audio_set_float(AUDIO_ACTION_VOLUME_GAIN, settings->floats.audio_volume);
#ifdef HAVE_AUDIOMIXER
audio_set_float(AUDIO_ACTION_MIXER_VOLUME_GAIN, settings->floats.audio_mixer_volume);
#endif
audio_set_float(AUDIO_ACTION_RATE_CONTROL_DELTA, settings->floats.audio_rate_control_delta);
#ifdef HAVE_WASAPI
{
/* Migrate from old deprecated negative value */
int wasapi_sh_buffer_length = settings->uints.audio_wasapi_sh_buffer_length;
if (wasapi_sh_buffer_length < 0)
settings->uints.audio_wasapi_sh_buffer_length = 0;
}
#endif
#if defined(HAVE_BLUETOOTH) && defined(_WIN32)
/* "null" was the only Bluetooth driver a Windows build had, so a
* saved one was never chosen: Windows' own is the default now */
if (string_is_equal(settings->arrays.bluetooth_driver, "null"))
configuration_set_string(settings,
settings->arrays.bluetooth_driver,
config_get_default_bluetooth());
#endif
/* MIDI fallback for old OFF-string */
if (string_is_equal(settings->arrays.midi_input, "Off"))
configuration_set_string(settings,
settings->arrays.midi_input,
DEFAULT_MIDI_INPUT);
if (string_is_equal(settings->arrays.midi_output, "Off"))
configuration_set_string(settings,
settings->arrays.midi_output,
DEFAULT_MIDI_OUTPUT);
/* Built-in playlist default legacy path migration */
{
const char *path_config = path_get(RARCH_PATH_CONFIG);
char new_path[PATH_MAX_LENGTH];
fill_pathname_join_special(
new_path,
settings->paths.directory_playlist,
FILE_PATH_BUILTIN,
sizeof(new_path));
if ( !(retroarch_get_flags() & RARCH_FLAGS_USER_DIRS_HELD)
&& !path_is_directory(new_path))
path_mkdir(new_path);
if (!*settings->paths.path_content_favorites)
strlcpy_lit(settings->paths.directory_content_favorites, "default",
sizeof(settings->paths.directory_content_favorites));
if ( !*settings->paths.directory_content_favorites
|| string_is_equal(settings->paths.directory_content_favorites, "default"))
{
CONFIG_PLAYLIST_MIGRATION(settings->paths.path_content_favorites,
FILE_PATH_CONTENT_FAVORITES);
}
else
fill_pathname_join_special(
settings->paths.path_content_favorites,
settings->paths.directory_content_favorites,
FILE_PATH_CONTENT_FAVORITES,
sizeof(settings->paths.path_content_favorites));
if (!*settings->paths.path_content_history)
strlcpy_lit(settings->paths.directory_content_history, "default",
sizeof(settings->paths.directory_content_history));
if ( !*settings->paths.directory_content_history
|| string_is_equal(settings->paths.directory_content_history, "default"))
{
CONFIG_PLAYLIST_MIGRATION(settings->paths.path_content_history,
FILE_PATH_CONTENT_HISTORY);
}
else
fill_pathname_join_special(
settings->paths.path_content_history,
settings->paths.directory_content_history,
FILE_PATH_CONTENT_HISTORY,
sizeof(settings->paths.path_content_history));
if (!*settings->paths.path_content_image_history)
strlcpy_lit(settings->paths.directory_content_image_history, "default",
sizeof(settings->paths.directory_content_image_history));
if ( !*settings->paths.directory_content_image_history
|| string_is_equal(settings->paths.directory_content_image_history, "default"))
{
CONFIG_PLAYLIST_MIGRATION(settings->paths.path_content_image_history,
FILE_PATH_CONTENT_IMAGE_HISTORY);
}
else
fill_pathname_join_special(
settings->paths.path_content_image_history,
settings->paths.directory_content_image_history,
FILE_PATH_CONTENT_IMAGE_HISTORY,
sizeof(settings->paths.path_content_image_history));
if (*settings->paths.path_content_music_history)
strlcpy_lit(settings->paths.directory_content_music_history, "default",
sizeof(settings->paths.directory_content_music_history));
if ( !*settings->paths.directory_content_music_history
|| string_is_equal(settings->paths.directory_content_music_history, "default"))
{
CONFIG_PLAYLIST_MIGRATION(settings->paths.path_content_music_history,
FILE_PATH_CONTENT_MUSIC_HISTORY);
}
else
fill_pathname_join_special(
settings->paths.path_content_music_history,
settings->paths.directory_content_music_history,
FILE_PATH_CONTENT_MUSIC_HISTORY,
sizeof(settings->paths.path_content_music_history));
if (!*settings->paths.path_content_video_history)
strlcpy_lit(settings->paths.directory_content_video_history, "default",
sizeof(settings->paths.directory_content_video_history));
if ( !*settings->paths.directory_content_video_history
|| string_is_equal(settings->paths.directory_content_video_history, "default"))
{
CONFIG_PLAYLIST_MIGRATION(settings->paths.path_content_video_history,
FILE_PATH_CONTENT_VIDEO_HISTORY);
}
else
fill_pathname_join_special(
settings->paths.path_content_video_history,
settings->paths.directory_content_video_history,
FILE_PATH_CONTENT_VIDEO_HISTORY,
sizeof(settings->paths.path_content_video_history));
}
if (*settings->paths.directory_screenshot)
{
if (string_is_equal(settings->paths.directory_screenshot, "default"))
*settings->paths.directory_screenshot = '\0';
else if (!path_is_directory(settings->paths.directory_screenshot))
{
RARCH_WARN("[Config] \"screenshot_directory\" is not an existing directory, ignoring...\n");
*settings->paths.directory_screenshot = '\0';
}
}
#if defined(__APPLE__) && TARGET_OS_OSX
if ( ((frontend_driver_get_cpu_architecture() == FRONTEND_ARCH_X86_64) &&
string_ends_with(settings->paths.network_buildbot_url, "/arm64/latest/"))
|| ((frontend_driver_get_cpu_architecture() == FRONTEND_ARCH_ARMV8) &&
string_ends_with(settings->paths.network_buildbot_url, "/x86_64/latest/")))
/* Wrong architecture, set it back */
configuration_set_string(settings,
settings->paths.network_buildbot_url, DEFAULT_BUILDBOT_SERVER_URL);
#endif
if (string_is_equal(settings->paths.path_menu_wallpaper, "default"))
*settings->paths.path_menu_wallpaper = '\0';
if (string_is_equal(settings->paths.path_rgui_theme_preset, "default"))
*settings->paths.path_rgui_theme_preset = '\0';
libretro_video_shader_directory = getenv("LIBRETRO_VIDEO_SHADER_DIRECTORY");
if (libretro_video_shader_directory)
{
/* override configuration value */
configuration_set_string(settings, settings->paths.directory_video_shader,
libretro_video_shader_directory);
}
else if (string_is_equal(settings->paths.directory_video_shader, "default"))
*settings->paths.directory_video_shader = '\0';
libretro_video_filter_directory = getenv("LIBRETRO_VIDEO_FILTER_DIRECTORY");
if (libretro_video_filter_directory)
{
/* override configuration value */
configuration_set_string(settings,
settings->paths.directory_video_filter,
libretro_video_filter_directory);
}
else if (string_is_equal(settings->paths.directory_video_filter, "default"))
*settings->paths.directory_video_filter = '\0';
if (string_is_equal(settings->paths.directory_audio_filter, "default"))
*settings->paths.directory_audio_filter = '\0';
if (string_is_equal(settings->paths.directory_core_assets, "default"))
*settings->paths.directory_core_assets = '\0';
libretro_assets_directory = getenv("LIBRETRO_ASSETS_DIRECTORY");
if (libretro_assets_directory)
{
/* override configuration value */
configuration_set_string(settings,
settings->paths.directory_assets, libretro_assets_directory);
}
else if (string_is_equal(settings->paths.directory_assets, "default"))
*settings->paths.directory_assets = '\0';
#ifdef _3DS
if (string_is_equal(settings->paths.directory_bottom_assets, "default"))
configuration_set_string(settings,
settings->paths.directory_bottom_assets,
g_defaults.dirs[DEFAULT_DIR_BOTTOM_ASSETS]);
#endif
if (string_is_equal(settings->paths.directory_dynamic_wallpapers, "default"))
*settings->paths.directory_dynamic_wallpapers = '\0';
if (string_is_equal(settings->paths.directory_thumbnails, "default"))
*settings->paths.directory_thumbnails = '\0';
if (string_is_equal(settings->paths.directory_playlist, "default"))
*settings->paths.directory_playlist = '\0';
if (string_is_equal(settings->paths.directory_content_favorites, "default"))
*settings->paths.directory_content_favorites = '\0';
if (string_is_equal(settings->paths.directory_content_history, "default"))
*settings->paths.directory_content_history = '\0';
if (string_is_equal(settings->paths.directory_content_image_history, "default"))
*settings->paths.directory_content_image_history = '\0';
if (string_is_equal(settings->paths.directory_content_music_history, "default"))
*settings->paths.directory_content_music_history = '\0';
if (string_is_equal(settings->paths.directory_content_video_history, "default"))
*settings->paths.directory_content_video_history = '\0';
if (string_is_equal(settings->paths.directory_runtime_log, "default"))
*settings->paths.directory_runtime_log = '\0';
#ifdef HAVE_MENU
if (string_is_equal(settings->paths.directory_menu_content, "default"))
*settings->paths.directory_menu_content = '\0';
if (string_is_equal(settings->paths.directory_menu_config, "default"))
*settings->paths.directory_menu_config = '\0';
#endif
#ifdef HAVE_OVERLAY
if (string_is_equal(settings->paths.directory_overlay, "default"))
*settings->paths.directory_overlay = '\0';
if (string_is_equal(settings->paths.directory_osk_overlay, "default"))
*settings->paths.directory_osk_overlay = '\0';
#endif
if (string_is_equal(settings->paths.directory_system, "default"))
*settings->paths.directory_system = '\0';
/* Log directory is a special case, since it must contain
* a valid path as soon as possible - if config file
* value is 'default' must copy g_defaults.dirs[DEFAULT_DIR_LOGS]
* directly... */
if (string_is_equal(settings->paths.log_dir, "default"))
{
if (*g_defaults.dirs[DEFAULT_DIR_LOGS])
{
configuration_set_string(settings,
settings->paths.log_dir,
g_defaults.dirs[DEFAULT_DIR_LOGS]);
}
else
*settings->paths.log_dir = '\0';
}
if (settings->floats.slowmotion_ratio < 1.0f)
configuration_set_float(settings, settings->floats.slowmotion_ratio, 1.0f);
/* Sanitize fastforward_ratio value - previously range was -1
* and up (with 0 being skipped) */
if (settings->floats.fastforward_ratio < 0.0f)
configuration_set_float(settings, settings->floats.fastforward_ratio, 0.0f);
#ifdef HAVE_OZONE
/* Convert legacy numeric values of Ozone color themes to string identifiers.
* Necessary to avoid breaking existing configs. */
{
static const char *legacy_ozone_color_themes[] = {
"basic_white",
"basic_black",
"nord",
"gruvbox_dark",
"boysenberry",
"hacking_the_kernel",
"twilight_zone",
"dracula",
"solarized_dark",
"solarized_light",
"gray_dark",
"gray_light",
"purple_rain",
"selenium",
"evergarden"
};
unsigned color_theme;
config_get_array(conf, MENU_ENUM_LABEL_OZONE_MENU_COLOR_THEME_STR,
settings->arrays.menu_ozone_color_theme,
sizeof(settings->arrays.menu_ozone_color_theme));
if ( config_get_uint(conf, MENU_ENUM_LABEL_OZONE_MENU_COLOR_THEME_STR, &color_theme)
&& color_theme < ARRAY_SIZE(legacy_ozone_color_themes))
configuration_set_string(settings,
settings->arrays.menu_ozone_color_theme,
legacy_ozone_color_themes[color_theme]);
}
#endif
config_sanitize_turbo_binds(settings);
/* Menu Frame Rate took over from Throttle Menu Framerate, which
* only acted with Sync to Exact Content Framerate on, where its
* default held the menu to the content's rate. A configuration
* written before carries that choice; keep it. */
if ( settings->bools.vrr_runloop_enable
&& !config_get_entry(conf, MENU_ENUM_LABEL_MENU_FRAME_RATE_STR))
{
bool menu_throttle = true;
config_get_bool(conf, "menu_throttle_framerate", &menu_throttle);
if (menu_throttle)
configuration_set_uint(settings,
settings->uints.menu_frame_rate, MENU_FRAME_RATE_CONTENT);
}
#ifdef HAVE_CHEEVOS
if (*settings->arrays.cheevos_leaderboards_enable)
{
if (string_is_equal(settings->arrays.cheevos_leaderboards_enable, "true"))
{
settings->bools.cheevos_visibility_lboard_start = true;
settings->bools.cheevos_visibility_lboard_submit = true;
settings->bools.cheevos_visibility_lboard_cancel = true;
settings->bools.cheevos_visibility_lboard_trackers = true;
}
else if (string_is_equal(settings->arrays.cheevos_leaderboards_enable, "trackers"))
{
settings->bools.cheevos_visibility_lboard_start = false;
settings->bools.cheevos_visibility_lboard_submit = true;
settings->bools.cheevos_visibility_lboard_cancel = false;
settings->bools.cheevos_visibility_lboard_trackers = true;
}
else if (string_is_equal(settings->arrays.cheevos_leaderboards_enable, "notifications"))
{
settings->bools.cheevos_visibility_lboard_start = true;
settings->bools.cheevos_visibility_lboard_submit = true;
settings->bools.cheevos_visibility_lboard_cancel = true;
settings->bools.cheevos_visibility_lboard_trackers = false;
}
else
{
settings->bools.cheevos_visibility_lboard_start = false;
settings->bools.cheevos_visibility_lboard_submit = false;
settings->bools.cheevos_visibility_lboard_cancel = false;
settings->bools.cheevos_visibility_lboard_trackers = false;
}
settings->arrays.cheevos_leaderboards_enable[0] = '\0';
}
#endif
#ifdef HAVE_LAKKA
configuration_set_bool(settings,
settings->bools.ssh_enable, filestream_exists(LAKKA_SSH_PATH));
configuration_set_bool(settings,
settings->bools.samba_enable, !filestream_exists(LAKKA_SAMBA_DISABLED_FILE_PATH));
configuration_set_bool(settings,
settings->bools.bluetooth_enable, filestream_exists(LAKKA_BLUETOOTH_PATH));
#ifdef HAVE_RETROFLAG
configuration_set_bool(settings,
settings->bools.safeshutdown_enable, filestream_exists(LAKKA_SAFESHUTDOWN_PATH));
#endif
#endif
/* The "without-overrides" load (config_save_overrides) is a
* comparison-only pass to obtain the pre-override baseline; it must
* not mutate runtime directory state. Without this guard, saving an
* override would reset the live save directory to the base config
* value (issue #18809). */
if ( !without_overrides
&& !retroarch_override_setting_is_set(RARCH_OVERRIDE_SETTING_SAVE_PATH, NULL)
&& config_get_path(conf, "savefile_directory", tmp_str, sizeof(tmp_str)))
{
if (string_is_equal(tmp_str, "default"))
dir_set(RARCH_DIR_SAVEFILE, g_defaults.dirs[DEFAULT_DIR_SRAM]);
else if (path_is_directory(tmp_str))
{
dir_set(RARCH_DIR_SAVEFILE, tmp_str);
strlcpy(runloop_st->name.savefile, tmp_str,
sizeof(runloop_st->name.savefile));
fill_pathname_dir(runloop_st->name.savefile,
path_get(RARCH_PATH_BASENAME),
FILE_PATH_SRM_EXTENSION,
sizeof(runloop_st->name.savefile));
}
else
RARCH_WARN("[Config] \"savefile_directory\" is not a directory, ignoring...\n");
}
if ( !without_overrides
&& !retroarch_override_setting_is_set(RARCH_OVERRIDE_SETTING_STATE_PATH, NULL)
&& config_get_path(conf, "savestate_directory", tmp_str, sizeof(tmp_str)))
{
if (string_is_equal(tmp_str, "default"))
dir_set(RARCH_DIR_SAVESTATE, g_defaults.dirs[DEFAULT_DIR_SAVESTATE]);
else if (path_is_directory(tmp_str))
{
dir_set(RARCH_DIR_SAVESTATE, tmp_str);
strlcpy(runloop_st->name.savestate, tmp_str,
sizeof(runloop_st->name.savestate));
fill_pathname_dir(runloop_st->name.savestate,
path_get(RARCH_PATH_BASENAME),
".state",
sizeof(runloop_st->name.savestate));
strlcpy(runloop_st->name.replay, tmp_str,
sizeof(runloop_st->name.replay));
fill_pathname_dir(runloop_st->name.replay,
path_get(RARCH_PATH_BASENAME),
".replay",
sizeof(runloop_st->name.replay));
}
else
RARCH_WARN("[Config] \"savestate_directory\" is not a directory, ignoring...\n");
}
config_read_keybinds_conf(conf);
/* the binds, and the device settings read above */
input_config_binds_changed();
#if defined(HAVE_MENU) && defined(HAVE_RGUI)
if (!check_menu_driver_compatibility(settings))
configuration_set_string(settings,
settings->arrays.menu_driver, "rgui");
#endif
#ifdef HAVE_LIBNX
/* Apply initial clocks */
{
extern void libnx_apply_overclock(void);
libnx_apply_overclock();
}
#endif
#ifdef HAVE_LAKKA_SWITCH
{
FILE* f = fopen(SWITCH_OC_TOGGLE_PATH, "w");
if (settings->bools.switch_oc)
fprintf(f, "1\n");
else
fprintf(f, "0\n");
fclose(f);
if (settings->bools.switch_cec)
{
FILE* f = fopen(SWITCH_CEC_TOGGLE_PATH, "w");
fprintf(f, "\n");
fclose(f);
}
else
filestream_delete(SWITCH_CEC_TOGGLE_PATH);
if (settings->bools.bluetooth_ertm_disable)
{
FILE* f = fopen(BLUETOOTH_ERTM_TOGGLE_PATH, "w");
fprintf(f, "1\n");
fclose(f);
}
else
{
FILE* f = fopen(BLUETOOTH_ERTM_TOGGLE_PATH, "w");
fprintf(f, "0\n");
fclose(f);
}
}
#endif
frontend_driver_set_sustained_performance_mode(settings->bools.sustained_performance_mode);
#if defined(_WIN32) && !defined(_XBOX) && !defined(__WINRT__)
/* Also undoes a plan left active by a run that did not exit cleanly. */
if ( !frontend_driver_set_power_plan(settings->bools.win32_power_plan,
settings->bools.win32_power_plan_idle_disable)
&& settings->bools.win32_power_plan_idle_disable)
frontend_driver_set_power_plan(settings->bools.win32_power_plan, false);
#endif
#ifdef HAVE_COMPRESSION
rzipstream_set_write_codec(settings->uints.save_compression_codec == 1
? RZIP_CODEC_ZSTD : RZIP_CODEC_DEFLATE);
#endif
#ifdef ANDROID
android_app_set_window_settings(
settings->bools.video_notch_write_over_enable,
settings->bools.input_auto_mouse_grab);
#endif
recording_driver_update_streaming_url();
if (!config_get_entry(conf, "user_language"))
msg_hash_set_uint(MSG_HASH_USER_LANGUAGE, frontend_driver_get_user_language());
/* If GameMode is enabled in the config but libgamemode is not
* available, warn once. Do NOT clear the setting: that would
* silently overwrite the user's preference in retroarch.cfg, so
* a transient failure (sandbox path issue, library not yet
* installed, etc.) would force them to re-enable it manually on
* every subsequent launch. The probe is latched inside the
* frontend driver, so it will not be retried this session. */
if ( settings->bools.gamemode_enable
&& frontend_driver_has_gamemode())
frontend_driver_set_gamemode(true);
/* If this is the first run of an existing installation
* after the independent favourites playlist size limit was
* added, set the favourites limit according to the current
* history playlist size limit. (Have to do this, otherwise
* users with large custom history size limits may lose
* favourites entries when updating RetroArch...) */
if ( config_get_entry(conf, "content_history_size")
&& !config_get_entry(conf, "content_favorites_size"))
{
if (settings->uints.content_history_size > 999)
settings->ints.content_favorites_size = -1;
else
settings->ints.content_favorites_size = (int)settings->uints.content_history_size;
}
/* Migrate "quit_press_twice" to "confirm_quit" */
{
const char *tmp_key = "quit_press_twice";
struct config_entry_list *tmp = config_get_entry(conf, tmp_key);
if (tmp)
{
configuration_set_bool(settings,
settings->bools.confirm_quit,
string_is_equal(tmp->value, "true") ? true : false);
RARCH_LOG("[Config] Migrated \"%s\" to \"confirm_quit\" = \"%s\".\n",
tmp->key, tmp->value);
}
}
#ifdef HAVE_SSL
/* Every load of the live settings comes through here: startup, a
* per-core or per-game override, and its unload. Hand the TLS
* verification mode to the SSL backend each time, so an override
* that changes it applies now, not after a restart. Only for the
* live settings: config_save_overrides() loads the base config into
* a scratch copy to diff against, and its mode must not reach the
* backend while the override's stays on screen. */
if (settings == config_st)
ssl_socket_set_verify_mode(settings->uints.tls_verify_mode);
#endif
if (conf)
config_file_free(conf);
if (bool_settings)
free(bool_settings);
if (int_settings)
free(int_settings);
if (uint_settings)
free(uint_settings);
if (float_settings)
free(float_settings);
if (array_settings)
free(array_settings);
if (path_settings)
free(path_settings);
if (size_settings)
free(size_settings);
first_load = false;
/* each port's deadzones, from the settings now loaded */
input_driver_deadzones_refresh();
return true;
}
/**
* config_load_override:
*
* Tries to append game-specific and core-specific configuration.
* These settings will always have precedence, thus this feature
* can be used to enforce overrides.
*
* This function only has an effect if a game-specific or core-specific
* configuration file exists at respective locations.
*
* core-specific: $CONFIG_DIR/$CORE_NAME/$CORE_NAME.cfg
* fallback: $CURRENT_CFG_LOCATION/$CORE_NAME/$CORE_NAME.cfg
*
* game-specific: $CONFIG_DIR/$CORE_NAME/$ROM_NAME.cfg
* fallback: $CURRENT_CFG_LOCATION/$CORE_NAME/$GAME_NAME.cfg
*
* Returns: false if there was an error or no action was performed.
*
*/
bool config_load_override(void *data)
{
const char *a = NULL;
char core_path[PATH_MAX_LENGTH];
char game_path[PATH_MAX_LENGTH];
char content_path[PATH_MAX_LENGTH];
char config_directory[DIR_MAX_LENGTH];
bool should_append = false;
rarch_system_info_t *sys_info = (rarch_system_info_t*)data;
const char *core_name = sys_info
? sys_info->info.library_name : NULL;
const char *rarch_path_basename = path_get(RARCH_PATH_BASENAME);
const char *game_name = NULL;
settings_t *settings = config_st;
bool has_content = (rarch_path_basename && *rarch_path_basename);
core_path[0] = '\0';
game_path[0] = '\0';
content_path[0] = '\0';
config_directory[0] = '\0';
path_clear(RARCH_PATH_CONFIG_OVERRIDE);
/* Cannot load an override if we have no core */
if (!core_name || !*core_name)
return false;
/* Get base config directory */
fill_pathname_application_special(config_directory,
sizeof(config_directory),
APPLICATION_SPECIAL_DIRECTORY_CONFIG);
/* Concatenate strings into full paths for core_path,
* game_path, content_path */
if (has_content)
{
char content_dir_name[DIR_MAX_LENGTH];
fill_pathname_parent_dir_name(content_dir_name,
rarch_path_basename, sizeof(content_dir_name));
game_name = path_basename_nocompression(rarch_path_basename);
fill_pathname_join_special_ext(game_path,
config_directory, core_name,
game_name,
".cfg",
sizeof(game_path));
fill_pathname_join_special_ext(content_path,
config_directory, core_name,
content_dir_name,
".cfg",
sizeof(content_path));
}
fill_pathname_join_special_ext(core_path,
config_directory, core_name,
core_name,
".cfg",
sizeof(core_path));
/* Prevent "--appendconfig" from being ignored */
if (!path_is_empty(RARCH_PATH_CONFIG_APPEND))
should_append = true;
/* per-core overrides */
/* Create a new config file from core_path */
if (path_is_valid(core_path))
{
const char *a = path_get(RARCH_PATH_CONFIG_OVERRIDE);
RARCH_LOG("[Override] Core-specific overrides found at \"%s\".\n",
core_path);
if (should_append && a && *a)
{
char tmp_path[PATH_MAX_LENGTH];
size_t _len = strlcpy(tmp_path, a, sizeof(tmp_path) - 2);
tmp_path[ _len] = '|';
tmp_path[++_len] = '\0';
strlcpy(tmp_path + _len, core_path, sizeof(tmp_path) - _len);
path_set(RARCH_PATH_CONFIG_OVERRIDE, tmp_path);
RARCH_LOG("[Override] Core-specific overrides stacking on top of previous overrides.\n");
}
else
path_set(RARCH_PATH_CONFIG_OVERRIDE, core_path);
should_append = true;
}
if (has_content)
{
/* per-content-dir overrides */
/* Create a new config file from content_path */
if (path_is_valid(content_path))
{
const char *a = path_get(RARCH_PATH_CONFIG_OVERRIDE);
RARCH_LOG("[Override] Content dir-specific overrides found at \"%s\".\n",
content_path);
if (should_append && a && *a)
{
char tmp_path[PATH_MAX_LENGTH];
size_t _len = strlcpy(tmp_path, a, sizeof(tmp_path) - 2);
tmp_path[ _len] = '|';
tmp_path[++_len] = '\0';
strlcpy(tmp_path + _len, content_path, sizeof(tmp_path) - _len);
path_set(RARCH_PATH_CONFIG_OVERRIDE, tmp_path);
RARCH_LOG("[Override] Content dir-specific overrides stacking on top of previous overrides.\n");
}
else
path_set(RARCH_PATH_CONFIG_OVERRIDE, content_path);
should_append = true;
}
/* per-game overrides */
/* Create a new config file from game_path */
if (path_is_valid(game_path))
{
const char *a = path_get(RARCH_PATH_CONFIG_OVERRIDE);
RARCH_LOG("[Override] Game-specific overrides found at \"%s\".\n",
game_path);
if (should_append && a && *a)
{
char tmp_path[PATH_MAX_LENGTH];
size_t _len = strlcpy(tmp_path, a, sizeof(tmp_path) - 2);
tmp_path[ _len] = '|';
tmp_path[++_len] = '\0';
strlcpy(tmp_path + _len, game_path, sizeof(tmp_path) - _len);
path_set(RARCH_PATH_CONFIG_OVERRIDE, tmp_path);
RARCH_LOG("[Override] Game-specific overrides stacking on top of previous overrides.\n");
}
else
path_set(RARCH_PATH_CONFIG_OVERRIDE, game_path);
should_append = true;
}
}
if (!should_append)
return false;
/* Re-load the configuration with any overrides
* that might have been found */
/* Toggle has_save_path to false so it resets */
retroarch_override_setting_unset(RARCH_OVERRIDE_SETTING_STATE_PATH, NULL);
retroarch_override_setting_unset(RARCH_OVERRIDE_SETTING_SAVE_PATH, NULL);
if (!config_load_file(path_get(RARCH_PATH_CONFIG), settings))
return false;
a = path_get(RARCH_PATH_CONFIG_OVERRIDE);
if ( settings->bools.notification_show_config_override_load
&& a && *a)
{
char msg[128];
size_t _len = strlcpy(msg, msg_hash_to_str(MSG_CONFIG_OVERRIDE_LOADED), sizeof(msg));
runloop_msg_queue_push(msg, _len, 2, 100, false, NULL,
MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
}
/* Reset save paths. */
retroarch_override_setting_set(RARCH_OVERRIDE_SETTING_STATE_PATH, NULL);
retroarch_override_setting_set(RARCH_OVERRIDE_SETTING_SAVE_PATH, NULL);
a = path_get(RARCH_PATH_CONFIG_OVERRIDE);
if (a && *a)
runloop_state_get_ptr()->flags |= RUNLOOP_FLAG_OVERRIDES_ACTIVE;
else
runloop_state_get_ptr()->flags &= ~RUNLOOP_FLAG_OVERRIDES_ACTIVE;
/* each port's deadzones, from the override's settings */
input_driver_deadzones_refresh();
return true;
}
bool config_load_override_file(const char *config_path)
{
const char *a = NULL;
settings_t *settings = config_st;
path_clear(RARCH_PATH_CONFIG_OVERRIDE);
if (!path_is_valid(config_path))
return false;
path_set(RARCH_PATH_CONFIG_OVERRIDE, config_path);
/* Re-load the configuration with any overrides
* that might have been found */
/* Toggle has_save_path to false so it resets */
retroarch_override_setting_unset(RARCH_OVERRIDE_SETTING_STATE_PATH, NULL);
retroarch_override_setting_unset(RARCH_OVERRIDE_SETTING_SAVE_PATH, NULL);
if (!config_load_file(path_get(RARCH_PATH_CONFIG), settings))
return false;
if (settings->bools.notification_show_config_override_load)
{
char msg[128];
size_t _len = strlcpy(msg, msg_hash_to_str(MSG_CONFIG_OVERRIDE_LOADED), sizeof(msg));
runloop_msg_queue_push(msg, _len, 2, 100, false, NULL,
MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
}
/* Reset save paths. */
retroarch_override_setting_set(RARCH_OVERRIDE_SETTING_STATE_PATH, NULL);
retroarch_override_setting_set(RARCH_OVERRIDE_SETTING_SAVE_PATH, NULL);
a = path_get(RARCH_PATH_CONFIG_OVERRIDE);
if (a && *a)
runloop_state_get_ptr()->flags |= RUNLOOP_FLAG_OVERRIDES_ACTIVE;
else
runloop_state_get_ptr()->flags &= ~RUNLOOP_FLAG_OVERRIDES_ACTIVE;
/* each port's deadzones, from the override's settings */
input_driver_deadzones_refresh();
return true;
}
/**
* config_unload_override:
*
* Unloads configuration overrides if overrides are active.
*
*
* Returns: false if there was an error.
*/
bool config_unload_override(void)
{
settings_t *settings = config_st;
runloop_state_t *runloop_st = runloop_state_get_ptr();
bool fullscreen_prev = settings->bools.video_fullscreen;
runloop_st->flags &= ~RUNLOOP_FLAG_OVERRIDES_ACTIVE;
path_clear(RARCH_PATH_CONFIG_OVERRIDE);
/* Toggle has_save_path to false so it resets */
retroarch_override_setting_unset(RARCH_OVERRIDE_SETTING_STATE_PATH, NULL);
retroarch_override_setting_unset(RARCH_OVERRIDE_SETTING_SAVE_PATH, NULL);
/* When using minimal config, reset to defaults first.
* This ensures settings not present in the config file
* get their default values restored after override unload. */
/* The connected controllers stay as they are: putting the settings
* back to their defaults does not forget them, so there is nothing
* of theirs to copy aside and put back around it. */
if (settings->bools.config_save_minimal)
config_set_defaults(config_st);
if (!config_load_file(
path_get(RARCH_PATH_CONFIG), config_st))
return false;
if (settings->bools.video_fullscreen != fullscreen_prev)
{
/* This is for 'win32_common.c', so we don't save
* fullscreen size and position if we're switching
* back to windowed mode.
* Might be useful for other devices as well? */
if ( settings->bools.video_window_save_positions
&& !settings->bools.video_fullscreen)
settings->flags |= SETTINGS_FLG_SKIP_WINDOW_POSITIONS;
if (runloop_st->flags & RUNLOOP_FLAG_CORE_RUNNING)
command_event(CMD_EVENT_REINIT, NULL);
}
/* Turbo fire settings must be reloaded from remap */
if (settings->bools.auto_remaps_enable)
config_load_remap(settings->paths.directory_input_remapping, &runloop_st->system);
RARCH_LOG("[Override] Configuration overrides unloaded, original configuration restored.\n");
/* Reset save paths */
retroarch_override_setting_set(RARCH_OVERRIDE_SETTING_STATE_PATH, NULL);
retroarch_override_setting_set(RARCH_OVERRIDE_SETTING_SAVE_PATH, NULL);
/* each port's deadzones, from the settings put back */
input_driver_deadzones_refresh();
return true;
}
/**
* config_load_remap:
*
* Tries to append game-specific and core-specific remap files.
*
* This function only has an effect if a game-specific or core-specific
* configuration file exists at respective locations.
*
* core-specific: $REMAP_DIR/$CORE_NAME/$CORE_NAME.cfg
* game-specific: $REMAP_DIR/$CORE_NAME/$GAME_NAME.cfg
*
* Returns: false if there was an error or no action was performed.
*/
bool config_load_remap(const char *directory_input_remapping,
void *data)
{
/* final path for core-specific configuration (prefix+suffix) */
char core_path[PATH_MAX_LENGTH];
/* final path for game-specific configuration (prefix+suffix) */
char game_path[PATH_MAX_LENGTH];
/* final path for content-dir-specific configuration (prefix+suffix) */
char content_path[PATH_MAX_LENGTH];
char remap_path[PATH_MAX_LENGTH];
config_file_t *new_conf = NULL;
rarch_system_info_t *sys_info = (rarch_system_info_t*)data;
const char *core_name = sys_info ? sys_info->info.library_name : NULL;
const char *rarch_path_basename = path_get(RARCH_PATH_BASENAME);
enum msg_hash_enums msg_remap_loaded = MSG_GAME_REMAP_FILE_LOADED;
settings_t *settings = config_st;
unsigned joypad_port = settings->uints.input_joypad_index[0];
bool notification_show_remap_load = settings->bools.notification_show_remap_load;
bool sort_remaps_by_controller = settings->bools.input_remap_sort_by_controller_enable;
/* > Cannot load remaps if we have no core
* > Cannot load remaps if remap directory is unset */
if ( (!core_name || !*core_name)
|| (!directory_input_remapping || !*directory_input_remapping))
return false;
core_path[0] = '\0';
game_path[0] = '\0';
content_path[0] = '\0';
strlcpy(remap_path, core_name, sizeof(remap_path));
if (sort_remaps_by_controller)
{
const char *input_device_name = input_config_get_device_display_name(joypad_port);
if (input_device_name && *input_device_name)
{
/* Ensure directory does not contain special chars */
const char *input_device_dir = sanitize_path_part(input_device_name, strlen(input_device_name));
fill_pathname_join_special(remap_path, core_name, input_device_dir, sizeof(remap_path));
}
}
if (rarch_path_basename && *rarch_path_basename)
{
char content_dir_name[DIR_MAX_LENGTH];
fill_pathname_join_special_ext(game_path,
directory_input_remapping, remap_path,
path_basename_nocompression(rarch_path_basename),
FILE_PATH_REMAP_EXTENSION,
sizeof(game_path));
/* If a game remap file exists, load it. */
if ((new_conf = config_file_new_from_path_to_string(game_path)))
{
bool ret = input_remapping_load_file(new_conf, game_path);
config_file_free(new_conf);
new_conf = NULL;
RARCH_LOG("[Remap] Game-specific remap found at \"%s\".\n", game_path);
if (ret)
{
retroarch_ctl(RARCH_CTL_SET_REMAPS_GAME_ACTIVE, NULL);
/* msg_remap_loaded is set to MSG_GAME_REMAP_FILE_LOADED
* by default - no need to change it here */
goto success;
}
}
fill_pathname_parent_dir_name(content_dir_name,
rarch_path_basename, sizeof(content_dir_name));
fill_pathname_join_special_ext(content_path,
directory_input_remapping, remap_path,
content_dir_name,
FILE_PATH_REMAP_EXTENSION,
sizeof(content_path));
/* If a content-dir remap file exists, load it. */
if ((new_conf = config_file_new_from_path_to_string(content_path)))
{
bool ret = input_remapping_load_file(new_conf, content_path);
config_file_free(new_conf);
new_conf = NULL;
RARCH_LOG("[Remap] Content-dir-specific remap found at \"%s\".\n", content_path);
if (ret)
{
retroarch_ctl(RARCH_CTL_SET_REMAPS_CONTENT_DIR_ACTIVE, NULL);
msg_remap_loaded = MSG_DIRECTORY_REMAP_FILE_LOADED;
goto success;
}
}
}
fill_pathname_join_special_ext(core_path,
directory_input_remapping, remap_path,
core_name,
FILE_PATH_REMAP_EXTENSION,
sizeof(core_path));
/* If a core remap file exists, load it. */
if ((new_conf = config_file_new_from_path_to_string(core_path)))
{
bool ret = input_remapping_load_file(new_conf, core_path);
config_file_free(new_conf);
new_conf = NULL;
RARCH_LOG("[Remap] Core-specific remap found at \"%s\".\n", core_path);
if (ret)
{
retroarch_ctl(RARCH_CTL_SET_REMAPS_CORE_ACTIVE, NULL);
msg_remap_loaded = MSG_CORE_REMAP_FILE_LOADED;
goto success;
}
}
if (new_conf)
config_file_free(new_conf);
new_conf = NULL;
return false;
success:
if (notification_show_remap_load)
{
char msg[128];
size_t _len = strlcpy(msg, msg_hash_to_str(msg_remap_loaded), sizeof(msg));
runloop_msg_queue_push(msg, _len, 2, 100, false, NULL,
MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
}
return true;
}
/**
* config_parse_file:
*
* Loads a config file and reads all the values into memory.
*
*/
static void config_parse_file(void)
{
const char *config_path = path_get(RARCH_PATH_CONFIG);
#ifdef __PS3__
char imported_path[PATH_MAX_LENGTH];
if ( config_path && *config_path
&& !string_is_equal(config_path, g_defaults.path_config))
{
if (!ps3_config_import(config_path, imported_path, sizeof(imported_path)))
{
RARCH_ERR("[Config] Failed to import configuration: %s\n", config_path);
path_set(RARCH_PATH_CONFIG, g_defaults.path_config);
}
else
path_set(RARCH_PATH_CONFIG, imported_path);
config_path = path_get(RARCH_PATH_CONFIG);
}
#endif
if (!config_load_file(config_path, config_st))
{
RARCH_ERR("[Config] Config not found at: \"%s\".\n",
config_path);
}
}
static void save_keybind_hat(config_file_t *conf, const char *key,
const struct retro_keybind *bind)
{
size_t _len;
char s[16];
s[0] = '\0';
_len = snprintf(s, sizeof(s), "h%u", GET_HAT(bind->joykey));
switch (GET_HAT_DIR(bind->joykey))
{
case HAT_UP_MASK:
strlcpy_lit(s + _len, "up", sizeof(s) - _len);
break;
case HAT_DOWN_MASK:
strlcpy_lit(s + _len, "down", sizeof(s) - _len);
break;
case HAT_LEFT_MASK:
strlcpy_lit(s + _len, "left", sizeof(s) - _len);
break;
case HAT_RIGHT_MASK:
strlcpy_lit(s + _len, "right", sizeof(s) - _len);
break;
default:
break;
}
config_set_string(conf, key, s);
}
static void save_keybind_joykey(config_file_t *conf,
const char *prefix,
const char *base,
const struct retro_keybind *bind,
bool save_empty)
{
char key[64];
size_t _len = fill_pathname_join_delim(key, prefix,
base, '_', sizeof(key));
strlcpy_lit(key + _len, "_btn", sizeof(key) - _len);
if (bind->joykey == NO_BTN)
{
if (save_empty)
config_set_string(conf, key, "nul");
}
else if (GET_HAT_DIR(bind->joykey))
save_keybind_hat(conf, key, bind);
else
config_set_uint64(conf, key, bind->joykey);
}
static void save_keybind_joykey_label(config_file_t *conf,
const char *prefix,
const char *base,
const struct input_bind_label *label)
{
char key[64];
size_t _len = fill_pathname_join_delim(key, prefix,
base, '_', sizeof(key));
_len += strlcpy_lit(key + _len, "_btn", sizeof(key) - _len);
if (label->joykey && *label->joykey)
{
strlcpy_lit(key + _len, "_label", sizeof(key) - _len);
config_set_string(conf, key, label->joykey);
}
}
static void save_keybind_axis(config_file_t *conf,
const char *prefix,
const char *base,
const struct retro_keybind *bind,
bool save_empty)
{
char key[64];
char config[16];
size_t _len = fill_pathname_join_delim(key, prefix, base, '_', sizeof(key));
strlcpy_lit(key + _len, "_axis", sizeof(key) - _len);
if (bind->joyaxis == AXIS_NONE)
{
if (save_empty)
config_set_string(conf, key, "nul");
return;
}
if (AXIS_NEG_GET(bind->joyaxis) != AXIS_DIR_NONE)
{
snprintf(config, sizeof(config), "-%lu",
(unsigned long)AXIS_NEG_GET(bind->joyaxis));
}
else if (AXIS_POS_GET(bind->joyaxis) != AXIS_DIR_NONE)
{
snprintf(config, sizeof(config), "+%lu",
(unsigned long)AXIS_POS_GET(bind->joyaxis));
}
config_set_string(conf, key, config);
}
static void save_keybind_axis_label(config_file_t *conf,
const char *prefix,
const char *base,
const struct input_bind_label *label)
{
char key[64];
size_t _len = fill_pathname_join_delim(key, prefix, base, '_', sizeof(key));
_len += strlcpy_lit(key + _len, "_axis", sizeof(key) - _len);
if (label->joyaxis && *label->joyaxis)
{
strlcpy_lit(key + _len, "_label", sizeof(key) - _len);
config_set_string(conf, key, label->joyaxis);
}
}
static void save_keybind_mbutton(config_file_t *conf,
const char *prefix,
const char *base,
const struct retro_keybind *bind, bool save_empty)
{
char key[64];
size_t _len = fill_pathname_join_delim(key, prefix,
base, '_', sizeof(key));
strlcpy_lit(key + _len, "_mbtn", sizeof(key) - _len);
switch (RETRO_KEYBIND_MBUTTON(bind))
{
case RETRO_DEVICE_ID_MOUSE_LEFT:
config_set_uint64(conf, key, 1);
break;
case RETRO_DEVICE_ID_MOUSE_RIGHT:
config_set_uint64(conf, key, 2);
break;
case RETRO_DEVICE_ID_MOUSE_MIDDLE:
config_set_uint64(conf, key, 3);
break;
case RETRO_DEVICE_ID_MOUSE_BUTTON_4:
config_set_uint64(conf, key, 4);
break;
case RETRO_DEVICE_ID_MOUSE_BUTTON_5:
config_set_uint64(conf, key, 5);
break;
case RETRO_DEVICE_ID_MOUSE_WHEELUP:
config_set_string(conf, key, "wu");
break;
case RETRO_DEVICE_ID_MOUSE_WHEELDOWN:
config_set_string(conf, key, "wd");
break;
case RETRO_DEVICE_ID_MOUSE_HORIZ_WHEELUP:
config_set_string(conf, key, "whu");
break;
case RETRO_DEVICE_ID_MOUSE_HORIZ_WHEELDOWN:
config_set_string(conf, key, "whd");
break;
default:
if (save_empty)
config_set_string(conf, key, "nul");
break;
}
}
void input_config_get_prefix(char *s, char len, char user, bool meta)
{
if (meta)
{
/* Meta binds are only for the first user. */
if (user == 0)
strlcpy_lit(s, "input", len);
}
else
snprintf(s, len, "input_player%u", user + 1);
}
/**
* input_config_save_keybinds_user:
* @conf : pointer to config file object
* @user : user number
*
* Save the current keybinds of a user (@user) to the config file (@conf).
*/
static void input_config_save_keybinds_user(config_file_t *conf, unsigned user)
{
unsigned i;
for (i = 0; input_config_bind_map_get_valid(i); i++)
{
char key[64];
char btn[64];
char prefix[16];
const struct input_bind_map *keybind =
(const struct input_bind_map*)INPUT_CONFIG_BIND_MAP_GET(i);
bool meta = keybind ? keybind->meta : false;
const struct retro_keybind *bind = input_config_bind(user, i);
const char *base = NULL;
prefix[0] = '\0';
input_config_get_prefix(prefix, sizeof(prefix), user, meta);
if (!*prefix || !RETRO_KEYBIND_VALID(bind) || !keybind)
continue;
base = keybind->base;
btn[0] = '\0';
fill_pathname_join_delim(key, prefix, base, '_', sizeof(key));
input_keymaps_translate_rk_to_str(RETRO_KEYBIND_KEY(bind), btn, sizeof(btn));
config_set_string(conf, key, btn);
save_keybind_joykey (conf, prefix, base, bind, true);
save_keybind_axis (conf, prefix, base, bind, true);
save_keybind_mbutton(conf, prefix, base, bind, true);
}
}
/**
* input_config_save_keybinds_user_override:
* @conf : pointer to config file object
* @user : user number
* @bind_id : bind number
* @override_bind : override retro_keybind for comparison and saving
*
* Save the current bind (@override_bind) override of a user (@user) to the
* config file (@conf), and skip binds that are not modified.
*/
static void input_config_save_keybinds_user_override(config_file_t *conf,
unsigned user, unsigned bind_id,
const struct retro_keybind *override_bind)
{
unsigned i = bind_id;
if (input_config_bind_map_get_valid(i))
{
char key[64];
char btn[64];
char prefix[16];
const struct input_bind_map *keybind =
(const struct input_bind_map*)INPUT_CONFIG_BIND_MAP_GET(i);
bool meta = keybind ? keybind->meta : false;
const struct retro_keybind *bind = input_config_bind(user, i);
const char *base = NULL;
prefix[0] = '\0';
input_config_get_prefix(prefix, sizeof(prefix), user, meta);
if (!*prefix || !RETRO_KEYBIND_VALID(bind) || !keybind)
return;
base = keybind->base;
btn[0] = '\0';
fill_pathname_join_delim(key, prefix, base, '_', sizeof(key));
input_keymaps_translate_rk_to_str(RETRO_KEYBIND_KEY(override_bind), btn, sizeof(btn));
config_set_string(conf, key, btn);
if (bind->joykey != override_bind->joykey)
save_keybind_joykey (conf, prefix, base, override_bind, true);
if (bind->joyaxis != override_bind->joyaxis)
save_keybind_axis (conf, prefix, base, override_bind, true);
if (RETRO_KEYBIND_MBUTTON(bind) != RETRO_KEYBIND_MBUTTON(override_bind))
save_keybind_mbutton(conf, prefix, base, override_bind, true);
RARCH_DBG("[Override] %s = \"%s\"\n", key, btn);
}
}
/**
* input_config_save_keybinds_user_minimal:
* @conf : pointer to config file object
* @user : user number
*
*
* Save the current keybinds of a user (@user) to the config file (@conf),
* but only save binds that differ from defaults. Remove binds that match defaults.
*/
static void input_config_save_keybinds_user_minimal(config_file_t *conf,
unsigned user)
{
unsigned i;
for (i = 0; input_config_bind_map_get_valid(i); i++)
{
char key[64];
char btn[64];
char prefix[16];
const struct input_bind_map *keybind =
(const struct input_bind_map*)INPUT_CONFIG_BIND_MAP_GET(i);
bool meta = keybind ? keybind->meta : false;
const struct retro_keybind *bind = input_config_bind(user, i);
/* the bind's default, made from its definition as a reset makes
* it: no copy of every user's binds with the defaults loaded */
struct retro_keybind def_bind_made;
const struct retro_keybind *def_bind = &def_bind_made;
const char *base = NULL;
bool differs_from_default = false;
prefix[0] = '\0';
input_config_get_prefix(prefix, sizeof(prefix), user, meta);
if (!*prefix || !RETRO_KEYBIND_VALID(bind) || !keybind)
continue;
input_config_bind_from_def(&def_bind_made,
input_config_bind_def(user, i));
base = keybind->base;
btn[0] = '\0';
/* Check if any component differs from default */
differs_from_default = (RETRO_KEYBIND_KEY(bind) != RETRO_KEYBIND_KEY(def_bind))
|| (bind->joykey != def_bind->joykey)
|| (bind->joyaxis != def_bind->joyaxis)
|| (RETRO_KEYBIND_MBUTTON(bind) != RETRO_KEYBIND_MBUTTON(def_bind));
fill_pathname_join_delim(key, prefix, base, '_', sizeof(key));
if (differs_from_default)
{
/* Save the current bind */
input_keymaps_translate_rk_to_str(RETRO_KEYBIND_KEY(bind), btn, sizeof(btn));
config_set_string(conf, key, btn);
save_keybind_joykey (conf, prefix, base, bind, false);
save_keybind_axis (conf, prefix, base, bind, false);
save_keybind_mbutton(conf, prefix, base, bind, false);
}
else
{
/* Remove keys that match default */
char temp_key[64];
config_unset(conf, key);
/* Also unset joykey, axis, and mbutton keys. Build the
* "prefix_base" stem once and overwrite just the suffix
* at the known offset for each variant; the prior form
* called fill_pathname_join_delim three times and let
* each strlcat re-scan temp_key from the start to find
* its end. */
{
size_t _len = fill_pathname_join_delim(temp_key,
prefix, base, '_', sizeof(temp_key));
if (_len + sizeof("_axis") <= sizeof(temp_key))
{
memcpy(temp_key + _len, "_btn", sizeof("_btn"));
config_unset(conf, temp_key);
memcpy(temp_key + _len, "_axis", sizeof("_axis"));
config_unset(conf, temp_key);
memcpy(temp_key + _len, "_mbtn", sizeof("_mbtn"));
config_unset(conf, temp_key);
}
}
}
}
}
void config_get_autoconf_profile_filename(
const char *device_name, unsigned user,
char *s, size_t len)
{
static const char invalid_filename_chars[] =
"~#%&*{}\\:[]?/|'\"";
size_t i;
size_t _len;
char sanitised_name[PATH_MAX_LENGTH];
if (!device_name || !*device_name)
return;
strlcpy(sanitised_name, device_name, sizeof(sanitised_name));
/* Remove invalid filename characters from
* input device name */
for (i = 0; sanitised_name[i]; i++)
{
if (strchr(invalid_filename_chars, sanitised_name[i]))
sanitised_name[i] = '_';
}
/* Generate autoconfig file path */
_len = strlcpy(s, sanitised_name, len);
strlcpy_lit(s + _len, ".cfg", len - _len);
}
/**
* config_save_autoconf_profile:
* @device_name : Input device name
* @user : Port whose binds are saved
* Writes a controller autoconf file to disk for the
* device assigned to @user.
**/
bool config_save_autoconf_profile(const char *device_name, unsigned user)
{
unsigned i;
unsigned dev;
char buf[PATH_MAX_LENGTH];
char autoconf_file[PATH_MAX_LENGTH];
const char *a = NULL;
config_file_t *conf = NULL;
int32_t pid_user = 0;
int32_t vid_user = 0;
bool ret = false;
bool valid = true;
settings_t *settings = config_st;
const char *autoconf_dir = settings->paths.directory_autoconfig;
const char *joypad_driver_fallback = settings->arrays.input_joypad_driver;
const char *joypad_driver = NULL;
if (!device_name || !*device_name || user >= MAX_USERS)
return false;
/* Binds and their labels are per port; the device's
* driver, identity and autoconf binds are per device */
dev = settings->uints.input_joypad_index[user];
if (dev >= MAX_USERS)
return false;
/* Get currently set joypad driver */
joypad_driver = input_config_get_device_joypad_driver(dev);
if (!joypad_driver || !*joypad_driver)
{
/* This cannot happen, but if we reach this
* point without a driver being set for the
* current input device then use the value
* from the settings struct as a fallback */
joypad_driver = joypad_driver_fallback;
if (!joypad_driver || !*joypad_driver)
return false;
}
/* Generate autoconfig file path */
config_get_autoconf_profile_filename(device_name, dev, buf, sizeof(buf));
fill_pathname_join_special(autoconf_file, autoconf_dir, buf, sizeof(autoconf_file));
/* The directory only exists once profiles have been
* downloaded or bundled */
if ( *autoconf_dir
&& !path_is_directory(autoconf_dir)
&& !path_mkdir(autoconf_dir))
{
RARCH_ERR("[Autoconf] Failed creating directory \"%s\".\n", autoconf_dir);
return false;
}
/* Open config file */
if ( !(conf = config_file_new_from_path_to_string(autoconf_file))
&& !(conf = config_file_new_alloc())
)
{
if (conf)
config_file_free(conf);
return false;
}
/* Pre-fill existing autoconf binds for empty binds */
for (i = 0; i < RARCH_ANALOG_BIND_LIST_END; i++)
{
struct retro_keybind *bind = input_config_bind_edit(user, i);
const struct retro_keybind *auto_bind = input_autoconf_bind(dev, i);
const struct input_bind_label *albl =
input_autoconf_bind_names(dev, i);
/* the names the bind takes over from the profile, with what it
* takes over */
struct input_bind_label got = { NULL, NULL };
if (bind->joykey == NO_BTN && auto_bind->joykey != NO_BTN)
{
bind->joykey = auto_bind->joykey;
if (albl->joykey && *albl->joykey)
got.joykey = strdup(albl->joykey);
}
if (bind->joyaxis == AXIS_NONE && auto_bind->joyaxis != AXIS_NONE)
{
bind->joyaxis = auto_bind->joyaxis;
if (albl->joyaxis && *albl->joyaxis)
got.joyaxis = strdup(albl->joyaxis);
}
input_config_bind_names_take(user, i, &got);
}
/* Require at least directions (D-Pad or Left Analog) and South button,
* otherwise the profile is completely useless */
if (input_config_bind(user, RETRO_DEVICE_ID_JOYPAD_B)->joykey == NO_BTN)
valid = false;
if ( input_config_bind(user, RETRO_DEVICE_ID_JOYPAD_UP)->joykey == NO_BTN
&& input_config_bind(user, RETRO_DEVICE_ID_JOYPAD_UP)->joyaxis == AXIS_NONE
&& input_config_bind(user, RARCH_ANALOG_LEFT_Y_MINUS)->joykey == NO_BTN
&& input_config_bind(user, RARCH_ANALOG_LEFT_Y_MINUS)->joyaxis == AXIS_NONE)
valid = false;
if ( input_config_bind(user, RETRO_DEVICE_ID_JOYPAD_DOWN)->joykey == NO_BTN
&& input_config_bind(user, RETRO_DEVICE_ID_JOYPAD_DOWN)->joyaxis == AXIS_NONE
&& input_config_bind(user, RARCH_ANALOG_LEFT_Y_PLUS)->joykey == NO_BTN
&& input_config_bind(user, RARCH_ANALOG_LEFT_Y_PLUS)->joyaxis == AXIS_NONE)
valid = false;
if ( input_config_bind(user, RETRO_DEVICE_ID_JOYPAD_LEFT)->joykey == NO_BTN
&& input_config_bind(user, RETRO_DEVICE_ID_JOYPAD_LEFT)->joyaxis == AXIS_NONE
&& input_config_bind(user, RARCH_ANALOG_LEFT_X_MINUS)->joykey == NO_BTN
&& input_config_bind(user, RARCH_ANALOG_LEFT_X_MINUS)->joyaxis == AXIS_NONE)
valid = false;
if ( input_config_bind(user, RETRO_DEVICE_ID_JOYPAD_RIGHT)->joykey == NO_BTN
&& input_config_bind(user, RETRO_DEVICE_ID_JOYPAD_RIGHT)->joyaxis == AXIS_NONE
&& input_config_bind(user, RARCH_ANALOG_LEFT_X_PLUS)->joykey == NO_BTN
&& input_config_bind(user, RARCH_ANALOG_LEFT_X_PLUS)->joyaxis == AXIS_NONE)
valid = false;
/* Update config file */
config_set_string(conf, "input_driver",
joypad_driver);
config_set_string(conf, "input_device",
input_config_get_device_name(dev));
a = input_config_get_device_display_name(dev);
config_set_string(conf, "input_device_display_name",
(a && *a) ? a : input_config_get_device_name(dev));
pid_user = input_config_get_device_pid(dev);
vid_user = input_config_get_device_vid(dev);
if (pid_user && vid_user)
{
config_set_int(conf, "input_vendor_id", vid_user);
config_set_int(conf, "input_product_id", pid_user);
}
/* the controller's own deadzones, where it has them */
{
float v;
if ((v = input_config_get_device_deadzone(dev, 0)) >= 0.0f)
config_set_float(conf, "input_analog_deadzone", v);
if ((v = input_config_get_device_deadzone(dev, 1)) >= 0.0f)
config_set_float(conf, "input_analog_trigger_deadzone", v);
}
for (i = 0; i < RARCH_ANALOG_BIND_LIST_END && valid; i++)
{
unsigned id = input_config_bind_order[i];
const struct retro_keybind *bind = input_config_bind(user, id);
if (RETRO_KEYBIND_VALID(bind))
{
save_keybind_joykey(conf, "input", input_config_bind_map_get_base(id), bind, false);
save_keybind_axis(conf, "input", input_config_bind_map_get_base(id), bind, false);
}
}
for (i = 0; i < RARCH_ANALOG_BIND_LIST_END && valid; i++)
{
unsigned id = input_config_bind_order[i];
const struct retro_keybind *bind = input_config_bind(user, id);
const struct input_bind_label *lbl = input_config_bind_names(user, id);
if (RETRO_KEYBIND_VALID(bind))
{
if (lbl->joykey && *lbl->joykey)
save_keybind_joykey_label(conf, "input", input_config_bind_map_get_base(id), lbl);
if (lbl->joyaxis && *lbl->joyaxis)
save_keybind_axis_label(conf, "input", input_config_bind_map_get_base(id), lbl);
/* written out: the bind is called nothing from here, as each
* name was freed once it was saved */
input_config_bind_names_drop(user, id);
}
}
/* The profile's own hotkeys: the port's binds never hold them, and a
* profile saved under a new name would lose them. */
for (i = RARCH_FIRST_META_KEY; i < RARCH_BIND_LIST_END && valid; i++)
{
const struct retro_keybind *bind = input_autoconf_bind(dev, i);
const struct input_bind_label *lbl = input_autoconf_bind_names(dev, i);
const char *base = input_config_bind_map_get_base(i);
if (!base)
continue;
save_keybind_joykey(conf, "input", base, bind, false);
save_keybind_axis(conf, "input", base, bind, false);
if (lbl->joykey && *lbl->joykey)
save_keybind_joykey_label(conf, "input", base, lbl);
if (lbl->joyaxis && *lbl->joyaxis)
save_keybind_axis_label(conf, "input", base, lbl);
}
if (valid)
{
ret = config_file_write(conf, autoconf_file, false);
if (ret)
RARCH_LOG("[Autoconf] Saved profile to \"%s\".\n", autoconf_file);
else
RARCH_LOG("[Autoconf] Failed saving profile to \"%s\".\n", autoconf_file);
}
else
RARCH_ERR("[Autoconf] Not saving invalid profile for device \"%s\".\n", device_name);
if (conf)
config_file_free(conf);
return ret;
}
/* config_path_strip_trailing_slash:
*
* Removes a single trailing path separator from a directory value, so
* that directory paths are serialised consistently in the config file
* (e.g. ".../assets/" is written as ".../assets").
*
* Intentionally left untouched:
* - root paths ("/") -> length < 2
* - drive roots and the content marker -> preceding char is ':'
* ("C:\", "C:/", ":/")
* - empty strings, "default" and file
* paths -> never end in a separator
*
* This only affects serialisation: fill_pathname_join() and friends
* ignore a trailing separator on their directory operand, so runtime
* path construction is unaffected either way. */
static void config_path_strip_trailing_slash(char *s)
{
size_t len;
if (!s || !*s)
return;
len = strlen(s);
if (len < 2)
return;
if (!PATH_CHAR_IS_SLASH(s[len - 1]))
return;
if (s[len - 2] == ':')
return;
s[len - 1] = '\0';
}
/**
* config_get_credentials_path:
*
* Builds the path to the credentials config file.
* Uses the same directory as the main config file.
*
* Returns: length of the string written to @s.
**/
static size_t config_get_credentials_path(char *s, size_t len)
{
char config_directory[DIR_MAX_LENGTH];
const char *config_path =
#ifdef __PS3__
g_defaults.path_config;
#else
path_get(RARCH_PATH_CONFIG);
#endif
config_directory[0] = '\0';
if (!config_path || !*config_path)
{
s[0] = '\0';
return 0;
}
fill_pathname_basedir(config_directory,
config_path,
sizeof(config_directory));
return fill_pathname_join_special(s, config_directory,
"retroarch-keychain.cfg", len);
}
/**
* config_save_credentials:
* @main_conf : loaded retroarch.cfg, source for secrets the
* current build has no setting for
* @array_settings : string settings table (from populate_settings_array)
* @array_settings_size : number of entries in @array_settings
* @path_settings : path settings table (from populate_settings_path)
* @path_settings_size : number of entries in @path_settings
*
* Writes only sensitive settings (passwords, tokens, keys)
* to a separate retroarch-keychain.cfg file. The tables are the ones
* config_save_file() has already built, so nothing is
* re-populated here.
*
* Returns: true (1) on success, otherwise returns false (0).
**/
static bool config_save_credentials(
config_file_t *main_conf,
const struct config_array_setting *array_settings,
int array_settings_size,
const struct config_path_setting *path_settings,
int path_settings_size)
{
unsigned i;
bool ret = false;
char credentials_path[PATH_MAX_LENGTH];
config_file_t *conf = NULL;
credentials_path[0] = '\0';
config_get_credentials_path(credentials_path, sizeof(credentials_path));
if (string_is_empty(credentials_path))
return false;
conf = config_file_new_from_path_to_string(credentials_path);
if (!conf)
conf = config_file_new_alloc();
if (!conf)
return false;
#ifdef HAVE_KEYCHAIN
config_keychain_carried = 0;
config_keychain_withheld = 0;
if (config_keychain_init())
config_set_int(conf, "keychain_version", 1);
else if (keychain_is_locked())
RARCH_WARN("[Config] Keychain is locked: enter its passphrase under "
"Settings > User to open the saved credentials.\n");
else
RARCH_WARN("[Config] Keychain key file unavailable, "
"credentials are written in the clear.\n");
#endif
if (array_settings && (array_settings_size > 0))
{
for (i = 0; i < (unsigned)array_settings_size; i++)
{
if (!(array_settings[i].flags & CFG_BOOL_FLG_SENSITIVE))
continue;
config_keychain_set(conf,
array_settings[i].ident,
array_settings[i].ptr, true);
}
}
if (path_settings && (path_settings_size > 0))
{
for (i = 0; i < (unsigned)path_settings_size; i++)
{
if (!(path_settings[i].flags & CFG_BOOL_FLG_SENSITIVE))
continue;
config_keychain_set(conf,
path_settings[i].ident,
path_settings[i].ptr, true);
}
}
/* Secrets for features compiled out of this build have no
* settings entry above; carry them over from retroarch.cfg
* as-is so they are not lost when it is stripped. Anything
* already sealed in the keychain file (opened or not) is kept
* sealed; only plaintext still in retroarch.cfg gets sealed on
* its way over. */
if (main_conf)
{
for (i = 0; i < ARRAY_SIZE(config_sensitive_keys); i++)
{
const struct config_entry_list *entry;
const char *key = config_sensitive_keys[i];
if (config_get_entry(conf, key))
continue;
entry = config_get_entry(main_conf, key);
if (entry && entry->value)
config_keychain_set(conf, key, entry->value, false);
}
}
ret = config_file_write(conf, credentials_path, true);
config_file_free(conf);
#ifdef HAVE_KEYCHAIN
/* Load-time logging is not up yet for the first config, so this
* is where the user hears about it. */
if (ret && config_keychain_carried)
RARCH_WARN("[Config] %u credential(s) in \"%s\" were sealed on "
"another machine or install, could not be opened here and "
"were kept as they are.\n",
config_keychain_carried, credentials_path);
if (ret && config_keychain_withheld)
RARCH_WARN("[Config] %u credential(s) set while the keychain was "
"locked were not saved; unlock it and set them again.\n",
config_keychain_withheld);
#endif
if (ret)
{
/* Sealed or not, make the file owner-only. Not fatal on
* failure (e.g. FAT/exFAT media), the write itself succeeded. */
if (!path_set_private(credentials_path))
RARCH_WARN("[Config] Could not restrict permissions on \"%s\".\n",
credentials_path);
RARCH_LOG("[Config] Saved credentials to \"%s\".\n", credentials_path);
}
else
RARCH_ERR("[Config] Failed to save credentials to \"%s\".\n", credentials_path);
return ret;
}
/**
* config_save_file:
* @path : Path that shall be written to.
*
* Writes a config file to disk.
*
* Returns: true (1) on success, otherwise returns false (0).
**/
#ifdef HAVE_KEYCHAIN
/**
* config_keychain_reapply:
*
* After the keychain is unlocked, opens the credentials that were
* sealed on another machine and puts them into the running settings,
* so accounts work without a restart. Settings the credentials file
* does not hold are left as they are.
*
* Returns: number of credentials put back.
**/
unsigned config_keychain_reapply(void)
{
char credentials_path[PATH_MAX_LENGTH];
settings_t *settings = config_st;
config_file_t *conf;
struct config_array_setting *arrays;
struct config_path_setting *paths;
int arrays_size = 0;
int paths_size = 0;
int i;
unsigned applied = 0;
if (!keychain_is_ready())
return 0;
credentials_path[0] = '\0';
config_get_credentials_path(credentials_path, sizeof(credentials_path));
if (string_is_empty(credentials_path)
|| !(conf = config_file_new_from_path_to_string(credentials_path)))
return 0;
config_keychain_open_entries(conf);
if ((arrays = populate_settings_array(settings, &arrays_size)))
{
for (i = 0; i < arrays_size; i++)
if ((arrays[i].flags & CFG_BOOL_FLG_SENSITIVE)
&& config_get_entry(conf, arrays[i].ident)
&& config_get_array(conf, arrays[i].ident,
arrays[i].ptr, PATH_MAX_LENGTH))
applied++;
free(arrays);
}
if ((paths = populate_settings_path(settings, &paths_size)))
{
for (i = 0; i < paths_size; i++)
{
char tmp[PATH_MAX_LENGTH];
if ((paths[i].flags & CFG_BOOL_FLG_SENSITIVE)
&& config_get_entry(conf, paths[i].ident)
&& config_get_path(conf, paths[i].ident, tmp, sizeof(tmp)))
{
strlcpy(paths[i].ptr, tmp, PATH_MAX_LENGTH);
applied++;
}
}
free(paths);
}
config_file_free(conf);
return applied;
}
#endif
bool config_save_file(const char *path)
{
float msg_color;
unsigned i = 0;
bool ret = false;
bool minimal = false;
bool credentials_saved = false;
settings_t *defaults = NULL;
struct config_bool_setting *bool_settings = NULL;
struct config_bool_setting *bool_defaults = NULL;
struct config_int_setting *int_settings = NULL;
struct config_int_setting *int_defaults = NULL;
struct config_uint_setting *uint_settings = NULL;
struct config_uint_setting *uint_defaults = NULL;
struct config_size_setting *size_settings = NULL;
struct config_size_setting *size_defaults = NULL;
struct config_float_setting *float_settings = NULL;
struct config_float_setting *float_defaults = NULL;
struct config_array_setting *array_settings = NULL;
struct config_array_setting *array_defaults = NULL;
struct config_path_setting *path_settings = NULL;
struct config_path_setting *path_defaults = NULL;
uint32_t flags = runloop_get_flags();
config_file_t *conf = config_file_new_from_path_to_string(path);
settings_t *settings = config_st;
int bool_settings_size = SETTINGS_BOOL_COUNT_MAX;
int float_settings_size = SETTINGS_FLOAT_COUNT_MAX;
int int_settings_size = SETTINGS_INT_COUNT_MAX;
int uint_settings_size = SETTINGS_UINT_COUNT_MAX;
int size_settings_size = SETTINGS_SIZE_COUNT_MAX;
int array_settings_size = SETTINGS_ARRAY_COUNT_MAX;
int path_settings_size = SETTINGS_PATH_COUNT_MAX;
if (!conf)
conf = config_file_new_alloc();
if (!conf || (flags & RUNLOOP_FLAG_OVERRIDES_ACTIVE))
{
if (conf)
config_file_free(conf);
return false;
}
bool_settings = populate_settings_bool (settings, &bool_settings_size);
int_settings = populate_settings_int (settings, &int_settings_size);
uint_settings = populate_settings_uint (settings, &uint_settings_size);
size_settings = populate_settings_size (settings, &size_settings_size);
float_settings = populate_settings_float (settings, &float_settings_size);
array_settings = populate_settings_array (settings, &array_settings_size);
path_settings = populate_settings_path (settings, &path_settings_size);
/* Check if we should save minimal config (only changed values) */
minimal = settings->bools.config_save_minimal;
/* If minimal mode, create a defaults struct and populate it */
if (minimal)
{
int tmp_int;
/* Allocate fresh settings struct for defaults */
defaults = (settings_t*)calloc(1, sizeof(settings_t));
if (!defaults)
{
/* Failed to allocate, fall back to non-minimal mode */
minimal = false;
}
else
{
{
#ifdef HAVE_LANGEXTRA
unsigned saved_user_language = *msg_hash_get_uint(MSG_HASH_USER_LANGUAGE);
#endif
/* Populate the local defaults struct directly: config_st
* stays what every other thread's config_get_ptr() returns,
* and the input's own state is not reset for it (see
* config_set_defaults()). Nothing of the binds, their labels
* or the controllers' profiles is copied aside and put back:
* a bind's default is asked for where it is compared. */
config_set_defaults(defaults);
#ifdef HAVE_LANGEXTRA
/* Restore user_language global, clobbered by config_set_defaults. */
msg_hash_set_uint(MSG_HASH_USER_LANGUAGE, saved_user_language);
#endif
}
/* Populate default setting arrays */
if (minimal)
{
tmp_int = sizeof(defaults->bools) / sizeof(defaults->bools.placeholder);
bool_defaults = populate_settings_bool(defaults, &tmp_int);
tmp_int = sizeof(defaults->ints) / sizeof(defaults->ints.placeholder);
int_defaults = populate_settings_int(defaults, &tmp_int);
tmp_int = sizeof(defaults->uints) / sizeof(defaults->uints.placeholder);
uint_defaults = populate_settings_uint(defaults, &tmp_int);
tmp_int = sizeof(defaults->sizes) / sizeof(defaults->sizes.placeholder);
size_defaults = populate_settings_size(defaults, &tmp_int);
tmp_int = sizeof(defaults->floats) / sizeof(defaults->floats.placeholder);
float_defaults = populate_settings_float(defaults, &tmp_int);
tmp_int = sizeof(defaults->arrays) / sizeof(defaults->arrays.placeholder);
array_defaults = populate_settings_array(defaults, &tmp_int);
tmp_int = sizeof(defaults->paths) / sizeof(defaults->paths.placeholder);
path_defaults = populate_settings_path(defaults, &tmp_int);
}
}
}
/* Save credentials to a separate file.
* Only strip sensitive fields from retroarch.cfg
* when retroarch-keychain.cfg was written successfully. */
credentials_saved = config_save_credentials(conf,
array_settings, array_settings_size,
path_settings, path_settings_size);
if (credentials_saved)
{
/* Strip by key name, not by settings table, so entries
* belonging to features this build lacks go too. */
for (i = 0; i < ARRAY_SIZE(config_sensitive_keys); i++)
config_unset(conf, config_sensitive_keys[i]);
}
else
RARCH_WARN("[Config] Credentials save failed, "
"keeping sensitive fields in main config.\n");
/* Path settings */
if (path_settings && (path_settings_size > 0))
{
for (i = 0; i < (unsigned)path_settings_size; i++)
{
char value_buf[PATH_MAX_LENGTH];
char default_buf[PATH_MAX_LENGTH];
const char *value = path_settings[i].ptr;
const char *default_value = path_defaults ? path_defaults[i].ptr : NULL;
/* Sensitive settings live in retroarch-keychain.cfg and
* were already stripped from conf by key name. */
if ( credentials_saved
&& (path_settings[i].flags & CFG_BOOL_FLG_SENSITIVE))
continue;
if (path_settings[i].flags & CFG_BOOL_FLG_DEF_ENABLE)
{
if (!path_settings[i].ptr || !*path_settings[i].ptr)
value = "default";
if (minimal && (!default_value || !*default_value))
default_value = "default";
}
/* Normalise a trailing separator out of directory values so
* saved paths are consistent. File paths and the "" / "default"
* sentinels never end in a separator, so they pass through
* unchanged; both the written value and the default used for
* the minimal-mode comparison are normalised so the dedup
* stays correct. */
if (value)
{
strlcpy(value_buf, value, sizeof(value_buf));
config_path_strip_trailing_slash(value_buf);
value = value_buf;
}
if (default_value)
{
strlcpy(default_buf, default_value, sizeof(default_buf));
config_path_strip_trailing_slash(default_buf);
default_value = default_buf;
}
/* In minimal mode, only save if value differs from default */
if ( !minimal
|| !string_is_equal(value, default_value))
config_set_path(conf, path_settings[i].ident, value);
else
/* Remove key if it matches default */
config_unset(conf, path_settings[i].ident);
}
}
#ifdef HAVE_MENU
/* xmb_font */
{
const char *xmb_font_value = *settings->paths.path_menu_xmb_font
? settings->paths.path_menu_xmb_font : "";
const char *xmb_font_default = (minimal && defaults)
? ( *defaults->paths.path_menu_xmb_font
? defaults->paths.path_menu_xmb_font : "")
: "";
if ( !minimal
|| !string_is_equal(xmb_font_value, xmb_font_default))
{
config_set_path(conf, "xmb_font", xmb_font_value);
}
else
{
config_unset(conf, "xmb_font");
}
}
/* ozone_font */
{
const char *ozone_font_value =
*settings->paths.path_menu_ozone_font
? settings->paths.path_menu_ozone_font : "";
const char *ozone_font_default = (minimal && defaults)
? ( *defaults->paths.path_menu_ozone_font
? defaults->paths.path_menu_ozone_font : "")
: "";
if ( !minimal
|| !string_is_equal(ozone_font_value, ozone_font_default))
{
config_set_path(conf, "ozone_font", ozone_font_value);
}
else
{
config_unset(conf, "ozone_font");
}
}
#endif
/* String settings */
if (array_settings && (array_settings_size > 0))
{
for (i = 0; i < (unsigned)array_settings_size; i++)
{
/* Sensitive settings live in retroarch-keychain.cfg and
* were already stripped from conf by key name. */
if ( credentials_saved
&& (array_settings[i].flags & CFG_BOOL_FLG_SENSITIVE))
continue;
if ( !array_settings[i].override
|| !retroarch_override_setting_is_set(array_settings[i].override, NULL))
{
/* In minimal mode, only save if value differs from default */
if ( !minimal
|| !string_is_equal(array_settings[i].ptr, array_defaults[i].ptr))
{
config_set_string(conf,
array_settings[i].ident,
array_settings[i].ptr);
}
else
{
/* Remove key if it matches default */
config_unset(conf, array_settings[i].ident);
}
}
}
}
/* Float settings */
if (float_settings && (float_settings_size > 0))
{
for (i = 0; i < (unsigned)float_settings_size; i++)
{
if ( !float_settings[i].override
|| !retroarch_override_setting_is_set(float_settings[i].override, NULL))
{
/* In minimal mode, only save if value differs from default */
if ( !minimal
|| *float_settings[i].ptr != *float_defaults[i].ptr)
{
config_set_float(conf,
float_settings[i].ident,
*float_settings[i].ptr);
}
else
{
/* Remove key if it matches default */
config_unset(conf, float_settings[i].ident);
}
}
}
}
/* Integer settings */
if (int_settings && (int_settings_size > 0))
{
for (i = 0; i < (unsigned)int_settings_size; i++)
{
if ( !int_settings[i].override
|| !retroarch_override_setting_is_set(int_settings[i].override, NULL))
{
/* In minimal mode, only save if value differs from default */
if ( !minimal
|| cfg_int_get(&int_settings[i])
!= cfg_int_get(&int_defaults[i]))
{
config_set_int(conf,
int_settings[i].ident,
cfg_int_get(&int_settings[i]));
}
else
{
/* Remove key if it matches default */
config_unset(conf, int_settings[i].ident);
}
}
}
}
if (uint_settings && (uint_settings_size > 0))
{
for (i = 0; i < (unsigned)uint_settings_size; i++)
{
if ( !uint_settings[i].override
|| !retroarch_override_setting_is_set(uint_settings[i].override, NULL))
{
unsigned default_val = 0;
bool has_default = false;
if (minimal)
{
if (uint_settings[i].ptr == uint_defaults[i].ptr)
{
if (uint_settings[i].flags & CFG_BOOL_FLG_DEF_ENABLE)
{
default_val = uint_settings[i].def;
has_default = true;
}
}
else
{
default_val = cfg_uint_get(&uint_defaults[i]);
has_default = true;
}
}
/* In minimal mode, only save if value differs from default */
if ( !minimal
|| !has_default
|| cfg_uint_get(&uint_settings[i]) != default_val)
{
config_set_int(conf,
uint_settings[i].ident,
cfg_uint_get(&uint_settings[i]));
}
else
{
/* Remove key if it matches default */
config_unset(conf, uint_settings[i].ident);
}
}
}
}
if (size_settings && (size_settings_size > 0))
{
for (i = 0; i < (unsigned)size_settings_size; i++)
{
if ( !size_settings[i].override
|| !retroarch_override_setting_is_set(size_settings[i].override, NULL))
{
/* In minimal mode, only save if value differs from default */
if ( !minimal
|| *size_settings[i].ptr != *size_defaults[i].ptr)
{
config_set_int(conf,
size_settings[i].ident,
(int)*size_settings[i].ptr);
}
else
{
/* Remove key if it matches default */
config_unset(conf, size_settings[i].ident);
}
}
}
}
#ifdef HAVE_VIDEO_WINDOWS
for (i = 0; i < RETRO_VIDEO_VIEWS_MAX; i++)
{
char cfg[64];
size_t len = snprintf(cfg, sizeof(cfg), "video_screen%u_window_", i + 1);
strlcpy_lit(cfg + len, "mode", sizeof(cfg) - len);
if ( !minimal
|| settings->uints.video_screen_window_mode[i] != defaults->uints.video_screen_window_mode[i])
config_set_int(conf, cfg, settings->uints.video_screen_window_mode[i]);
else
config_unset(conf, cfg);
strlcpy_lit(cfg + len, "x", sizeof(cfg) - len);
if ( !minimal
|| VIDEO_POS_X(settings->uints.video_screen_window_pos[i]) != VIDEO_POS_X(defaults->uints.video_screen_window_pos[i]))
config_set_int(conf, cfg, VIDEO_POS_X(settings->uints.video_screen_window_pos[i]));
else
config_unset(conf, cfg);
strlcpy_lit(cfg + len, "y", sizeof(cfg) - len);
if ( !minimal
|| VIDEO_POS_Y(settings->uints.video_screen_window_pos[i]) != VIDEO_POS_Y(defaults->uints.video_screen_window_pos[i]))
config_set_int(conf, cfg, VIDEO_POS_Y(settings->uints.video_screen_window_pos[i]));
else
config_unset(conf, cfg);
strlcpy_lit(cfg + len, "width", sizeof(cfg) - len);
if ( !minimal
|| VIDEO_SCALE_W(settings->uints.video_screen_window_dims[i]) != VIDEO_SCALE_W(defaults->uints.video_screen_window_dims[i]))
config_set_int(conf, cfg, VIDEO_SCALE_W(settings->uints.video_screen_window_dims[i]));
else
config_unset(conf, cfg);
strlcpy_lit(cfg + len, "height", sizeof(cfg) - len);
if ( !minimal
|| VIDEO_SCALE_H(settings->uints.video_screen_window_dims[i]) != VIDEO_SCALE_H(defaults->uints.video_screen_window_dims[i]))
config_set_int(conf, cfg, VIDEO_SCALE_H(settings->uints.video_screen_window_dims[i]));
else
config_unset(conf, cfg);
strlcpy_lit(cfg + len, "monitor", sizeof(cfg) - len);
if ( !minimal
|| settings->uints.video_screen_window_monitor[i] != defaults->uints.video_screen_window_monitor[i])
config_set_int(conf, cfg, settings->uints.video_screen_window_monitor[i]);
else
config_unset(conf, cfg);
strlcpy_lit(cfg + len, "fullscreen", sizeof(cfg) - len);
if ( !minimal
|| settings->bools.video_screen_window_fullscreen[i] != defaults->bools.video_screen_window_fullscreen[i])
config_set_string(conf, cfg, settings->bools.video_screen_window_fullscreen[i] ? "true" : "false");
else
config_unset(conf, cfg);
}
#endif
for (i = 0; i < MAX_USERS; i++)
{
size_t _len;
char cfg[64];
char formatted_number[4];
formatted_number[0] = '\0';
snprintf(formatted_number, sizeof(formatted_number), "%u", i + 1);
_len = strlcpy_lit(cfg, "input_device_p", sizeof(cfg));
strlcpy(cfg + _len, formatted_number, sizeof(cfg) - _len);
if ( !minimal
|| settings->uints.input_device[i] != defaults->uints.input_device[i])
config_set_int(conf, cfg, settings->uints.input_device[i]);
else
config_unset(conf, cfg);
_len = strlcpy_lit(cfg, "input_player", sizeof(cfg));
_len += strlcpy(cfg + _len, formatted_number, sizeof(cfg) - _len);
strlcpy_lit(cfg + _len, "_mouse_index", sizeof(cfg) - _len);
if ( !minimal
|| settings->uints.input_mouse_index[i] != defaults->uints.input_mouse_index[i])
config_set_int(conf, cfg, settings->uints.input_mouse_index[i]);
else
config_unset(conf, cfg);
strlcpy_lit(cfg + _len, "_keyboard_index", sizeof(cfg) - _len);
if ( !minimal
|| settings->uints.input_keyboard_index[i] != defaults->uints.input_keyboard_index[i])
config_set_int(conf, cfg, settings->uints.input_keyboard_index[i]);
else
config_unset(conf, cfg);
strlcpy_lit(cfg + _len, "_aim_stick", sizeof(cfg) - _len);
if ( !minimal
|| settings->uints.input_aim_stick[i] != defaults->uints.input_aim_stick[i])
config_set_int(conf, cfg, settings->uints.input_aim_stick[i]);
else
config_unset(conf, cfg);
strlcpy_lit(cfg + _len, "_touchpad", sizeof(cfg) - _len);
if ( !minimal
|| settings->uints.input_touchpad[i] != defaults->uints.input_touchpad[i])
config_set_int(conf, cfg, settings->uints.input_touchpad[i]);
else
config_unset(conf, cfg);
/* What the user configured, which is not what the setting holds
* while a driver restart has put controllers back on their
* ports. */
strlcpy_lit(cfg + _len, "_joypad_index", sizeof(cfg) - _len);
if ( !minimal
|| input_config_get_saved_joypad_index(i) != defaults->uints.input_joypad_index[i])
config_set_int(conf, cfg, input_config_get_saved_joypad_index(i));
else
config_unset(conf, cfg);
strlcpy_lit(cfg + _len, "_analog_dpad_mode", sizeof(cfg) - _len);
if ( !minimal
|| settings->uints.input_analog_dpad_mode[i] != defaults->uints.input_analog_dpad_mode[i])
config_set_int(conf, cfg, settings->uints.input_analog_dpad_mode[i]);
else
config_unset(conf, cfg);
strlcpy_lit(cfg + _len, "_device_reservation_type", sizeof(cfg) - _len);
if ( !minimal
|| settings->uints.input_device_reservation_type[i] != defaults->uints.input_device_reservation_type[i])
config_set_int(conf, cfg, settings->uints.input_device_reservation_type[i]);
else
config_unset(conf, cfg);
}
/* Boolean settings */
if (bool_settings && (bool_settings_size > 0))
{
for (i = 0; i < (unsigned)bool_settings_size; i++)
{
if ( !bool_settings[i].override
|| !retroarch_override_setting_is_set(bool_settings[i].override, NULL))
{
/* In minimal mode, only save if value differs from default */
if ( !minimal
|| *bool_settings[i].ptr != *bool_defaults[i].ptr)
{
config_set_string(conf, bool_settings[i].ident,
*bool_settings[i].ptr
? "true" : "false");
}
else
{
/* Remove key if it matches default */
config_unset(conf, bool_settings[i].ident);
}
}
}
}
#ifdef HAVE_NETWORKGAMEPAD
{
char tmp[64];
size_t _len = strlcpy_lit(tmp, "network_remote_enable_user_p", sizeof(tmp));
for (i = 0; i < MAX_USERS; i++)
{
snprintf(tmp + _len, sizeof(tmp) - _len, "%u", i + 1);
if ( !minimal
|| settings->bools.network_remote_enable_user[i] != defaults->bools.network_remote_enable_user[i])
{
config_set_string(conf, tmp,
settings->bools.network_remote_enable_user[i]
? "true" : "false");
}
else
{
config_unset(conf, tmp);
}
}
}
#endif
#ifdef HAVE_MENU
/* menu_show_start_screen is force-written in minimal mode because the SETTING_BOOL
* default (false) doesn't match DEFAULT_MENU_SHOW_START_SCREEN (true) - see TODO
* comment at line 2095. This workaround ensures the config file is written correctly
* even though the default mismatch would normally cause it to be omitted.
* TODO: Remove this force-write when the default at line 2095 is fixed. */
if (minimal)
{
config_set_string(conf, "rgui_show_start_screen",
settings->bools.menu_show_start_screen ? "true" : "false");
}
#endif
/* Verbosity isn't in bool_settings since it needs to be loaded differently */
if (!retroarch_override_setting_is_set(RARCH_OVERRIDE_SETTING_VERBOSITY, NULL))
{
bool verbosity_enabled = verbosity_is_enabled();
bool default_verbosity = false; /* Default is disabled */
if ( !minimal
|| verbosity_enabled != default_verbosity)
{
config_set_string(conf, "log_verbosity",
verbosity_enabled ? "true" : "false");
}
else
{
config_unset(conf, "log_verbosity");
}
}
/* perfcnt_enable */
{
bool perfcnt_enabled = retroarch_ctl(RARCH_CTL_IS_PERFCNT_ENABLE, NULL);
bool default_perfcnt = false; /* Default is disabled */
if ( !minimal
|| perfcnt_enabled != default_perfcnt)
{
config_set_string(conf, "perfcnt_enable",
perfcnt_enabled ? "true" : "false");
}
else
{
config_unset(conf, "perfcnt_enable");
}
}
msg_color = (((int)(settings->floats.video_msg_color_r * 255.0f) & 0xff) << 16) +
(((int)(settings->floats.video_msg_color_g * 255.0f) & 0xff) << 8) +
(((int)(settings->floats.video_msg_color_b * 255.0f) & 0xff));
/* Hexadecimal settings */
/* video_message_color */
{
uint32_t default_msg_color = DEFAULT_MESSAGE_COLOR;
if (minimal && defaults)
{
default_msg_color = (((int)(defaults->floats.video_msg_color_r * 255.0f) & 0xff) << 16) +
(((int)(defaults->floats.video_msg_color_g * 255.0f) & 0xff) << 8) +
(((int)(defaults->floats.video_msg_color_b * 255.0f) & 0xff));
}
if ( !minimal
|| msg_color != default_msg_color)
{
config_set_hex(conf, "video_message_color", msg_color);
}
else
{
config_unset(conf, "video_message_color");
}
}
#ifdef HAVE_LAKKA
if (settings->bools.ssh_enable)
filestream_close(filestream_open(LAKKA_SSH_PATH,
RETRO_VFS_FILE_ACCESS_WRITE,
RETRO_VFS_FILE_ACCESS_HINT_NONE));
else
filestream_delete(LAKKA_SSH_PATH);
if (settings->bools.samba_enable)
filestream_delete(LAKKA_SAMBA_DISABLED_FILE_PATH);
else
filestream_close(filestream_open(LAKKA_SAMBA_DISABLED_FILE_PATH,
RETRO_VFS_FILE_ACCESS_WRITE,
RETRO_VFS_FILE_ACCESS_HINT_NONE));
if (settings->bools.bluetooth_enable)
filestream_close(filestream_open(LAKKA_BLUETOOTH_PATH,
RETRO_VFS_FILE_ACCESS_WRITE,
RETRO_VFS_FILE_ACCESS_HINT_NONE));
else
filestream_delete(LAKKA_BLUETOOTH_PATH);
#ifdef HAVE_RETROFLAG
if (settings->bools.safeshutdown_enable)
filestream_close(filestream_open(LAKKA_SAFESHUTDOWN_PATH,
RETRO_VFS_FILE_ACCESS_WRITE,
RETRO_VFS_FILE_ACCESS_HINT_NONE));
else
filestream_delete(LAKKA_SAFESHUTDOWN_PATH);
#endif
#endif
for (i = 0; i < MAX_USERS; i++)
{
if (minimal)
input_config_save_keybinds_user_minimal(conf, i);
else
input_config_save_keybinds_user(conf, i);
}
/* the entries and macros, as they are now */
input_entries_write(conf);
/* Remove unused "quit_press_twice" after migrating to "confirm_quit" */
{
const char *tmp_key = "quit_press_twice";
struct config_entry_list *tmp = config_get_entry(conf, tmp_key);
if (tmp)
config_unset(conf, tmp->key);
}
/* Remove unused "menu_throttle_framerate" after migrating to
* "menu_frame_rate" */
{
const char *tmp_key = "menu_throttle_framerate";
struct config_entry_list *tmp = config_get_entry(conf, tmp_key);
if (tmp)
config_unset(conf, tmp->key);
}
ret = config_file_write(conf, path, true);
config_file_free(conf);
#if TARGET_OS_TV
if (ret && string_is_equal(path, path_get(RARCH_PATH_CONFIG)))
write_userdefaults_config_file();
#endif
/* Clean up defaults struct and arrays if allocated */
if (defaults)
{
if (bool_defaults)
free(bool_defaults);
if (int_defaults)
free(int_defaults);
if (uint_defaults)
free(uint_defaults);
if (size_defaults)
free(size_defaults);
if (float_defaults)
free(float_defaults);
if (array_defaults)
free(array_defaults);
if (path_defaults)
free(path_defaults);
free(defaults);
}
if (bool_settings)
free(bool_settings);
if (int_settings)
free(int_settings);
if (uint_settings)
free(uint_settings);
if (size_settings)
free(size_settings);
if (float_settings)
free(float_settings);
if (array_settings)
free(array_settings);
if (path_settings)
free(path_settings);
return ret;
}
/**
* config_save_overrides:
* @path : Path that shall be written to.
*
* Writes a config file override to disk.
*
* Returns: true (1) on success, (-1) if nothing to write, otherwise returns false (0).
**/
int8_t config_save_overrides(enum override_type type,
void *data, bool remove, const char *path)
{
int tmp_i = 0;
unsigned i = 0;
int8_t ret = 0;
input_config_binds_copy_t *input_override_binds = NULL;
config_file_t *conf = NULL;
settings_t *settings = NULL;
struct config_bool_setting *bool_settings = NULL;
struct config_bool_setting *bool_overrides = NULL;
struct config_int_setting *int_settings = NULL;
struct config_uint_setting *uint_settings = NULL;
struct config_size_setting *size_settings = NULL;
struct config_int_setting *int_overrides = NULL;
struct config_uint_setting *uint_overrides = NULL;
struct config_size_setting *size_overrides = NULL;
struct config_float_setting *float_settings = NULL;
struct config_float_setting *float_overrides= NULL;
struct config_array_setting *array_settings = NULL;
struct config_array_setting *array_overrides= NULL;
struct config_path_setting *path_settings = NULL;
struct config_path_setting *path_overrides = NULL;
char config_directory[DIR_MAX_LENGTH];
char override_directory[DIR_MAX_LENGTH];
char override_path[PATH_MAX_LENGTH];
char base_savefile[PATH_MAX_LENGTH];
char base_savestate[PATH_MAX_LENGTH];
bool savefile_cmdline = false;
bool savestate_cmdline = false;
settings_t *overrides = config_st;
int bool_settings_size = SETTINGS_BOOL_COUNT_MAX;
int float_settings_size = SETTINGS_FLOAT_COUNT_MAX;
int int_settings_size = SETTINGS_INT_COUNT_MAX;
int uint_settings_size = SETTINGS_UINT_COUNT_MAX;
int size_settings_size = SETTINGS_SIZE_COUNT_MAX;
int array_settings_size = SETTINGS_ARRAY_COUNT_MAX;
int path_settings_size = SETTINGS_PATH_COUNT_MAX;
rarch_system_info_t *sys_info = (rarch_system_info_t*)data;
const char *core_name = sys_info ? sys_info->info.library_name : NULL;
const char *rarch_path_basename = path_get(RARCH_PATH_BASENAME);
const char *game_name = NULL;
bool has_content = (rarch_path_basename && *rarch_path_basename);
override_path[0] = '\0';
/* > Cannot save an override if we have no core
* > Cannot save a per-game or per-content-directory
* override if we have no content */
if ( (!core_name || !*core_name)
|| (!has_content && (type != OVERRIDE_CORE)))
return false;
settings = (settings_t*)calloc(1, sizeof(settings_t));
conf = config_file_new_alloc();
/* A copy of the binds is kept off the stack (this function is
* reachable on small-stack platforms such as the 3DS). Made here so
* it shares the OOM bail below and is freed at the function-end
* cleanup. */
input_override_binds = input_config_binds_copy_new();
/* NULL-check: both calloc and config_file_new_alloc can
* return NULL on OOM. config_load_file at line ~6552
* dereferences settings unconditionally, and all the
* config_set_* calls later dereference conf. Rather than
* sprinkle NULL-guards through a 300-line function, bail
* out here. The function-end cleanup at line ~6866 does
* free(settings) which is NULL-safe, but conf needs
* explicit config_file_free + NULL guard.
*
* Return -1 to signal hard failure (as distinct from
* 'override was not needed' = false/0 at line 6529).
* int8_t return value accommodates -1. */
if (!settings || !conf || !input_override_binds)
{
if (conf)
config_file_free(conf);
free(settings);
if (input_override_binds)
input_config_binds_copy_free(input_override_binds);
return -1;
}
/* Get base config directory */
fill_pathname_application_special(config_directory,
sizeof(config_directory),
APPLICATION_SPECIAL_DIRECTORY_CONFIG);
fill_pathname_join_special(override_directory,
config_directory, core_name,
sizeof(override_directory));
/* Ensure base config directory exists */
if (!path_is_directory(override_directory))
path_mkdir(override_directory);
/* Store current binds as override binds */
input_config_binds_copy_take(input_override_binds);
/* Load the original config file in memory */
config_load_file(
"without-overrides", settings);
bool_settings = populate_settings_bool(settings, &bool_settings_size);
tmp_i = SETTINGS_BOOL_COUNT_MAX;
bool_overrides = populate_settings_bool(overrides, &tmp_i);
int_settings = populate_settings_int(settings, &int_settings_size);
tmp_i = SETTINGS_INT_COUNT_MAX;
int_overrides = populate_settings_int(overrides, &tmp_i);
uint_settings = populate_settings_uint(settings, &uint_settings_size);
tmp_i = SETTINGS_UINT_COUNT_MAX;
uint_overrides = populate_settings_uint(overrides, &tmp_i);
size_settings = populate_settings_size(settings, &size_settings_size);
tmp_i = SETTINGS_SIZE_COUNT_MAX;
size_overrides = populate_settings_size(overrides, &tmp_i);
float_settings = populate_settings_float(settings, &float_settings_size);
tmp_i = SETTINGS_FLOAT_COUNT_MAX;
float_overrides = populate_settings_float(overrides, &tmp_i);
array_settings = populate_settings_array(settings, &array_settings_size);
tmp_i = SETTINGS_ARRAY_COUNT_MAX;
array_overrides = populate_settings_array(overrides, &tmp_i);
path_settings = populate_settings_path(settings, &path_settings_size);
tmp_i = SETTINGS_PATH_COUNT_MAX;
path_overrides = populate_settings_path(overrides, &tmp_i);
/* savefile_directory and savestate_directory are backed by a single
* global runtime buffer (dir_get_ptr) rather than a per-settings
* field, so populate_settings_path() returns the same pointer for
* both 'settings' (base) and 'overrides' (live). The generic path
* diff below is therefore blind to changes in these two dirs
* (issue #18809). Read the pre-override baseline straight from the
* on-disk config so the live dirs can be diffed against it explicitly.
* "default" is resolved the same way the loader does, so an unchanged
* default does not register as a spurious change. The command-line
* --save/--savestate overrides mirror the loader's gate: when set,
* the dir cannot be applied from an override on load, so leave it to
* the (no-op) generic comparison instead. */
base_savefile[0] = '\0';
base_savestate[0] = '\0';
savefile_cmdline = retroarch_override_setting_is_set(
RARCH_OVERRIDE_SETTING_SAVE_PATH, NULL);
savestate_cmdline = retroarch_override_setting_is_set(
RARCH_OVERRIDE_SETTING_STATE_PATH, NULL);
{
config_file_t *base_conf = config_file_new_from_path_to_string(
path_get(RARCH_PATH_CONFIG));
if (base_conf)
{
if (config_get_path(base_conf, "savefile_directory",
base_savefile, sizeof(base_savefile))
&& string_is_equal(base_savefile, "default"))
strlcpy(base_savefile, g_defaults.dirs[DEFAULT_DIR_SRAM],
sizeof(base_savefile));
if (config_get_path(base_conf, "savestate_directory",
base_savestate, sizeof(base_savestate))
&& string_is_equal(base_savestate, "default"))
strlcpy(base_savestate, g_defaults.dirs[DEFAULT_DIR_SAVESTATE],
sizeof(base_savestate));
config_file_free(base_conf);
}
config_path_strip_trailing_slash(base_savefile);
config_path_strip_trailing_slash(base_savestate);
}
if (conf->flags & CONF_FILE_FLG_MODIFIED)
RARCH_LOG("[Override] Looking for changed settings...\n");
if (conf)
{
/* Turbo fire settings are saved to remaps and therefore skipped from overrides
* Also savestate slot is saved to runtime logs, so skip it here */
for (i = 0; i < (unsigned)bool_settings_size; i++)
{
if (string_starts_with(bool_settings[i].ident, "input_turbo"))
continue;
if ((*bool_settings[i].ptr) != (*bool_overrides[i].ptr))
{
config_set_string(conf, bool_overrides[i].ident,
(*bool_overrides[i].ptr) ? "true" : "false");
RARCH_DBG("[Override] %s = \"%s\"\n",
bool_overrides[i].ident,
(*bool_overrides[i].ptr) ? "true" : "false");
}
}
for (i = 0; i < (unsigned)int_settings_size; i++)
{
if (string_starts_with(int_settings[i].ident, "input_turbo"))
continue;
if (string_starts_with(int_settings[i].ident, "state_slot"))
continue;
if (cfg_int_get(&int_settings[i])
!= cfg_int_get(&int_overrides[i]))
{
config_set_int(conf, int_overrides[i].ident,
cfg_int_get(&int_overrides[i]));
RARCH_DBG("[Override] %s = \"%d\"\n",
int_overrides[i].ident, cfg_int_get(&int_overrides[i]));
}
}
for (i = 0; i < (unsigned)uint_settings_size; i++)
{
if (string_starts_with(uint_settings[i].ident, "input_turbo"))
continue;
if (cfg_uint_get(&uint_settings[i])
!= cfg_uint_get(&uint_overrides[i]))
{
config_set_int(conf, uint_overrides[i].ident,
cfg_uint_get(&uint_overrides[i]));
RARCH_DBG("[Override] %s = \"%d\"\n",
uint_overrides[i].ident,
cfg_uint_get(&uint_overrides[i]));
}
}
for (i = 0; i < (unsigned)size_settings_size; i++)
{
if ((*size_settings[i].ptr) != (*size_overrides[i].ptr))
{
config_set_int(conf, size_overrides[i].ident,
(int)(*size_overrides[i].ptr));
RARCH_DBG("[Override] %s = \"%d\"\n",
size_overrides[i].ident, *size_overrides[i].ptr);
}
}
for (i = 0; i < (unsigned)float_settings_size; i++)
{
if ((*float_settings[i].ptr) != (*float_overrides[i].ptr))
{
config_set_float(conf, float_overrides[i].ident,
*float_overrides[i].ptr);
RARCH_DBG("[Override] %s = \"%f\"\n",
float_overrides[i].ident, *float_overrides[i].ptr);
}
}
for (i = 0; i < (unsigned)array_settings_size; i++)
{
if (!string_is_equal(array_settings[i].ptr, array_overrides[i].ptr))
{
/* Authentication tokens stored in overrides become stale
* when they expire and get regenerated in the master
* config, forcing users to reauthenticate per override.
* Originally applied to cheevos credentials, now
* generalized to all sensitive settings via
* retroarch-keychain.cfg. */
if (array_settings[i].flags & CFG_BOOL_FLG_SENSITIVE)
continue;
config_set_string(conf, array_overrides[i].ident,
array_overrides[i].ptr);
RARCH_DBG("[Override] %s = \"%s\"\n",
array_overrides[i].ident, array_overrides[i].ptr);
}
}
for (i = 0; i < (unsigned)path_settings_size; i++)
{
const char *cur = path_overrides[i].ptr;
const char *base = path_settings[i].ptr;
char cur_buf[PATH_MAX_LENGTH];
/* Sensitive settings are managed via retroarch-keychain.cfg */
if (path_settings[i].flags & CFG_BOOL_FLG_SENSITIVE)
continue;
/* savefile_directory / savestate_directory alias a global
* buffer, so path_settings[] and path_overrides[] point at the
* same string and the generic comparison never fires. Diff the
* live dir against the on-disk baseline read above instead,
* normalising a trailing separator on both sides. When the
* matching command-line override is set the dir cannot be
* applied from an override on load, so fall through to the
* (equal -> no-op) generic comparison. */
if ( !savefile_cmdline
&& string_is_equal(path_overrides[i].ident, "savefile_directory"))
{
strlcpy(cur_buf, cur ? cur : "", sizeof(cur_buf));
config_path_strip_trailing_slash(cur_buf);
cur = cur_buf;
base = base_savefile;
}
else if (!savestate_cmdline
&& string_is_equal(path_overrides[i].ident, "savestate_directory"))
{
strlcpy(cur_buf, cur ? cur : "", sizeof(cur_buf));
config_path_strip_trailing_slash(cur_buf);
cur = cur_buf;
base = base_savestate;
}
if (!string_is_equal(base, cur))
{
#if TARGET_OS_IPHONE
if (string_is_equal(path_settings[i].ident, "libretro_directory"))
continue;
#endif
config_set_path(conf, path_overrides[i].ident, cur);
RARCH_DBG("[Override] %s = \"%s\"\n",
path_overrides[i].ident, cur);
}
}
#ifdef HAVE_VIDEO_WINDOWS
for (i = 0; i < RETRO_VIDEO_VIEWS_MAX; i++)
{
char cfg[64];
size_t len = snprintf(cfg, sizeof(cfg), "video_screen%u_window_", i + 1);
strlcpy_lit(cfg + len, "mode", sizeof(cfg) - len);
if (settings->uints.video_screen_window_mode[i] != overrides->uints.video_screen_window_mode[i])
config_set_int(conf, cfg, overrides->uints.video_screen_window_mode[i]);
strlcpy_lit(cfg + len, "x", sizeof(cfg) - len);
if (VIDEO_POS_X(settings->uints.video_screen_window_pos[i]) != VIDEO_POS_X(overrides->uints.video_screen_window_pos[i]))
config_set_int(conf, cfg, VIDEO_POS_X(overrides->uints.video_screen_window_pos[i]));
strlcpy_lit(cfg + len, "y", sizeof(cfg) - len);
if (VIDEO_POS_Y(settings->uints.video_screen_window_pos[i]) != VIDEO_POS_Y(overrides->uints.video_screen_window_pos[i]))
config_set_int(conf, cfg, VIDEO_POS_Y(overrides->uints.video_screen_window_pos[i]));
strlcpy_lit(cfg + len, "width", sizeof(cfg) - len);
if (VIDEO_SCALE_W(settings->uints.video_screen_window_dims[i]) != VIDEO_SCALE_W(overrides->uints.video_screen_window_dims[i]))
config_set_int(conf, cfg, VIDEO_SCALE_W(overrides->uints.video_screen_window_dims[i]));
strlcpy_lit(cfg + len, "height", sizeof(cfg) - len);
if (VIDEO_SCALE_H(settings->uints.video_screen_window_dims[i]) != VIDEO_SCALE_H(overrides->uints.video_screen_window_dims[i]))
config_set_int(conf, cfg, VIDEO_SCALE_H(overrides->uints.video_screen_window_dims[i]));
strlcpy_lit(cfg + len, "monitor", sizeof(cfg) - len);
if (settings->uints.video_screen_window_monitor[i] != overrides->uints.video_screen_window_monitor[i])
config_set_int(conf, cfg, overrides->uints.video_screen_window_monitor[i]);
strlcpy_lit(cfg + len, "fullscreen", sizeof(cfg) - len);
if (settings->bools.video_screen_window_fullscreen[i] != overrides->bools.video_screen_window_fullscreen[i])
config_set_string(conf, cfg, overrides->bools.video_screen_window_fullscreen[i] ? "true" : "false");
}
#endif
for (i = 0; i < MAX_USERS; i++)
{
size_t _len;
uint8_t j;
char cfg[64];
char formatted_number[4];
cfg[0] = formatted_number[0] = '\0';
snprintf(formatted_number, sizeof(formatted_number), "%u", i + 1);
if (settings->uints.input_device[i]
!= overrides->uints.input_device[i])
{
size_t _len = strlcpy_lit(cfg, "input_device_p", sizeof(cfg));
strlcpy(cfg + _len, formatted_number, sizeof(cfg) - _len);
config_set_int(conf, cfg, overrides->uints.input_device[i]);
RARCH_DBG("[Override] %s = \"%u\"\n", cfg, overrides->uints.input_device[i]);
}
_len = strlcpy_lit(cfg, "input_player", sizeof(cfg));
_len += strlcpy(cfg + _len, formatted_number, sizeof(cfg) - _len);
if (settings->uints.input_mouse_index[i]
!= overrides->uints.input_mouse_index[i])
{
strlcpy_lit(cfg + _len, "_mouse_index", sizeof(cfg) - _len);
config_set_int(conf, cfg, overrides->uints.input_mouse_index[i]);
RARCH_DBG("[Override] %s = \"%u\"\n", cfg, overrides->uints.input_mouse_index[i]);
}
if (settings->uints.input_keyboard_index[i]
!= overrides->uints.input_keyboard_index[i])
{
strlcpy_lit(cfg + _len, "_keyboard_index", sizeof(cfg) - _len);
config_set_int(conf, cfg, overrides->uints.input_keyboard_index[i]);
RARCH_DBG("[Override] %s = \"%u\"\n", cfg, overrides->uints.input_keyboard_index[i]);
}
if (settings->uints.input_aim_stick[i]
!= overrides->uints.input_aim_stick[i])
{
strlcpy_lit(cfg + _len, "_aim_stick", sizeof(cfg) - _len);
config_set_int(conf, cfg, overrides->uints.input_aim_stick[i]);
RARCH_DBG("[Override] %s = \"%u\"\n", cfg, overrides->uints.input_aim_stick[i]);
}
if (settings->uints.input_touchpad[i]
!= overrides->uints.input_touchpad[i])
{
strlcpy_lit(cfg + _len, "_touchpad", sizeof(cfg) - _len);
config_set_int(conf, cfg, overrides->uints.input_touchpad[i]);
RARCH_DBG("[Override] %s = \"%u\"\n", cfg, overrides->uints.input_touchpad[i]);
}
/* The live value is what the user configured, not a port a
* driver restart handed back. */
if (settings->uints.input_joypad_index[i]
!= input_config_get_saved_joypad_index(i))
{
strlcpy_lit(cfg + _len, "_joypad_index", sizeof(cfg) - _len);
config_set_int(conf, cfg, input_config_get_saved_joypad_index(i));
RARCH_DBG("[Override] %s = \"%u\"\n", cfg, input_config_get_saved_joypad_index(i));
}
if (settings->uints.input_device_reservation_type[i]
!= overrides->uints.input_device_reservation_type[i])
{
strlcpy_lit(cfg + _len, "_device_reservation_type", sizeof(cfg) - _len);
config_set_int(conf, cfg, overrides->uints.input_device_reservation_type[i]);
RARCH_DBG("[Override] %s = \"%u\"\n", cfg, overrides->uints.input_device_reservation_type[i]);
}
for (j = 0; j < RARCH_BIND_LIST_END; j++)
{
const struct retro_keybind *override_bind =
input_config_binds_copy_bind(input_override_binds, i, j);
const struct retro_keybind *config_bind = input_config_bind(i, j);
if ( config_bind->joyaxis != override_bind->joyaxis
|| config_bind->joykey != override_bind->joykey
|| RETRO_KEYBIND_KEY(config_bind) != RETRO_KEYBIND_KEY(override_bind)
|| RETRO_KEYBIND_MBUTTON(config_bind) != RETRO_KEYBIND_MBUTTON(override_bind)
)
input_config_save_keybinds_user_override(conf, i, j, override_bind);
}
}
ret = 0;
switch (type)
{
case OVERRIDE_CORE:
fill_pathname_join_special_ext(override_path,
config_directory, core_name,
core_name,
FILE_PATH_CONFIG_EXTENSION,
sizeof(override_path));
break;
case OVERRIDE_GAME:
game_name = path_basename_nocompression(rarch_path_basename);
fill_pathname_join_special_ext(override_path,
config_directory, core_name,
game_name,
FILE_PATH_CONFIG_EXTENSION,
sizeof(override_path));
break;
case OVERRIDE_CONTENT_DIR:
{
char content_dir_name[DIR_MAX_LENGTH];
content_dir_name[0] = '\0';
fill_pathname_parent_dir_name(content_dir_name,
rarch_path_basename, sizeof(content_dir_name));
fill_pathname_join_special_ext(override_path,
config_directory, core_name,
content_dir_name,
FILE_PATH_CONFIG_EXTENSION,
sizeof(override_path));
}
break;
case OVERRIDE_AS:
fill_pathname_join_special_ext(override_path,
config_directory, core_name,
path,
FILE_PATH_CONFIG_EXTENSION,
sizeof(override_path));
break;
case OVERRIDE_NONE:
default:
break;
}
if (!(conf->flags & CONF_FILE_FLG_MODIFIED) && !remove)
ret = -1;
if (*override_path)
{
if (!(conf->flags & CONF_FILE_FLG_MODIFIED) && !remove)
if (path_is_valid(override_path))
remove = true;
if ( remove
&& path_is_valid(override_path))
{
if (filestream_delete(override_path) == 0)
{
ret = -1;
RARCH_LOG("[Override] %s: \"%s\".\n",
"Deleted", override_path);
}
}
else if (conf->flags & CONF_FILE_FLG_MODIFIED)
{
ret = config_file_write(conf, override_path, true);
if (ret)
{
path_set(RARCH_PATH_CONFIG_OVERRIDE, override_path);
RARCH_LOG("[Override] %s: \"%s\".\n",
"Saved", override_path);
}
else
{
RARCH_LOG("[Override] %s: \"%s\".\n",
"Failed to save", override_path);
}
}
}
config_file_free(conf);
}
/* Since config_load_file resets binds, restore overrides back to current binds */
input_config_binds_copy_restore(input_override_binds);
if (bool_settings)
free(bool_settings);
if (bool_overrides)
free(bool_overrides);
if (int_settings)
free(int_settings);
if (uint_settings)
free(uint_settings);
if (size_settings)
free(size_settings);
if (int_overrides)
free(int_overrides);
if (uint_overrides)
free(uint_overrides);
if (float_settings)
free(float_settings);
if (float_overrides)
free(float_overrides);
if (array_settings)
free(array_settings);
if (array_overrides)
free(array_overrides);
if (path_settings)
free(path_settings);
if (path_overrides)
free(path_overrides);
if (size_overrides)
free(size_overrides);
free(settings);
input_config_binds_copy_free(input_override_binds);
return ret;
}
/* Replaces currently loaded configuration file with
* another one. Will load a dummy core to flush state
* properly. */
bool config_replace(bool config_replace_save_on_exit, char *path)
{
content_ctx_info_t content_info = {0};
const char *rarch_path_config = path_get(RARCH_PATH_CONFIG);
#ifdef __PS3__
char imported_path[PATH_MAX_LENGTH];
if (!ps3_config_import(path, imported_path, sizeof(imported_path)))
{
RARCH_ERR("[Config] Failed to import configuration: %s\n", path);
return false;
}
path = imported_path;
#endif
/* If config file to be replaced is the same as the
* current config file, exit. */
if (string_is_equal(path, rarch_path_config))
return false;
if (config_replace_save_on_exit && !path_is_empty(RARCH_PATH_CONFIG))
config_save_file(rarch_path_config);
path_set(RARCH_PATH_CONFIG, path);
retroarch_ctl(RARCH_CTL_UNSET_BLOCK_CONFIG_READ, NULL);
/* Load core in new (salamander) config. */
path_clear(RARCH_PATH_CORE);
return task_push_start_dummy_core(&content_info);
}
/**
* input_remapping_load_file:
* @data : Path to config file.
*
* Loads a remap file from disk to memory.
*
* Returns: true (1) if successful, otherwise false (0).
**/
bool input_remapping_load_file(void *data, const char *path)
{
unsigned i, j;
config_file_t *conf = (config_file_t*)data;
settings_t *settings = config_st;
runloop_state_t *runloop_st = runloop_state_get_ptr();
char key_strings[RARCH_ANALOG_BIND_LIST_END][8] =
{
"b", "y", "select", "start",
"up", "down", "left", "right",
"a", "x", "l", "r",
"l2", "r2", "l3", "r3",
"l_x+", "l_x-", "l_y+", "l_y-",
"r_x+", "r_x-", "r_y+", "r_y-"
};
if ( !conf
|| (!path || !*path))
return false;
/* the remaps are part of what a port's mapping is made from */
input_config_binds_changed();
if (runloop_st->name.remapfile && *runloop_st->name.remapfile)
input_remapping_deinit(false);
input_remapping_set_defaults(false);
runloop_st->name.remapfile = strdup(path);
for (i = 0; i < MAX_USERS; i++)
{
size_t _len;
char prefix[16];
char s1[32], s2[32], s3[32];
char formatted_number[4];
formatted_number[0] = '\0';
snprintf(formatted_number, sizeof(formatted_number), "%u", i + 1);
_len = strlcpy_lit(prefix, "input_player", sizeof(prefix));
strlcpy(prefix + _len, formatted_number, sizeof(prefix) - _len);
_len = strlcpy(s1, prefix, sizeof(s1));
strlcpy_lit(s1 + _len, "_btn", sizeof(s1) - _len);
_len = strlcpy(s2, prefix, sizeof(s2));
strlcpy_lit(s2 + _len, "_key", sizeof(s2) - _len);
_len = strlcpy(s3, prefix, sizeof(s3));
strlcpy_lit(s3 + _len, "_stk", sizeof(s3) - _len);
for (j = 0; j < RARCH_ANALOG_BIND_LIST_END; j++)
{
const char *key_string = key_strings[j];
if (j < RARCH_FIRST_CUSTOM_BIND)
{
char ident[128];
int _remap = -1;
fill_pathname_join_delim(ident, s1,
key_string, '_', sizeof(ident));
if (config_get_int(conf, ident, &_remap))
{
if (_remap == -1)
_remap = RARCH_UNMAPPED;
/* Reject .rmp values outside the legitimate range.
* Runtime use sites in input_driver.c index a
* fixed-size analog_value[][8] array using
* (_remap - RARCH_FIRST_CUSTOM_BIND); pre-this-patch
* a malformed .rmp could supply an arbitrary int
* here and OOB-write up to ~1007 elements past
* analog_value, corrupting adjacent input-state
* fields and (for the last user) the keys[] mask.
* Legal values are any concrete bind index in
* [0, RARCH_ANALOG_BIND_LIST_END) plus the
* RARCH_UNMAPPED sentinel. */
if ( _remap != (int)RARCH_UNMAPPED
&& (_remap < 0 || _remap >= (int)RARCH_ANALOG_BIND_LIST_END))
_remap = RARCH_UNMAPPED;
configuration_set_uint(settings,
settings->uints.input_remap_ids[i][j], _remap);
}
fill_pathname_join_delim(ident, s2,
key_string, '_', sizeof(ident));
_remap = -1;
if (!config_get_int(conf, ident, &_remap))
_remap = RETROK_UNKNOWN;
if ( _remap < (int)RETROK_UNKNOWN
|| _remap >= (int)RETROK_LAST)
_remap = RETROK_UNKNOWN;
configuration_set_uint(settings,
settings->uints.input_keymapper_ids[i][j], _remap);
}
else
{
char ident[256];
int _remap = -1;
fill_pathname_join_delim(ident, s3,
key_string, '_', sizeof(ident));
if (config_get_int(conf, ident, &_remap))
{
if (_remap == -1)
_remap = RARCH_UNMAPPED;
/* See the matching comment in the button-branch
* above: same OOB-write primitive, same fix. */
if ( _remap != (int)RARCH_UNMAPPED
&& (_remap < 0 || _remap >= (int)RARCH_ANALOG_BIND_LIST_END))
_remap = RARCH_UNMAPPED;
configuration_set_uint(settings,
settings->uints.input_remap_ids[i][j], _remap);
}
fill_pathname_join_delim(ident, s2,
key_string, '_', sizeof(ident));
_remap = -1;
if (!config_get_int(conf, ident, &_remap))
_remap = RETROK_UNKNOWN;
if ( _remap < (int)RETROK_UNKNOWN
|| _remap >= (int)RETROK_LAST)
_remap = RETROK_UNKNOWN;
configuration_set_uint(settings,
settings->uints.input_keymapper_ids[i][j], _remap);
}
}
_len = strlcpy_lit(s1, "input_libretro_device_p", sizeof(s1));
strlcpy(s1 + _len, formatted_number, sizeof(s1) - _len);
CONFIG_GET_INT_BASE(conf, settings, uints.input_libretro_device[i], s1);
_len = strlcpy(s1, prefix, sizeof(s1));
strlcpy_lit(s1 + _len, "_analog_dpad_mode", sizeof(s1) - _len);
CONFIG_GET_INT_BASE(conf, settings, uints.input_analog_dpad_mode[i], s1);
_len = strlcpy_lit(s1, "input_remap_port_p", sizeof(s1));
strlcpy(s1 + _len, formatted_number, sizeof(s1) - _len);
CONFIG_GET_INT_BASE(conf, settings, uints.input_remap_ports[i], s1);
/* The mapped port indexes per-port arrays (libretro device,
* input descriptors, analog requests). MAX_USERS is 'None':
* the user feeds no core port, and no array is indexed. */
if (settings->uints.input_remap_ports[i] > MAX_USERS)
settings->uints.input_remap_ports[i] = i;
}
/* Turbo fire settings */
CONFIG_GET_BOOL_BASE(conf, settings, bools.input_turbo_enable, "input_turbo_enable");
CONFIG_GET_BOOL_BASE(conf, settings, bools.input_turbo_allow_dpad, "input_turbo_allow_dpad");
CONFIG_GET_INT_BASE(conf, settings, uints.input_turbo_mode, "input_turbo_mode");
CONFIG_GET_INT_BASE(conf, settings, ints.input_turbo_bind, "input_turbo_bind");
CONFIG_GET_INT_BASE(conf, settings, uints.input_turbo_button, "input_turbo_button");
CONFIG_GET_INT_BASE(conf, settings, uints.input_turbo_period, "input_turbo_period");
CONFIG_GET_INT_BASE(conf, settings, uints.input_turbo_duty_cycle, "input_turbo_duty_cycle");
config_sanitize_turbo_binds(settings);
input_remapping_update_port_map();
/* Whenever a remap file is loaded, subsequent
* changes to global remap-related parameters
* must be reset at the next core deinitialisation */
input_driver_set_remapping_cache_active();
return true;
}
/**
* input_remapping_save_file:
* @path : Path to remapping file.
*
* Saves remapping values to file.
*
* Returns: true (1) if successful, otherwise false (0).
**/
bool input_remapping_save_file(const char *path)
{
bool ret;
unsigned i, j;
char remap_file_dir[DIR_MAX_LENGTH];
char key_strings[RARCH_ANALOG_BIND_LIST_END][8] =
{
"b", "y", "select", "start",
"up", "down", "left", "right",
"a", "x", "l", "r",
"l2", "r2", "l3", "r3",
"l_x+", "l_x-", "l_y+", "l_y-",
"r_x+", "r_x-", "r_y+", "r_y-"
};
config_file_t *conf = NULL;
runloop_state_t *runloop_st = runloop_state_get_ptr();
settings_t *settings = config_st;
unsigned max_users = settings->uints.input_max_users;
if (!path || !*path)
return false;
/* Create output directory, if required */
fill_pathname_parent_dir(remap_file_dir, path,
sizeof(remap_file_dir));
if ( *remap_file_dir
&& !path_is_directory(remap_file_dir)
&& !path_mkdir(remap_file_dir))
return false;
/* Attempt to load file */
if (!(conf = config_file_new_alloc()))
return false;
for (i = 0; i < MAX_USERS; i++)
{
size_t _len;
bool skip_port = true;
char formatted_number[4];
char prefix[16];
char s1[32];
char s2[32];
char s3[32];
formatted_number[0] = '\0';
/* We must include all mapped ports + all those
* with an index less than max_users */
if (i < max_users)
skip_port = false;
else
{
/* Check whether current port is mapped
* to an input device */
for (j = 0; j < max_users; j++)
{
if (i == settings->uints.input_remap_ports[j])
{
skip_port = false;
break;
}
}
}
if (skip_port)
continue;
_len = snprintf(formatted_number, sizeof(formatted_number), "%u", i + 1);
if (_len >= sizeof(formatted_number))
{
RARCH_ERR("[Config] Unexpectedly high number of users.");
break;
}
_len = strlcpy_lit(prefix, "input_player", sizeof(prefix));
strlcpy(prefix + _len, formatted_number, sizeof(prefix) - _len);
_len = strlcpy(s1, prefix, sizeof(s1));
strlcpy_lit(s1 + _len, "_btn", sizeof(s1) - _len);
_len = strlcpy(s2, prefix, sizeof(s2));
strlcpy_lit(s2 + _len, "_key", sizeof(s2) - _len);
_len = strlcpy(s3, prefix, sizeof(s3));
strlcpy_lit(s3 + _len, "_stk", sizeof(s3) - _len);
for (j = 0; j < RARCH_FIRST_CUSTOM_BIND; j++)
{
char _ident[128];
const char *key_string = key_strings[j];
unsigned remap_id = settings->uints.input_remap_ids[i][j];
unsigned keymap_id = settings->uints.input_keymapper_ids[i][j];
fill_pathname_join_delim(_ident, s1,
key_string, '_', sizeof(_ident));
/* Only save modified button values */
if (remap_id == j)
config_unset(conf, _ident);
else
{
if (remap_id == RARCH_UNMAPPED)
{
if (!runloop_st->system.input_desc_btn[i][j] ||
!*runloop_st->system.input_desc_btn[i][j])
config_unset(conf, _ident);
else
config_set_int(conf, _ident, -1);
}
else
config_set_int(conf, _ident,
settings->uints.input_remap_ids[i][j]);
}
fill_pathname_join_delim(_ident, s2,
key_string, '_', sizeof(_ident));
/* Only save non-empty keymapper values */
if (keymap_id == RETROK_UNKNOWN)
config_unset(conf, _ident);
else
config_set_int(conf, _ident,
settings->uints.input_keymapper_ids[i][j]);
}
for (j = RARCH_FIRST_CUSTOM_BIND; j < RARCH_ANALOG_BIND_LIST_END; j++)
{
char _ident[128];
const char *key_string = key_strings[j];
unsigned remap_id = settings->uints.input_remap_ids[i][j];
unsigned keymap_id = settings->uints.input_keymapper_ids[i][j];
fill_pathname_join_delim(_ident, s3,
key_string, '_', sizeof(_ident));
/* Only save modified button values */
if (remap_id == j)
config_unset(conf, _ident);
else
{
if (remap_id == RARCH_UNMAPPED)
{
if (!runloop_st->system.input_desc_btn[i][j]
|| !*runloop_st->system.input_desc_btn[i][j])
config_unset(conf, _ident);
else
config_set_int(conf, _ident, -1);
}
else
config_set_int(conf, _ident,
settings->uints.input_remap_ids[i][j]);
}
fill_pathname_join_delim(_ident, s2,
key_string, '_', sizeof(_ident));
/* Only save non-empty keymapper values */
if (keymap_id == RETROK_UNKNOWN)
config_unset(conf, _ident);
else
config_set_int(conf, _ident,
settings->uints.input_keymapper_ids[i][j]);
}
_len = strlcpy_lit(s1, "input_libretro_device_p", sizeof(s1));
strlcpy(s1 + _len, formatted_number, sizeof(s1) - _len);
config_set_int(conf, s1, input_config_get_device(i));
_len = strlcpy(s1, prefix, sizeof(s1));
strlcpy_lit(s1 + _len, "_analog_dpad_mode", sizeof(s1) - _len);
config_set_int(conf, s1, settings->uints.input_analog_dpad_mode[i]);
/* a port a first press gave is not the user's choice: left
* out, so the next press decides again */
if (!input_first_press_assigned(i))
{
_len = strlcpy_lit(s1, "input_remap_port_p", sizeof(s1));
strlcpy(s1 + _len, formatted_number, sizeof(s1) - _len);
config_set_int(conf, s1, settings->uints.input_remap_ports[i]);
}
}
/* Turbo fire settings */
config_set_string(conf, "input_turbo_enable", settings->bools.input_turbo_enable ? "true" : "false");
config_set_string(conf, "input_turbo_allow_dpad", settings->bools.input_turbo_allow_dpad ? "true" : "false");
config_set_int(conf, "input_turbo_mode", settings->uints.input_turbo_mode);
config_set_int(conf, "input_turbo_bind", settings->ints.input_turbo_bind);
config_set_int(conf, "input_turbo_button", settings->uints.input_turbo_button);
config_set_int(conf, "input_turbo_period", settings->uints.input_turbo_period);
config_set_int(conf, "input_turbo_duty_cycle", settings->uints.input_turbo_duty_cycle);
ret = config_file_write(conf, path, true);
config_file_free(conf);
/* Cache remap file path
* > Must guard against the case where
* runloop_st->name.remapfile itself
* is passed to this function... */
if (runloop_st->name.remapfile != path)
{
if (runloop_st->name.remapfile)
free(runloop_st->name.remapfile);
runloop_st->name.remapfile = strdup(path);
}
return ret;
}
#endif
#if !defined(HAVE_DYNAMIC)
/* Salamander config file contains a single
* entry (libretro_path), which is linked to
* RARCH_PATH_CORE
* > Used to select which core to load
* when launching a salamander build */
static bool config_file_salamander_get_path(char *s, size_t len)
{
const char *rarch_config_path = g_defaults.path_config;
if (rarch_config_path && *rarch_config_path)
fill_pathname_resolve_relative(s,
rarch_config_path,
FILE_PATH_SALAMANDER_CONFIG,
len);
else
strlcpy(s, FILE_PATH_SALAMANDER_CONFIG, len);
return (s && *s);
}
void config_load_file_salamander(void)
{
char config_path[PATH_MAX_LENGTH];
config_file_t *config = NULL;
config_path[0] = '\0';
/* Get config file path */
if (!config_file_salamander_get_path(
config_path, sizeof(config_path)))
return;
/* Open config file */
if (!(config = config_file_new_from_path_to_string(config_path)))
return;
/* Read 'libretro_path' value and update
* RARCH_PATH_CORE */
RARCH_LOG("[Config] Loading salamander config from: \"%s\".\n",
config_path);
if (config_get_path(config, "libretro_path",
config_path, sizeof(config_path))
&& *config_path
&& !string_is_equal(config_path, "builtin"))
path_set(RARCH_PATH_CORE, config_path);
config_file_free(config);
}
void config_save_file_salamander(void)
{
config_file_t *conf = NULL;
const char *libretro_path = path_get(RARCH_PATH_CORE);
char config_path[PATH_MAX_LENGTH];
config_path[0] = '\0';
if ( (!libretro_path || !*libretro_path)
|| string_is_equal(libretro_path, "builtin"))
return;
/* Get config file path */
if (!config_file_salamander_get_path(
config_path, sizeof(config_path)))
return;
/* Open config file */
if ( !(conf = config_file_new_from_path_to_string(config_path))
&& !(conf = config_file_new_alloc())
)
{
if (conf)
config_file_free(conf);
return;
}
/* Update config file */
config_set_path(conf, "libretro_path", libretro_path);
/* Save config file
* > Only one entry - no need to sort */
if (config_file_write(conf, config_path, false))
RARCH_LOG("[Config] Saving salamander config to: \"%s\".\n",
config_path);
else
RARCH_ERR("[Config] Failed to create new salamander config file in: \"%s\".\n",
config_path);
if (conf)
config_file_free(conf);
}
#endif
bool input_config_bind_map_get_valid(unsigned bind_index)
{
const struct input_bind_map *keybind =
(const struct input_bind_map*)INPUT_CONFIG_BIND_MAP_GET(bind_index);
return (keybind && keybind->valid);
}
unsigned input_config_bind_map_get_meta(unsigned bind_index)
{
const struct input_bind_map *keybind =
(const struct input_bind_map*)INPUT_CONFIG_BIND_MAP_GET(bind_index);
if (!keybind)
return 0;
return keybind->meta;
}
const char *input_config_bind_map_get_base(unsigned bind_index)
{
const struct input_bind_map *keybind =
(const struct input_bind_map*)INPUT_CONFIG_BIND_MAP_GET(bind_index);
if (!keybind)
return NULL;
return keybind->base;
}
const char *input_config_bind_map_get_desc(unsigned bind_index)
{
const struct input_bind_map *keybind =
(const struct input_bind_map*)INPUT_CONFIG_BIND_MAP_GET(bind_index);
if (!keybind)
return NULL;
return msg_hash_to_str(keybind->desc);
}
uint8_t input_config_bind_map_get_retro_key(unsigned bind_index)
{
const struct input_bind_map *keybind =
(const struct input_bind_map*)INPUT_CONFIG_BIND_MAP_GET(bind_index);
if (!keybind)
return 0;
return keybind->retro_key;
}
void input_config_reset_autoconfig_binds(unsigned port)
{
unsigned i;
input_sensor_map_t map;
if (port >= MAX_USERS)
return;
input_autoconf_binds_none(port);
input_autoconf_bind_names_free(port);
/* Reset sensor axis map to default identity mapping */
for (i = 0; i < 6; i++)
{
map.axes[i].source = (int8_t)i;
map.axes[i].sign = 1;
}
input_driver_set_sensor_map(port, &map);
/* counted again once written: this can run on a task's thread while
* the frontend polls */
input_config_binds_changed();
}
void input_config_set_autoconfig_binds(unsigned port, void *data)
{
static const char *sensor_keys[6] = {
"input_sensor_accel_x", "input_sensor_accel_y", "input_sensor_accel_z",
"input_sensor_gyro_x", "input_sensor_gyro_y", "input_sensor_gyro_z"
};
size_t i;
config_file_t *config = (config_file_t*)data;
struct retro_keybind *binds = NULL;
const input_sensor_map_t *current;
input_sensor_map_t map;
if ((port >= MAX_USERS) || !config)
return;
binds = input_autoconf_bind_edit(port, 0);
for (i = 0; i < RARCH_BIND_LIST_END; i++)
{
const struct input_bind_map *keybind =
(const struct input_bind_map*)INPUT_CONFIG_BIND_MAP_GET(i);
if (keybind)
{
char str[256];
const char *base = keybind->base;
/* the names the profile gives it, if it gives any */
struct input_bind_label got = { NULL, NULL };
fill_pathname_join_delim(str, "input", base, '_', sizeof(str));
input_config_parse_joy_button(str, config, "input", base, &binds[i],
&got);
input_config_parse_joy_axis (str, config, "input", base, &binds[i],
&got);
input_autoconf_bind_names_take(port, (unsigned)i, &got);
}
}
/* Parse sensor axis map overrides from autoconfig profile */
if (!(current = input_config_get_sensor_map(port)))
return;
map = *current;
for (i = 0; i < 6; i++)
{
char tmp[16];
tmp[0] = '\0';
if (config_get_array(config, sensor_keys[i], tmp, sizeof(tmp)))
{
if (tmp[0] == '+' || tmp[0] == '-')
{
int code = (int)strtol(tmp + 1, NULL, 0);
if (code >= 0 && code <= 5)
{
map.axes[i].source = (int8_t)code;
map.axes[i].sign = (tmp[0] == '-') ? -1 : 1;
}
}
}
}
input_driver_set_sensor_map(port, &map);
/* counted again once written: this can run on a task's thread while
* the frontend polls */
input_config_binds_changed();
}
void input_config_parse_mouse_button(char *s,
void *conf_data, const char *prefix,
const char *btn, void *bind_data)
{
int val;
char tmp[64], key[64];
config_file_t *conf = (config_file_t*)conf_data;
struct retro_keybind *bind = (struct retro_keybind*)bind_data;
tmp[0] = '\0';
fill_pathname_join_delim(key, s, "mbtn", '_', sizeof(key));
if (config_get_array(conf, key, tmp, sizeof(tmp)))
{
RETRO_KEYBIND_SET_MBUTTON(bind, NO_BTN);
if (tmp[0]=='w')
{
switch (tmp[1])
{
case 'u':
RETRO_KEYBIND_SET_MBUTTON(bind, RETRO_DEVICE_ID_MOUSE_WHEELUP);
break;
case 'd':
RETRO_KEYBIND_SET_MBUTTON(bind, RETRO_DEVICE_ID_MOUSE_WHEELDOWN);
break;
case 'h':
switch (tmp[2])
{
case 'u':
RETRO_KEYBIND_SET_MBUTTON(bind, RETRO_DEVICE_ID_MOUSE_HORIZ_WHEELUP);
break;
case 'd':
RETRO_KEYBIND_SET_MBUTTON(bind, RETRO_DEVICE_ID_MOUSE_HORIZ_WHEELDOWN);
break;
}
break;
}
}
else
{
val = atoi(tmp);
switch (val)
{
case 1:
RETRO_KEYBIND_SET_MBUTTON(bind, RETRO_DEVICE_ID_MOUSE_LEFT);
break;
case 2:
RETRO_KEYBIND_SET_MBUTTON(bind, RETRO_DEVICE_ID_MOUSE_RIGHT);
break;
case 3:
RETRO_KEYBIND_SET_MBUTTON(bind, RETRO_DEVICE_ID_MOUSE_MIDDLE);
break;
case 4:
RETRO_KEYBIND_SET_MBUTTON(bind, RETRO_DEVICE_ID_MOUSE_BUTTON_4);
break;
case 5:
RETRO_KEYBIND_SET_MBUTTON(bind, RETRO_DEVICE_ID_MOUSE_BUTTON_5);
break;
}
}
}
}
void input_config_parse_joy_axis(char *s,
void *conf_data, const char *prefix,
const char *axis, void *bind_data, void *label_data)
{
struct input_bind_label *label = (struct input_bind_label*)label_data;
char tmp[64];
char key[64];
config_file_t *conf = (config_file_t*)conf_data;
struct retro_keybind *bind = (struct retro_keybind*)bind_data;
struct config_entry_list *tmp_a = NULL;
tmp[0] = '\0';
fill_pathname_join_delim(key, s, "axis", '_', sizeof(key));
if (config_get_array(conf, key, tmp, sizeof(tmp)))
{
if ( tmp[0] == 'n'
&& tmp[1] == 'u'
&& tmp[2] == 'l'
&& tmp[3] == '\0'
)
bind->joyaxis = AXIS_NONE;
else if
( tmp[0] != '\0'
&& tmp[1] != '\0'
&& (*tmp == '+'
|| *tmp == '-'))
{
int i_axis = (int)strtol(tmp + 1, NULL, 0);
if (*tmp == '+')
bind->joyaxis = AXIS_POS(i_axis);
else
bind->joyaxis = AXIS_NEG(i_axis);
RETRO_KEYBIND_SET_VALID(bind, true);
}
}
fill_pathname_join_delim(key, s,
"axis_label", '_', sizeof(key));
tmp_a = config_get_entry(conf, key);
if (tmp_a && tmp_a->value && *tmp_a->value)
{
if (label->joyaxis && *label->joyaxis)
free(label->joyaxis);
label->joyaxis = strdup(tmp_a->value);
}
}
static uint16_t input_config_parse_hat(const char *dir)
{
if ( dir[0] == 'u'
&& dir[1] == 'p'
&& dir[2] == '\0'
)
return HAT_UP_MASK;
else if (
dir[0] == 'd'
&& dir[1] == 'o'
&& dir[2] == 'w'
&& dir[3] == 'n'
&& dir[4] == '\0'
)
return HAT_DOWN_MASK;
else if (
dir[0] == 'l'
&& dir[1] == 'e'
&& dir[2] == 'f'
&& dir[3] == 't'
&& dir[4] == '\0'
)
return HAT_LEFT_MASK;
else if (
dir[0] == 'r'
&& dir[1] == 'i'
&& dir[2] == 'g'
&& dir[3] == 'h'
&& dir[4] == 't'
&& dir[5] == '\0'
)
return HAT_RIGHT_MASK;
return 0;
}
void input_config_parse_joy_button(
char *s,
void *data, const char *prefix,
const char *btn, void *bind_data, void *label_data)
{
struct input_bind_label *label = (struct input_bind_label*)label_data;
char tmp[64], key[64];
config_file_t *conf = (config_file_t*)data;
struct retro_keybind *bind = (struct retro_keybind*)bind_data;
struct config_entry_list *tmp_a = NULL;
tmp[0] = '\0';
fill_pathname_join_delim(key, s, "btn", '_', sizeof(key));
if (config_get_array(conf, key, tmp, sizeof(tmp)))
{
btn = tmp;
if ( btn[0] == 'n'
&& btn[1] == 'u'
&& btn[2] == 'l'
&& btn[3] == '\0'
)
bind->joykey = NO_BTN;
else
{
if (*btn == 'h')
{
const char *str = btn + 1;
/* Parse hat? */
if (str && *str >= '0' && *str <= '9')
{
char *dir = NULL;
uint16_t hat = strtoul(str, &dir, 0);
uint16_t hat_dir = dir ? input_config_parse_hat(dir) : 0;
if (hat_dir)
bind->joykey = HAT_MAP(hat, hat_dir);
}
}
else
bind->joykey = strtoull(tmp, NULL, 0);
RETRO_KEYBIND_SET_VALID(bind, true);
}
}
fill_pathname_join_delim(key, s,
"btn_label", '_', sizeof(key));
tmp_a = config_get_entry(conf, key);
if (tmp_a && tmp_a->value && *tmp_a->value)
{
if (label->joykey && *label->joykey)
free(label->joykey);
label->joykey = strdup(tmp_a->value);
}
}
void retroarch_config_deinit(void)
{
if (config_st)
free(config_st);
config_st = NULL;
#if defined(HAVE_CONFIGFILE) && defined(HAVE_KEYCHAIN)
keychain_deinit();
#endif
}
void retroarch_config_init(void)
{
if (!config_st)
config_st = (settings_t*)calloc(1, sizeof(settings_t));
}