Configuration backend improvements Pt. 1 (#1762)

* Convert all setting keys in settings.h into hana strings

* Derive libretro setting keys from common/settings.h hana strings

* settings.h: Reduce code repetition in key definitions via macro

* Implemented mechanism to pass our C++ setting keys to Android/Kotlin

None of the Android keys have been moved over as of this commit, this is just prep work

* jni_settings_keys.cpp.in: Removed redundant code

* Migrate (almost) all Android setting string keys over to SettingKeys

Also some slight cleanup

* Updated license headers

* Fixed top custom width erroneously being used in place of top custom height

* Migrate (probably) all setting string keys to Settings::QKeys

* Migrated several previously missed string keys to generated keys

* SettingKeys.kt: Visually seperate shared and Android-exclusive keys, similar to GenerateSettingKeys.cmake

* android: sdl2_config --> android_config

Not sure why these values are named this way. Hold-over from SDL2 frontend?

* android: Generate and validate default config.ini dynamically

* Settings: Assume C-style string keys by default

Relative to the previous commit, the following names have changed:
- Settings::Keys --> Settings::HKeys
- Settings::CKeys --> Settings::Keys

* default_ini.h: Fixed formatting warning

* Comment cleanup

* android: Fixed compilation failure due to incorrect namespace

* config.cpp: Use ASSERT_MSG instead of LOG_ERROR and ASSERT(false)
This commit is contained in:
OpenSauce 2026-03-02 23:26:43 +00:00 committed by GitHub
parent fe2f637467
commit 068d6598bc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
29 changed files with 1286 additions and 687 deletions

View File

@ -0,0 +1,275 @@
## This file should be the *only place* where setting keys exist as strings.
# All references to setting strings should be derived from the
# `setting_keys.h` and `jni_setting_keys.cpp` files generated here.
# !!! Changes made here should be mirrored to SettingKeys.kt if used on Android
# Shared setting keys (multi-platform)
foreach(KEY IN ITEMS
"use_artic_base_controller"
"enable_gamemode"
"use_cpu_jit"
"cpu_clock_percentage"
"is_new_3ds"
"lle_applets"
"deterministic_async_operations"
"enable_required_online_lle_modules"
"use_virtual_sd"
"use_custom_storage"
"compress_cia_installs"
"region_value"
"init_clock"
"init_time"
"init_time_offset"
"init_ticks_type"
"init_ticks_override"
"plugin_loader"
"allow_plugin_loader"
"steps_per_hour"
"apply_region_free_patch"
"graphics_api"
"physical_device"
"use_gles"
"renderer_debug"
"dump_command_buffers"
"spirv_shader_gen"
"disable_spirv_optimizer"
"async_shader_compilation"
"async_presentation"
"use_hw_shader"
"use_disk_shader_cache"
"shaders_accurate_mul"
"use_vsync"
"use_display_refresh_rate_detection"
"use_shader_jit"
"resolution_factor"
"frame_limit"
"turbo_limit"
"texture_filter"
"texture_sampling"
"delay_game_render_thread_us"
"layout_option"
"swap_screen"
"upright_screen"
"secondary_display_layout"
"large_screen_proportion"
"screen_gap"
"small_screen_position"
"custom_top_x"
"custom_top_y"
"custom_top_width"
"custom_top_height"
"custom_bottom_x"
"custom_bottom_y"
"custom_bottom_width"
"custom_bottom_height"
"custom_second_layer_opacity"
"aspect_ratio"
"screen_top_stretch"
"screen_top_leftright_padding"
"screen_top_topbottom_padding"
"screen_bottom_stretch"
"screen_bottom_leftright_padding"
"screen_bottom_topbottom_padding"
"portrait_layout_option"
"custom_portrait_top_x"
"custom_portrait_top_y"
"custom_portrait_top_width"
"custom_portrait_top_height"
"custom_portrait_bottom_x"
"custom_portrait_bottom_y"
"custom_portrait_bottom_width"
"custom_portrait_bottom_height"
"bg_red"
"bg_green"
"bg_blue"
"render_3d"
"factor_3d"
"swap_eyes_3d"
"render_3d_which_display"
"mono_render_option"
"cardboard_screen_size"
"cardboard_x_shift"
"cardboard_y_shift"
"filter_mode"
"pp_shader_name"
"anaglyph_shader_name"
"dump_textures"
"custom_textures"
"preload_textures"
"async_custom_loading"
"disable_right_eye_render"
"audio_emulation"
"enable_audio_stretching"
"enable_realtime_audio"
"volume"
"output_type"
"output_device"
"input_type"
"input_device"
"delay_start_for_lle_modules"
"use_gdbstub"
"gdbstub_port"
"instant_debug_log"
"enable_rpc_server"
"log_filter"
"log_regex_filter"
"use_integer_scaling"
"layouts_to_cycle"
"camera_inner_flip"
"camera_outer_left_flip"
"camera_outer_right_flip"
"camera_inner_name"
"camera_inner_config"
"camera_outer_left_name"
"camera_outer_left_config"
"camera_outer_right_name"
"camera_outer_right_config"
"video_encoder"
"video_encoder_options"
"video_bitrate"
"audio_encoder"
"audio_encoder_options"
"audio_bitrate"
"last_artic_base_addr"
"motion_device"
"touch_device"
"udp_input_address"
"udp_input_port"
"udp_pad_index"
"record_frame_times"
"language" # FIXME: DUPLICATE KEY (libretro equivalent: language_value)
"web_api_url"
"citra_username"
"citra_token"
)
set(SETTING_KEY_LIST "${SETTING_KEY_LIST}\n\"${KEY}\",")
set(SETTING_KEY_DEFINITIONS "${SETTING_KEY_DEFINITIONS}\nDEFINE_KEY(${KEY})")
if (ANDROID)
string(REPLACE "_" "_1" KEY_JNI_ESCAPED ${KEY})
set(JNI_SETTING_KEY_DEFINITIONS "${JNI_SETTING_KEY_DEFINITIONS}
JNI_DEFINE_KEY(${KEY}, ${KEY_JNI_ESCAPED})")
endif()
endforeach()
# Qt exclusive setting keys
# Note: A lot of these are very generic because our Qt settings are currently put under groups:
# E.g. UILayout\geometry
# TODO: We should probably get rid of these groups and use complete keys at some point. -OS
# FIXME: Some of these settings don't use the standard snake_case. When we can migrate, address that. -OS
if (ENABLE_QT)
foreach(KEY IN ITEMS
"nickname"
"ip"
"port"
"room_nickname"
"room_name"
"room_port"
"host_type"
"max_player"
"room_description"
"multiplayer_filter_text"
"multiplayer_filter_games_owned"
"multiplayer_filter_hide_empty"
"multiplayer_filter_hide_full"
"username_ban_list"
"username"
"ip_ban_list"
"romsPath"
"symbolsPath"
"movieRecordPath"
"moviePlaybackPath"
"videoDumpingPath"
"gameListRootDir"
"gameListDeepScan"
"path"
"deep_scan"
"expanded"
"recentFiles"
"output_format"
"format_options"
"theme"
"program_id"
"geometry"
"state"
"geometryRenderWindow"
"gameListHeaderState"
"microProfileDialogGeometry"
"name"
"bind"
"profile"
"use_touch_from_button"
"touch_from_button_map"
"touch_from_button_maps" # Why are these two so similar? Basically typo bait
"nand_directory"
"sdmc_directory"
"game_id"
"KeySeq"
"gamedirs"
"libvorbis"
"Context"
"favorites"
)
set(SETTING_KEY_LIST "${SETTING_KEY_LIST}\n\"${KEY}\",")
set(SETTING_KEY_DEFINITIONS "${SETTING_KEY_DEFINITIONS}\nDEFINE_KEY(${KEY})")
endforeach()
endif()
# Android exclusive setting keys (standalone app only, not Android libretro)
if (ANDROID)
foreach(KEY IN ITEMS
"expand_to_cutout_area"
"performance_overlay_enable"
"performance_overlay_show_fps"
"performance_overlay_show_frame_time"
"performance_overlay_show_speed"
"performance_overlay_show_app_ram_usage"
"performance_overlay_show_available_ram"
"performance_overlay_show_battery_temp"
"performance_overlay_background"
"use_frame_limit" # FIXME: DUPLICATE KEY (shared equivalent: frame_limit)
"android_hide_images"
"screen_orientation"
"performance_overlay_position"
)
string(REPLACE "_" "_1" KEY_JNI_ESCAPED ${KEY})
set(SETTING_KEY_LIST "${SETTING_KEY_LIST}\n\"${KEY}\",")
set(SETTING_KEY_DEFINITIONS "${SETTING_KEY_DEFINITIONS}\nDEFINE_KEY(${KEY})")
set(JNI_SETTING_KEY_DEFINITIONS "${JNI_SETTING_KEY_DEFINITIONS}
JNI_DEFINE_KEY(${KEY}, ${KEY_JNI_ESCAPED})")
endforeach()
endif()
# Libretro exclusive setting keys
if (ENABLE_LIBRETRO)
foreach(KEY IN ITEMS
"language_value"
"swap_screen_mode"
"use_libretro_save_path"
"analog_function"
"analog_deadzone"
"enable_mouse_touchscreen"
"enable_touch_touchscreen"
"render_touchscreen"
"enable_motion"
"motion_sensitivity"
)
string(REPLACE "_" "_1" KEY_JNI_ESCAPED ${KEY})
set(SETTING_KEY_LIST "${SETTING_KEY_LIST}\n\"${KEY}\",")
set(SETTING_KEY_DEFINITIONS "${SETTING_KEY_DEFINITIONS}\nDEFINE_KEY(${KEY})")
endforeach()
endif()
# Trim trailing comma and newline from SETTING_KEY_LIST
string(LENGTH "${SETTING_KEY_LIST}" SETTING_KEY_LIST_LENGTH)
math(EXPR SETTING_KEY_LIST_NEW_LENGTH "${SETTING_KEY_LIST_LENGTH} - 1")
string(SUBSTRING "${SETTING_KEY_LIST}" 0 ${SETTING_KEY_LIST_NEW_LENGTH} SETTING_KEY_LIST)
# Configure files
configure_file("common/setting_keys.h.in" "common/setting_keys.h" @ONLY)
if (ENABLE_QT)
configure_file("citra_qt/setting_qkeys.h.in" "citra_qt/setting_qkeys.h" @ONLY)
endif()
if (ANDROID AND NOT ENABLE_LIBRETRO)
configure_file("android/app/src/main/jni/jni_setting_keys.cpp.in" "android/app/src/main/jni/jni_setting_keys.cpp" @ONLY)
endif()

2
externals/boost vendored

@ -1 +1 @@
Subproject commit 2c82bd787302398bcae990e3c9ab2b451284f4ca
Subproject commit f9b15f673a688982f78a5f63a49a27275b318e5f

View File

@ -1,6 +1,8 @@
# Enable modules to include each other's files
include_directories(.)
include(GenerateSettingKeys)
# CMake seems to only define _DEBUG on Windows
set_property(DIRECTORY APPEND PROPERTY
COMPILE_DEFINITIONS $<$<CONFIG:Debug>:_DEBUG> $<$<NOT:$<CONFIG:Debug>>:NDEBUG>)

View File

@ -0,0 +1,140 @@
// Copyright Citra Emulator Project / Azahar Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
package org.citra.citra_emu.features.settings
// This list should mirror the list in GenerateSettingKeys.cmake,
// specifically the Shared and Android setting keys.
@Suppress("KotlinJniMissingFunction", "FunctionName")
object SettingKeys {
// Shared
external fun use_artic_base_controller(): String
external fun use_cpu_jit(): String
external fun cpu_clock_percentage(): String
external fun is_new_3ds(): String
external fun lle_applets(): String
external fun deterministic_async_operations(): String
external fun enable_required_online_lle_modules(): String
external fun use_virtual_sd(): String
external fun compress_cia_installs(): String
external fun region_value(): String
external fun init_clock(): String
external fun init_time(): String
external fun init_ticks_type(): String
external fun init_ticks_override(): String
external fun plugin_loader(): String
external fun allow_plugin_loader(): String
external fun steps_per_hour(): String
external fun apply_region_free_patch(): String
external fun graphics_api(): String
external fun use_gles(): String
external fun renderer_debug(): String
external fun spirv_shader_gen(): String
external fun disable_spirv_optimizer(): String
external fun async_shader_compilation(): String
external fun async_presentation(): String
external fun use_hw_shader(): String
external fun use_disk_shader_cache(): String
external fun shaders_accurate_mul(): String
external fun use_vsync(): String
external fun use_shader_jit(): String
external fun resolution_factor(): String
external fun frame_limit(): String
external fun turbo_limit(): String
external fun texture_filter(): String
external fun texture_sampling(): String
external fun delay_game_render_thread_us(): String
external fun layout_option(): String
external fun swap_screen(): String
external fun upright_screen(): String
external fun secondary_display_layout(): String
external fun large_screen_proportion(): String
external fun screen_gap(): String
external fun small_screen_position(): String
external fun custom_top_x(): String
external fun custom_top_y(): String
external fun custom_top_width(): String
external fun custom_top_height(): String
external fun custom_bottom_x(): String
external fun custom_bottom_y(): String
external fun custom_bottom_width(): String
external fun custom_bottom_height(): String
external fun custom_second_layer_opacity(): String
external fun aspect_ratio(): String
external fun portrait_layout_option(): String
external fun custom_portrait_top_x(): String
external fun custom_portrait_top_y(): String
external fun custom_portrait_top_width(): String
external fun custom_portrait_top_height(): String
external fun custom_portrait_bottom_x(): String
external fun custom_portrait_bottom_y(): String
external fun custom_portrait_bottom_width(): String
external fun custom_portrait_bottom_height(): String
external fun bg_red(): String
external fun bg_green(): String
external fun bg_blue(): String
external fun render_3d(): String
external fun factor_3d(): String
external fun swap_eyes_3d(): String
external fun render_3d_which_display(): String
external fun cardboard_screen_size(): String
external fun cardboard_x_shift(): String
external fun cardboard_y_shift(): String
external fun filter_mode(): String
external fun pp_shader_name(): String
external fun anaglyph_shader_name(): String
external fun dump_textures(): String
external fun custom_textures(): String
external fun preload_textures(): String
external fun async_custom_loading(): String
external fun disable_right_eye_render(): String
external fun audio_emulation(): String
external fun enable_audio_stretching(): String
external fun enable_realtime_audio(): String
external fun volume(): String
external fun output_type(): String
external fun output_device(): String
external fun input_type(): String
external fun input_device(): String
external fun delay_start_for_lle_modules(): String
external fun use_gdbstub(): String
external fun gdbstub_port(): String
external fun instant_debug_log(): String
external fun enable_rpc_server(): String
external fun log_filter(): String
external fun log_regex_filter(): String
external fun use_integer_scaling(): String
external fun layouts_to_cycle(): String
external fun camera_inner_flip(): String
external fun camera_outer_left_flip(): String
external fun camera_outer_right_flip(): String
external fun camera_inner_name(): String
external fun camera_inner_config(): String
external fun camera_outer_left_name(): String
external fun camera_outer_left_config(): String
external fun camera_outer_right_name(): String
external fun camera_outer_right_config(): String
external fun last_artic_base_addr(): String
external fun motion_device(): String
external fun touch_device(): String
external fun udp_input_address(): String
external fun udp_input_port(): String
external fun udp_pad_index(): String
external fun record_frame_times(): String
// Android
external fun expand_to_cutout_area(): String
external fun performance_overlay_enable(): String
external fun performance_overlay_show_fps(): String
external fun performance_overlay_show_frame_time(): String
external fun performance_overlay_show_speed(): String
external fun performance_overlay_show_app_ram_usage(): String
external fun performance_overlay_show_available_ram(): String
external fun performance_overlay_show_battery_temp(): String
external fun performance_overlay_background(): String
external fun use_frame_limit(): String
external fun android_hide_images(): String
external fun screen_orientation(): String
external fun performance_overlay_position(): String
}

View File

@ -4,57 +4,58 @@
package org.citra.citra_emu.features.settings.model
import org.citra.citra_emu.features.settings.SettingKeys
enum class BooleanSetting(
override val key: String,
override val section: String,
override val defaultValue: Boolean
) : AbstractBooleanSetting {
EXPAND_TO_CUTOUT_AREA("expand_to_cutout_area", Settings.SECTION_LAYOUT, false),
SPIRV_SHADER_GEN("spirv_shader_gen", Settings.SECTION_RENDERER, true),
ASYNC_SHADERS("async_shader_compilation", Settings.SECTION_RENDERER, false),
DISABLE_SPIRV_OPTIMIZER("disable_spirv_optimizer", Settings.SECTION_RENDERER, true),
PLUGIN_LOADER("plugin_loader", Settings.SECTION_SYSTEM, false),
ALLOW_PLUGIN_LOADER("allow_plugin_loader", Settings.SECTION_SYSTEM, true),
SWAP_SCREEN("swap_screen", Settings.SECTION_LAYOUT, false),
INSTANT_DEBUG_LOG("instant_debug_log", Settings.SECTION_DEBUG, false),
ENABLE_RPC_SERVER("enable_rpc_server", Settings.SECTION_DEBUG, false),
CUSTOM_LAYOUT("custom_layout",Settings.SECTION_LAYOUT,false),
SWAP_EYES_3D("swap_eyes_3d",Settings.SECTION_RENDERER,false),
PERF_OVERLAY_ENABLE("performance_overlay_enable", Settings.SECTION_LAYOUT, false),
PERF_OVERLAY_SHOW_FPS("performance_overlay_show_fps", Settings.SECTION_LAYOUT, true),
PERF_OVERLAY_SHOW_FRAMETIME("performance_overlay_show_frame_time", Settings.SECTION_LAYOUT, false),
PERF_OVERLAY_SHOW_SPEED("performance_overlay_show_speed", Settings.SECTION_LAYOUT, false),
PERF_OVERLAY_SHOW_APP_RAM_USAGE("performance_overlay_show_app_ram_usage", Settings.SECTION_LAYOUT, false),
PERF_OVERLAY_SHOW_AVAILABLE_RAM("performance_overlay_show_available_ram", Settings.SECTION_LAYOUT, false),
PERF_OVERLAY_SHOW_BATTERY_TEMP("performance_overlay_show_battery_temp", Settings.SECTION_LAYOUT, false),
PERF_OVERLAY_BACKGROUND("performance_overlay_background", Settings.SECTION_LAYOUT, false),
DELAY_START_LLE_MODULES("delay_start_for_lle_modules", Settings.SECTION_DEBUG, true),
DETERMINISTIC_ASYNC_OPERATIONS("deterministic_async_operations", Settings.SECTION_DEBUG, false),
REQUIRED_ONLINE_LLE_MODULES("enable_required_online_lle_modules", Settings.SECTION_SYSTEM, false),
LLE_APPLETS("lle_applets", Settings.SECTION_SYSTEM, false),
NEW_3DS("is_new_3ds", Settings.SECTION_SYSTEM, true),
LINEAR_FILTERING("filter_mode", Settings.SECTION_RENDERER, true),
USE_INTEGER_SCALING("use_integer_scaling",Settings.SECTION_RENDERER, false),
SHADERS_ACCURATE_MUL("shaders_accurate_mul", Settings.SECTION_RENDERER, false),
DISK_SHADER_CACHE("use_disk_shader_cache", Settings.SECTION_RENDERER, true),
DUMP_TEXTURES("dump_textures", Settings.SECTION_UTILITY, false),
CUSTOM_TEXTURES("custom_textures", Settings.SECTION_UTILITY, false),
ASYNC_CUSTOM_LOADING("async_custom_loading", Settings.SECTION_UTILITY, true),
PRELOAD_TEXTURES("preload_textures", Settings.SECTION_UTILITY, false),
ENABLE_AUDIO_STRETCHING("enable_audio_stretching", Settings.SECTION_AUDIO, true),
ENABLE_REALTIME_AUDIO("enable_realtime_audio", Settings.SECTION_AUDIO, false),
CPU_JIT("use_cpu_jit", Settings.SECTION_CORE, true),
HW_SHADER("use_hw_shader", Settings.SECTION_RENDERER, true),
SHADER_JIT("use_shader_jit", Settings.SECTION_RENDERER, true),
VSYNC("use_vsync", Settings.SECTION_RENDERER, false),
USE_FRAME_LIMIT("use_frame_limit", Settings.SECTION_RENDERER, true),
DEBUG_RENDERER("renderer_debug", Settings.SECTION_DEBUG, false),
DISABLE_RIGHT_EYE_RENDER("disable_right_eye_render", Settings.SECTION_RENDERER, false),
USE_ARTIC_BASE_CONTROLLER("use_artic_base_controller", Settings.SECTION_CONTROLS, false),
UPRIGHT_SCREEN("upright_screen", Settings.SECTION_LAYOUT, false),
COMPRESS_INSTALLED_CIA_CONTENT("compress_cia_installs", Settings.SECTION_STORAGE, false),
ANDROID_HIDE_IMAGES("android_hide_images", Settings.SECTION_CORE, false),
APPLY_REGION_FREE_PATCH("apply_region_free_patch", Settings.SECTION_SYSTEM, true);
EXPAND_TO_CUTOUT_AREA(SettingKeys.expand_to_cutout_area(), Settings.SECTION_LAYOUT, false),
SPIRV_SHADER_GEN(SettingKeys.spirv_shader_gen(), Settings.SECTION_RENDERER, true),
ASYNC_SHADERS(SettingKeys.async_shader_compilation(), Settings.SECTION_RENDERER, false),
DISABLE_SPIRV_OPTIMIZER(SettingKeys.disable_spirv_optimizer(), Settings.SECTION_RENDERER, true),
PLUGIN_LOADER(SettingKeys.plugin_loader(), Settings.SECTION_SYSTEM, false),
ALLOW_PLUGIN_LOADER(SettingKeys.allow_plugin_loader(), Settings.SECTION_SYSTEM, true),
SWAP_SCREEN(SettingKeys.swap_screen(), Settings.SECTION_LAYOUT, false),
INSTANT_DEBUG_LOG(SettingKeys.instant_debug_log(), Settings.SECTION_DEBUG, false),
ENABLE_RPC_SERVER(SettingKeys.enable_rpc_server(), Settings.SECTION_DEBUG, false),
SWAP_EYES_3D(SettingKeys.swap_eyes_3d(),Settings.SECTION_RENDERER, false),
PERF_OVERLAY_ENABLE(SettingKeys.performance_overlay_enable(), Settings.SECTION_LAYOUT, false),
PERF_OVERLAY_SHOW_FPS(SettingKeys.performance_overlay_show_fps(), Settings.SECTION_LAYOUT, true),
PERF_OVERLAY_SHOW_FRAMETIME(SettingKeys.performance_overlay_show_frame_time(), Settings.SECTION_LAYOUT, false),
PERF_OVERLAY_SHOW_SPEED(SettingKeys.performance_overlay_show_speed(), Settings.SECTION_LAYOUT, false),
PERF_OVERLAY_SHOW_APP_RAM_USAGE(SettingKeys.performance_overlay_show_app_ram_usage(), Settings.SECTION_LAYOUT, false),
PERF_OVERLAY_SHOW_AVAILABLE_RAM(SettingKeys.performance_overlay_show_available_ram(), Settings.SECTION_LAYOUT, false),
PERF_OVERLAY_SHOW_BATTERY_TEMP(SettingKeys.performance_overlay_show_battery_temp(), Settings.SECTION_LAYOUT, false),
PERF_OVERLAY_BACKGROUND(SettingKeys.performance_overlay_background(), Settings.SECTION_LAYOUT, false),
DELAY_START_LLE_MODULES(SettingKeys.delay_start_for_lle_modules(), Settings.SECTION_DEBUG, true),
DETERMINISTIC_ASYNC_OPERATIONS(SettingKeys.deterministic_async_operations(), Settings.SECTION_DEBUG, false),
REQUIRED_ONLINE_LLE_MODULES(SettingKeys.enable_required_online_lle_modules(), Settings.SECTION_SYSTEM, false),
LLE_APPLETS(SettingKeys.lle_applets(), Settings.SECTION_SYSTEM, false),
NEW_3DS(SettingKeys.is_new_3ds(), Settings.SECTION_SYSTEM, true),
LINEAR_FILTERING(SettingKeys.filter_mode(), Settings.SECTION_RENDERER, true),
SHADERS_ACCURATE_MUL(SettingKeys.shaders_accurate_mul(), Settings.SECTION_RENDERER, false),
DISK_SHADER_CACHE(SettingKeys.use_disk_shader_cache(), Settings.SECTION_RENDERER, true),
DUMP_TEXTURES(SettingKeys.dump_textures(), Settings.SECTION_UTILITY, false),
CUSTOM_TEXTURES(SettingKeys.custom_textures(), Settings.SECTION_UTILITY, false),
ASYNC_CUSTOM_LOADING(SettingKeys.async_custom_loading(), Settings.SECTION_UTILITY, true),
PRELOAD_TEXTURES(SettingKeys.preload_textures(), Settings.SECTION_UTILITY, false),
ENABLE_AUDIO_STRETCHING(SettingKeys.enable_audio_stretching(), Settings.SECTION_AUDIO, true),
ENABLE_REALTIME_AUDIO(SettingKeys.enable_realtime_audio(), Settings.SECTION_AUDIO, false),
CPU_JIT(SettingKeys.use_cpu_jit(), Settings.SECTION_CORE, true),
HW_SHADER(SettingKeys.use_hw_shader(), Settings.SECTION_RENDERER, true),
SHADER_JIT(SettingKeys.use_shader_jit(), Settings.SECTION_RENDERER, true),
VSYNC(SettingKeys.use_vsync(), Settings.SECTION_RENDERER, false),
USE_FRAME_LIMIT(SettingKeys.use_frame_limit(), Settings.SECTION_RENDERER, true),
DEBUG_RENDERER(SettingKeys.renderer_debug(), Settings.SECTION_DEBUG, false),
DISABLE_RIGHT_EYE_RENDER(SettingKeys.disable_right_eye_render(), Settings.SECTION_RENDERER, false),
USE_ARTIC_BASE_CONTROLLER(SettingKeys.use_artic_base_controller(), Settings.SECTION_CONTROLS, false),
UPRIGHT_SCREEN(SettingKeys.upright_screen(), Settings.SECTION_LAYOUT, false),
COMPRESS_INSTALLED_CIA_CONTENT(SettingKeys.compress_cia_installs(), Settings.SECTION_STORAGE, false),
ANDROID_HIDE_IMAGES(SettingKeys.android_hide_images(), Settings.SECTION_MISC, false),
APPLY_REGION_FREE_PATCH(SettingKeys.apply_region_free_patch(), Settings.SECTION_SYSTEM, true),
USE_INTEGER_SCALING(SettingKeys.use_integer_scaling(), Settings.SECTION_RENDERER, false);
override var boolean: Boolean = defaultValue

View File

@ -4,17 +4,18 @@
package org.citra.citra_emu.features.settings.model
import org.citra.citra_emu.features.settings.SettingKeys
enum class FloatSetting(
override val key: String,
override val section: String,
override val defaultValue: Float
) : AbstractFloatSetting {
LARGE_SCREEN_PROPORTION("large_screen_proportion",Settings.SECTION_LAYOUT,2.25f),
SECOND_SCREEN_OPACITY("custom_second_layer_opacity", Settings.SECTION_RENDERER, 100f),
BACKGROUND_RED("bg_red", Settings.SECTION_RENDERER, 0f),
BACKGROUND_BLUE("bg_blue", Settings.SECTION_RENDERER, 0f),
BACKGROUND_GREEN("bg_green", Settings.SECTION_RENDERER, 0f),
EMPTY_SETTING("", "", 0.0f);
LARGE_SCREEN_PROPORTION(SettingKeys.large_screen_proportion(),Settings.SECTION_LAYOUT,2.25f),
SECOND_SCREEN_OPACITY(SettingKeys.custom_second_layer_opacity(), Settings.SECTION_RENDERER, 100f),
BACKGROUND_RED(SettingKeys.bg_red(), Settings.SECTION_RENDERER, 0f),
BACKGROUND_BLUE(SettingKeys.bg_blue(), Settings.SECTION_RENDERER, 0f),
BACKGROUND_GREEN(SettingKeys.bg_green(), Settings.SECTION_RENDERER, 0f);
override var float: Float = defaultValue

View File

@ -4,57 +4,59 @@
package org.citra.citra_emu.features.settings.model
import org.citra.citra_emu.features.settings.SettingKeys
enum class IntSetting(
override val key: String,
override val section: String,
override val defaultValue: Int
) : AbstractIntSetting {
FRAME_LIMIT("frame_limit", Settings.SECTION_RENDERER, 100),
EMULATED_REGION("region_value", Settings.SECTION_SYSTEM, -1),
INIT_CLOCK("init_clock", Settings.SECTION_SYSTEM, 0),
CAMERA_INNER_FLIP("camera_inner_flip", Settings.SECTION_CAMERA, 0),
CAMERA_OUTER_LEFT_FLIP("camera_outer_left_flip", Settings.SECTION_CAMERA, 0),
CAMERA_OUTER_RIGHT_FLIP("camera_outer_right_flip", Settings.SECTION_CAMERA, 0),
GRAPHICS_API("graphics_api", Settings.SECTION_RENDERER, 1),
RESOLUTION_FACTOR("resolution_factor", Settings.SECTION_RENDERER, 1),
STEREOSCOPIC_3D_MODE("render_3d", Settings.SECTION_RENDERER, 2),
STEREOSCOPIC_3D_DEPTH("factor_3d", Settings.SECTION_RENDERER, 0),
STEPS_PER_HOUR("steps_per_hour", Settings.SECTION_SYSTEM, 0),
CARDBOARD_SCREEN_SIZE("cardboard_screen_size", Settings.SECTION_LAYOUT, 85),
CARDBOARD_X_SHIFT("cardboard_x_shift", Settings.SECTION_LAYOUT, 0),
CARDBOARD_Y_SHIFT("cardboard_y_shift", Settings.SECTION_LAYOUT, 0),
SCREEN_LAYOUT("layout_option", Settings.SECTION_LAYOUT, 0),
SMALL_SCREEN_POSITION("small_screen_position",Settings.SECTION_LAYOUT,0),
LANDSCAPE_TOP_X("custom_top_x",Settings.SECTION_LAYOUT,0),
LANDSCAPE_TOP_Y("custom_top_y",Settings.SECTION_LAYOUT,0),
LANDSCAPE_TOP_WIDTH("custom_top_width",Settings.SECTION_LAYOUT,800),
LANDSCAPE_TOP_HEIGHT("custom_top_height",Settings.SECTION_LAYOUT,480),
LANDSCAPE_BOTTOM_X("custom_bottom_x",Settings.SECTION_LAYOUT,80),
LANDSCAPE_BOTTOM_Y("custom_bottom_y",Settings.SECTION_LAYOUT,480),
LANDSCAPE_BOTTOM_WIDTH("custom_bottom_width",Settings.SECTION_LAYOUT,640),
LANDSCAPE_BOTTOM_HEIGHT("custom_bottom_height",Settings.SECTION_LAYOUT,480),
SCREEN_GAP("screen_gap",Settings.SECTION_LAYOUT,0),
PORTRAIT_SCREEN_LAYOUT("portrait_layout_option",Settings.SECTION_LAYOUT,0),
SECONDARY_DISPLAY_LAYOUT("secondary_display_layout",Settings.SECTION_LAYOUT,0),
PORTRAIT_TOP_X("custom_portrait_top_x",Settings.SECTION_LAYOUT,0),
PORTRAIT_TOP_Y("custom_portrait_top_y",Settings.SECTION_LAYOUT,0),
PORTRAIT_TOP_WIDTH("custom_portrait_top_width",Settings.SECTION_LAYOUT,800),
PORTRAIT_TOP_HEIGHT("custom_portrait_top_height",Settings.SECTION_LAYOUT,480),
PORTRAIT_BOTTOM_X("custom_portrait_bottom_x",Settings.SECTION_LAYOUT,80),
PORTRAIT_BOTTOM_Y("custom_portrait_bottom_y",Settings.SECTION_LAYOUT,480),
PORTRAIT_BOTTOM_WIDTH("custom_portrait_bottom_width",Settings.SECTION_LAYOUT,640),
PORTRAIT_BOTTOM_HEIGHT("custom_portrait_bottom_height",Settings.SECTION_LAYOUT,480),
AUDIO_INPUT_TYPE("input_type", Settings.SECTION_AUDIO, 0),
CPU_CLOCK_SPEED("cpu_clock_percentage", Settings.SECTION_CORE, 100),
TEXTURE_FILTER("texture_filter", Settings.SECTION_RENDERER, 0),
TEXTURE_SAMPLING("texture_sampling", Settings.SECTION_RENDERER, 0),
USE_FRAME_LIMIT("use_frame_limit", Settings.SECTION_RENDERER, 1),
DELAY_RENDER_THREAD_US("delay_game_render_thread_us", Settings.SECTION_RENDERER, 0),
ORIENTATION_OPTION("screen_orientation", Settings.SECTION_LAYOUT, 2),
TURBO_LIMIT("turbo_limit", Settings.SECTION_CORE, 200),
PERFORMANCE_OVERLAY_POSITION("performance_overlay_position", Settings.SECTION_LAYOUT, 0),
RENDER_3D_WHICH_DISPLAY("render_3d_which_display",Settings.SECTION_RENDERER,0),
ASPECT_RATIO("aspect_ratio", Settings.SECTION_LAYOUT, 0);
FRAME_LIMIT(SettingKeys.frame_limit(), Settings.SECTION_RENDERER, 100),
EMULATED_REGION(SettingKeys.region_value(), Settings.SECTION_SYSTEM, -1),
INIT_CLOCK(SettingKeys.init_clock(), Settings.SECTION_SYSTEM, 0),
CAMERA_INNER_FLIP(SettingKeys.camera_inner_flip(), Settings.SECTION_CAMERA, 0),
CAMERA_OUTER_LEFT_FLIP(SettingKeys.camera_outer_left_flip(), Settings.SECTION_CAMERA, 0),
CAMERA_OUTER_RIGHT_FLIP(SettingKeys.camera_outer_right_flip(), Settings.SECTION_CAMERA, 0),
GRAPHICS_API(SettingKeys.graphics_api(), Settings.SECTION_RENDERER, 1),
RESOLUTION_FACTOR(SettingKeys.resolution_factor(), Settings.SECTION_RENDERER, 1),
STEREOSCOPIC_3D_MODE(SettingKeys.render_3d(), Settings.SECTION_RENDERER, 2),
STEREOSCOPIC_3D_DEPTH(SettingKeys.factor_3d(), Settings.SECTION_RENDERER, 0),
STEPS_PER_HOUR(SettingKeys.steps_per_hour(), Settings.SECTION_SYSTEM, 0),
CARDBOARD_SCREEN_SIZE(SettingKeys.cardboard_screen_size(), Settings.SECTION_LAYOUT, 85),
CARDBOARD_X_SHIFT(SettingKeys.cardboard_x_shift(), Settings.SECTION_LAYOUT, 0),
CARDBOARD_Y_SHIFT(SettingKeys.cardboard_y_shift(), Settings.SECTION_LAYOUT, 0),
SCREEN_LAYOUT(SettingKeys.layout_option(), Settings.SECTION_LAYOUT, 0),
SMALL_SCREEN_POSITION(SettingKeys.small_screen_position(),Settings.SECTION_LAYOUT,0),
LANDSCAPE_TOP_X(SettingKeys.custom_top_x(),Settings.SECTION_LAYOUT,0),
LANDSCAPE_TOP_Y(SettingKeys.custom_top_y(),Settings.SECTION_LAYOUT,0),
LANDSCAPE_TOP_WIDTH(SettingKeys.custom_top_width(),Settings.SECTION_LAYOUT,800),
LANDSCAPE_TOP_HEIGHT(SettingKeys.custom_top_height(),Settings.SECTION_LAYOUT,480),
LANDSCAPE_BOTTOM_X(SettingKeys.custom_bottom_x(),Settings.SECTION_LAYOUT,80),
LANDSCAPE_BOTTOM_Y(SettingKeys.custom_bottom_y(),Settings.SECTION_LAYOUT,480),
LANDSCAPE_BOTTOM_WIDTH(SettingKeys.custom_bottom_width(),Settings.SECTION_LAYOUT,640),
LANDSCAPE_BOTTOM_HEIGHT(SettingKeys.custom_bottom_height(),Settings.SECTION_LAYOUT,480),
SCREEN_GAP(SettingKeys.screen_gap(),Settings.SECTION_LAYOUT,0),
PORTRAIT_SCREEN_LAYOUT(SettingKeys.portrait_layout_option(),Settings.SECTION_LAYOUT,0),
SECONDARY_DISPLAY_LAYOUT(SettingKeys.secondary_display_layout(),Settings.SECTION_LAYOUT,0),
PORTRAIT_TOP_X(SettingKeys.custom_portrait_top_x(),Settings.SECTION_LAYOUT,0),
PORTRAIT_TOP_Y(SettingKeys.custom_portrait_top_y(),Settings.SECTION_LAYOUT,0),
PORTRAIT_TOP_WIDTH(SettingKeys.custom_portrait_top_width(),Settings.SECTION_LAYOUT,800),
PORTRAIT_TOP_HEIGHT(SettingKeys.custom_portrait_top_height(),Settings.SECTION_LAYOUT,480),
PORTRAIT_BOTTOM_X(SettingKeys.custom_portrait_bottom_x(),Settings.SECTION_LAYOUT,80),
PORTRAIT_BOTTOM_Y(SettingKeys.custom_portrait_bottom_y(),Settings.SECTION_LAYOUT,480),
PORTRAIT_BOTTOM_WIDTH(SettingKeys.custom_portrait_bottom_width(),Settings.SECTION_LAYOUT,640),
PORTRAIT_BOTTOM_HEIGHT(SettingKeys.custom_portrait_bottom_height(),Settings.SECTION_LAYOUT,480),
AUDIO_INPUT_TYPE(SettingKeys.input_type(), Settings.SECTION_AUDIO, 0),
CPU_CLOCK_SPEED(SettingKeys.cpu_clock_percentage(), Settings.SECTION_CORE, 100),
TEXTURE_FILTER(SettingKeys.texture_filter(), Settings.SECTION_RENDERER, 0),
TEXTURE_SAMPLING(SettingKeys.texture_sampling(), Settings.SECTION_RENDERER, 0),
USE_FRAME_LIMIT(SettingKeys.use_frame_limit(), Settings.SECTION_RENDERER, 1),
DELAY_RENDER_THREAD_US(SettingKeys.delay_game_render_thread_us(), Settings.SECTION_RENDERER, 0),
ORIENTATION_OPTION(SettingKeys.screen_orientation(), Settings.SECTION_LAYOUT, 2),
TURBO_LIMIT(SettingKeys.turbo_limit(), Settings.SECTION_CORE, 200),
PERFORMANCE_OVERLAY_POSITION(SettingKeys.performance_overlay_position(), Settings.SECTION_LAYOUT, 0),
RENDER_3D_WHICH_DISPLAY(SettingKeys.render_3d_which_display(),Settings.SECTION_RENDERER,0),
ASPECT_RATIO(SettingKeys.aspect_ratio(), Settings.SECTION_LAYOUT, 0);
override var int: Int = defaultValue

View File

@ -1,16 +1,18 @@
// Copyright 2023 Citra Emulator Project
// Copyright Citra Emulator Project / Azahar Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
package org.citra.citra_emu.features.settings.model
import org.citra.citra_emu.features.settings.SettingKeys
enum class ScaledFloatSetting(
override val key: String,
override val section: String,
override val defaultValue: Float,
val scale: Int
) : AbstractFloatSetting {
AUDIO_VOLUME("volume", Settings.SECTION_AUDIO, 1.0f, 100);
AUDIO_VOLUME(SettingKeys.volume(), Settings.SECTION_AUDIO, 1.0f, 100);
override var float: Float = defaultValue
get() = field * scale

View File

@ -113,6 +113,7 @@ class Settings {
const val SECTION_CUSTOM_PORTRAIT = "Custom Portrait Layout"
const val SECTION_PERFORMANCE_OVERLAY = "Performance Overlay"
const val SECTION_STORAGE = "Storage"
const val SECTION_MISC = "Miscellaneous"
const val KEY_BUTTON_A = "button_a"
const val KEY_BUTTON_B = "button_b"
@ -223,6 +224,7 @@ class Settings {
R.string.turbo_limit_hotkey
)
// TODO: Move these in with the other setting keys in GenerateSettingKeys.cmake
const val PREF_FIRST_APP_LAUNCH = "FirstApplicationLaunch"
const val PREF_MATERIAL_YOU = "MaterialYouTheme"
const val PREF_THEME_MODE = "ThemeMode"

View File

@ -1,21 +1,23 @@
// Copyright 2023 Citra Emulator Project
// Copyright Citra Emulator Project / Azahar Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
package org.citra.citra_emu.features.settings.model
import org.citra.citra_emu.features.settings.SettingKeys
enum class StringSetting(
override val key: String,
override val section: String,
override val defaultValue: String
) : AbstractStringSetting {
INIT_TIME("init_time", Settings.SECTION_SYSTEM, "946731601"),
CAMERA_INNER_NAME("camera_inner_name", Settings.SECTION_CAMERA, "ndk"),
CAMERA_INNER_CONFIG("camera_inner_config", Settings.SECTION_CAMERA, "_front"),
CAMERA_OUTER_LEFT_NAME("camera_outer_left_name", Settings.SECTION_CAMERA, "ndk"),
CAMERA_OUTER_LEFT_CONFIG("camera_outer_left_config", Settings.SECTION_CAMERA, "_back"),
CAMERA_OUTER_RIGHT_NAME("camera_outer_right_name", Settings.SECTION_CAMERA, "ndk"),
CAMERA_OUTER_RIGHT_CONFIG("camera_outer_right_config", Settings.SECTION_CAMERA, "_back");
INIT_TIME(SettingKeys.init_time(), Settings.SECTION_SYSTEM, "946731601"),
CAMERA_INNER_NAME(SettingKeys.camera_inner_name(), Settings.SECTION_CAMERA, "ndk"),
CAMERA_INNER_CONFIG(SettingKeys.camera_inner_config(), Settings.SECTION_CAMERA, "_front"),
CAMERA_OUTER_LEFT_NAME(SettingKeys.camera_outer_left_name(), Settings.SECTION_CAMERA, "ndk"),
CAMERA_OUTER_LEFT_CONFIG(SettingKeys.camera_outer_left_config(), Settings.SECTION_CAMERA, "_back"),
CAMERA_OUTER_RIGHT_NAME(SettingKeys.camera_outer_right_name(), Settings.SECTION_CAMERA, "ndk"),
CAMERA_OUTER_RIGHT_CONFIG(SettingKeys.camera_outer_right_config(), Settings.SECTION_CAMERA, "_back");
override var string: String = defaultValue

View File

@ -33,7 +33,7 @@ import org.citra.citra_emu.adapters.HomeSettingAdapter
import org.citra.citra_emu.databinding.DialogSoftwareKeyboardBinding
import org.citra.citra_emu.databinding.FragmentHomeSettingsBinding
import org.citra.citra_emu.features.settings.model.Settings
import org.citra.citra_emu.features.settings.model.StringSetting
import org.citra.citra_emu.features.settings.SettingKeys
import org.citra.citra_emu.features.settings.ui.SettingsActivity
import org.citra.citra_emu.features.settings.utils.SettingsFile
import org.citra.citra_emu.model.Game
@ -89,7 +89,7 @@ class HomeSettingsFragment : Fragment() {
{
val inflater = LayoutInflater.from(context)
val inputBinding = DialogSoftwareKeyboardBinding.inflate(inflater)
var textInputValue: String = preferences.getString("last_artic_base_addr", "")!!
var textInputValue: String = preferences.getString(SettingKeys.last_artic_base_addr(), "")!!
inputBinding.editTextInput.setText(textInputValue)
inputBinding.editTextInput.doOnTextChanged { text, _, _, _ ->
@ -103,7 +103,7 @@ class HomeSettingsFragment : Fragment() {
.setPositiveButton(android.R.string.ok) { _, _ ->
if (textInputValue.isNotEmpty()) {
preferences.edit()
.putString("last_artic_base_addr", textInputValue)
.putString(SettingKeys.last_artic_base_addr(), textInputValue)
.apply()
val menu = Game(
title = getString(R.string.artic_base),

View File

@ -39,6 +39,7 @@ import org.citra.citra_emu.R
import org.citra.citra_emu.databinding.DialogSoftwareKeyboardBinding
import org.citra.citra_emu.databinding.FragmentSystemFilesBinding
import org.citra.citra_emu.features.settings.model.Settings
import org.citra.citra_emu.features.settings.SettingKeys
import org.citra.citra_emu.model.Game
import org.citra.citra_emu.utils.SystemSaveGame
import org.citra.citra_emu.viewmodel.GamesViewModel
@ -177,7 +178,7 @@ class SystemFilesFragment : Fragment() {
binding.buttonSetUpSystemFiles.setOnClickListener {
val inflater = LayoutInflater.from(context)
val inputBinding = DialogSoftwareKeyboardBinding.inflate(inflater)
var textInputValue: String = preferences.getString("last_artic_base_addr", "")!!
var textInputValue: String = preferences.getString(SettingKeys.last_artic_base_addr(), "")!!
val progressDialog = showProgressDialog(
getText(R.string.setup_system_files),
@ -274,7 +275,7 @@ class SystemFilesFragment : Fragment() {
.setPositiveButton(android.R.string.ok) { diag, _ ->
if (textInputValue.isNotEmpty() && !(!buttonO3ds.isChecked && !buttonN3ds.isChecked)) {
preferences.edit()
.putString("last_artic_base_addr", textInputValue)
.putString(SettingKeys.last_artic_base_addr(), textInputValue)
.apply()
val menu = Game(
title = getString(R.string.artic_base),

View File

@ -22,6 +22,7 @@ add_library(citra-android SHARED
game_info.cpp
id_cache.cpp
id_cache.h
jni_setting_keys.cpp
native.cpp
ndk_motion.cpp
ndk_motion.h

View File

@ -4,13 +4,16 @@
#include <iomanip>
#include <memory>
#include <ranges>
#include <sstream>
#include <unordered_map>
#include <INIReader.h>
#include <boost/hana/string.hpp>
#include "common/file_util.h"
#include "common/logging/backend.h"
#include "common/logging/log.h"
#include "common/param_package.h"
#include "common/setting_keys.h"
#include "common/settings.h"
#include "core/core.h"
#include "core/hle/service/cfg/cfg.h"
@ -25,11 +28,11 @@
Config::Config() {
// TODO: Don't hardcode the path; let the frontend decide where to put the config files.
sdl2_config_loc = FileUtil::GetUserPath(FileUtil::UserPath::ConfigDir) + "config.ini";
android_config_loc = FileUtil::GetUserPath(FileUtil::UserPath::ConfigDir) + "config.ini";
std::string ini_buffer;
FileUtil::ReadFileToString(true, sdl2_config_loc, ini_buffer);
FileUtil::ReadFileToString(true, android_config_loc, ini_buffer);
if (!ini_buffer.empty()) {
sdl2_config = std::make_unique<INIReader>(ini_buffer.c_str(), ini_buffer.size());
android_config = std::make_unique<INIReader>(ini_buffer.c_str(), ini_buffer.size());
}
Reload();
@ -38,15 +41,15 @@ Config::Config() {
Config::~Config() = default;
bool Config::LoadINI(const std::string& default_contents, bool retry) {
const std::string& location = this->sdl2_config_loc;
if (sdl2_config == nullptr || sdl2_config->ParseError() < 0) {
const std::string& location = this->android_config_loc;
if (android_config == nullptr || android_config->ParseError() < 0) {
if (retry) {
LOG_WARNING(Config, "Failed to load {}. Creating file from defaults...", location);
FileUtil::CreateFullPath(location);
FileUtil::WriteStringToFile(true, location, default_contents);
std::string ini_buffer;
FileUtil::ReadFileToString(true, location, ini_buffer);
sdl2_config =
android_config =
std::make_unique<INIReader>(ini_buffer.c_str(), ini_buffer.size()); // Reopen file
return LoadINI(default_contents, false);
@ -77,7 +80,8 @@ static const std::array<int, Settings::NativeAnalog::NumAnalogs> default_analogs
template <>
void Config::ReadSetting(const std::string& group, Settings::Setting<std::string>& setting) {
std::string setting_value = sdl2_config->Get(group, setting.GetLabel(), setting.GetDefault());
std::string setting_value =
android_config->Get(group, setting.GetLabel(), setting.GetDefault());
if (setting_value.empty()) {
setting_value = setting.GetDefault();
}
@ -86,15 +90,15 @@ void Config::ReadSetting(const std::string& group, Settings::Setting<std::string
template <>
void Config::ReadSetting(const std::string& group, Settings::Setting<bool>& setting) {
setting = sdl2_config->GetBoolean(group, setting.GetLabel(), setting.GetDefault());
setting = android_config->GetBoolean(group, setting.GetLabel(), setting.GetDefault());
}
template <typename Type, bool ranged>
void Config::ReadSetting(const std::string& group, Settings::Setting<Type, ranged>& setting) {
if constexpr (std::is_floating_point_v<Type>) {
setting = sdl2_config->GetReal(group, setting.GetLabel(), setting.GetDefault());
setting = android_config->GetReal(group, setting.GetLabel(), setting.GetDefault());
} else {
setting = static_cast<Type>(sdl2_config->GetInteger(
setting = static_cast<Type>(android_config->GetInteger(
group, setting.GetLabel(), static_cast<long>(setting.GetDefault())));
}
}
@ -103,30 +107,30 @@ void Config::ReadValues() {
// Controls
for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) {
std::string default_param = InputManager::GenerateButtonParamPackage(default_buttons[i]);
Settings::values.current_input_profile.buttons[i] =
sdl2_config->GetString("Controls", Settings::NativeButton::mapping[i], default_param);
Settings::values.current_input_profile.buttons[i] = android_config->GetString(
"Controls", Settings::NativeButton::mapping[i], default_param);
if (Settings::values.current_input_profile.buttons[i].empty())
Settings::values.current_input_profile.buttons[i] = default_param;
}
for (int i = 0; i < Settings::NativeAnalog::NumAnalogs; ++i) {
std::string default_param = InputManager::GenerateAnalogParamPackage(default_analogs[i]);
Settings::values.current_input_profile.analogs[i] =
sdl2_config->GetString("Controls", Settings::NativeAnalog::mapping[i], default_param);
Settings::values.current_input_profile.analogs[i] = android_config->GetString(
"Controls", Settings::NativeAnalog::mapping[i], default_param);
if (Settings::values.current_input_profile.analogs[i].empty())
Settings::values.current_input_profile.analogs[i] = default_param;
}
Settings::values.current_input_profile.motion_device = sdl2_config->GetString(
Settings::values.current_input_profile.motion_device = android_config->GetString(
"Controls", "motion_device",
"engine:motion_emu,update_period:100,sensitivity:0.01,tilt_clamp:90.0");
Settings::values.current_input_profile.touch_device =
sdl2_config->GetString("Controls", "touch_device", "engine:emu_window");
Settings::values.current_input_profile.udp_input_address = sdl2_config->GetString(
android_config->GetString("Controls", "touch_device", "engine:emu_window");
Settings::values.current_input_profile.udp_input_address = android_config->GetString(
"Controls", "udp_input_address", InputCommon::CemuhookUDP::DEFAULT_ADDR);
Settings::values.current_input_profile.udp_input_port =
static_cast<u16>(sdl2_config->GetInteger("Controls", "udp_input_port",
InputCommon::CemuhookUDP::DEFAULT_PORT));
static_cast<u16>(android_config->GetInteger("Controls", "udp_input_port",
InputCommon::CemuhookUDP::DEFAULT_PORT));
ReadSetting("Controls", Settings::values.use_artic_base_controller);
@ -135,9 +139,9 @@ void Config::ReadValues() {
ReadSetting("Core", Settings::values.cpu_clock_percentage);
// Renderer
Settings::values.use_gles = sdl2_config->GetBoolean("Renderer", "use_gles", true);
Settings::values.use_gles = android_config->GetBoolean("Renderer", "use_gles", true);
Settings::values.shaders_accurate_mul =
sdl2_config->GetBoolean("Renderer", "shaders_accurate_mul", false);
android_config->GetBoolean("Renderer", "shaders_accurate_mul", false);
ReadSetting("Renderer", Settings::values.graphics_api);
ReadSetting("Renderer", Settings::values.async_presentation);
ReadSetting("Renderer", Settings::values.async_shader_compilation);
@ -152,7 +156,7 @@ void Config::ReadValues() {
ReadSetting("Renderer", Settings::values.texture_sampling);
ReadSetting("Renderer", Settings::values.turbo_limit);
// Workaround to map Android setting for enabling the frame limiter to the format Citra expects
if (sdl2_config->GetBoolean("Renderer", "use_frame_limit", true)) {
if (android_config->GetBoolean("Renderer", "use_frame_limit", true)) {
ReadSetting("Renderer", Settings::values.frame_limit);
} else {
Settings::values.frame_limit = 0;
@ -166,7 +170,7 @@ void Config::ReadValues() {
else if (Settings::values.render_3d.GetValue() == Settings::StereoRenderOption::Interlaced)
default_shader = "Horizontal (builtin)";
Settings::values.pp_shader_name =
sdl2_config->GetString("Renderer", "pp_shader_name", default_shader);
android_config->GetString("Renderer", "pp_shader_name", default_shader);
ReadSetting("Renderer", Settings::values.filter_mode);
ReadSetting("Renderer", Settings::values.use_integer_scaling);
@ -181,18 +185,19 @@ void Config::ReadValues() {
// Layout
// Somewhat inelegant solution to ensure layout value is between 0 and 5 on read
// since older config files may have other values
int layoutInt = (int)sdl2_config->GetInteger(
int layoutInt = (int)android_config->GetInteger(
"Layout", "layout_option", static_cast<int>(Settings::LayoutOption::LargeScreen));
if (layoutInt < 0 || layoutInt > 5) {
layoutInt = static_cast<int>(Settings::LayoutOption::LargeScreen);
}
Settings::values.layout_option = static_cast<Settings::LayoutOption>(layoutInt);
Settings::values.screen_gap = static_cast<int>(sdl2_config->GetReal("Layout", "screen_gap", 0));
Settings::values.screen_gap =
static_cast<int>(android_config->GetReal("Layout", "screen_gap", 0));
Settings::values.large_screen_proportion =
static_cast<float>(sdl2_config->GetReal("Layout", "large_screen_proportion", 2.25));
static_cast<float>(android_config->GetReal("Layout", "large_screen_proportion", 2.25));
Settings::values.small_screen_position = static_cast<Settings::SmallScreenPosition>(
sdl2_config->GetInteger("Layout", "small_screen_position",
static_cast<int>(Settings::SmallScreenPosition::TopRight)));
android_config->GetInteger("Layout", "small_screen_position",
static_cast<int>(Settings::SmallScreenPosition::TopRight)));
ReadSetting("Layout", Settings::values.screen_gap);
ReadSetting("Layout", Settings::values.custom_top_x);
ReadSetting("Layout", Settings::values.custom_top_y);
@ -209,12 +214,12 @@ void Config::ReadValues() {
ReadSetting("Layout", Settings::values.upright_screen);
Settings::values.portrait_layout_option =
static_cast<Settings::PortraitLayoutOption>(sdl2_config->GetInteger(
static_cast<Settings::PortraitLayoutOption>(android_config->GetInteger(
"Layout", "portrait_layout_option",
static_cast<int>(Settings::PortraitLayoutOption::PortraitTopFullWidth)));
Settings::values.secondary_display_layout = static_cast<Settings::SecondaryDisplayLayout>(
sdl2_config->GetInteger("Layout", "secondary_display_layout",
static_cast<int>(Settings::SecondaryDisplayLayout::None)));
android_config->GetInteger("Layout", Settings::HKeys::secondary_display_layout.c_str(),
static_cast<int>(Settings::SecondaryDisplayLayout::None)));
ReadSetting("Layout", Settings::values.custom_portrait_top_x);
ReadSetting("Layout", Settings::values.custom_portrait_top_y);
ReadSetting("Layout", Settings::values.custom_portrait_top_width);
@ -253,7 +258,8 @@ void Config::ReadValues() {
ReadSetting("System", Settings::values.region_value);
ReadSetting("System", Settings::values.init_clock);
{
std::string time = sdl2_config->GetString("System", "init_time", "946681277");
std::string time =
android_config->GetString("System", Settings::HKeys::init_time.c_str(), "946681277");
try {
Settings::values.init_time = std::stoll(time);
} catch (...) {
@ -268,24 +274,27 @@ void Config::ReadValues() {
// Camera
using namespace Service::CAM;
Settings::values.camera_name[OuterRightCamera] =
sdl2_config->GetString("Camera", "camera_outer_right_name", "ndk");
Settings::values.camera_config[OuterRightCamera] = sdl2_config->GetString(
"Camera", "camera_outer_right_config", std::string{Camera::NDK::BackCameraPlaceholder});
Settings::values.camera_name[OuterRightCamera] = android_config->GetString(
"Camera", Settings::HKeys::camera_outer_right_name.c_str(), "ndk");
Settings::values.camera_config[OuterRightCamera] =
android_config->GetString("Camera", Settings::HKeys::camera_outer_right_config.c_str(),
std::string{Camera::NDK::BackCameraPlaceholder});
Settings::values.camera_flip[OuterRightCamera] =
sdl2_config->GetInteger("Camera", "camera_outer_right_flip", 0);
android_config->GetInteger("Camera", Settings::HKeys::camera_outer_right_flip.c_str(), 0);
Settings::values.camera_name[InnerCamera] =
sdl2_config->GetString("Camera", "camera_inner_name", "ndk");
Settings::values.camera_config[InnerCamera] = sdl2_config->GetString(
"Camera", "camera_inner_config", std::string{Camera::NDK::FrontCameraPlaceholder});
android_config->GetString("Camera", Settings::HKeys::camera_inner_name.c_str(), "ndk");
Settings::values.camera_config[InnerCamera] =
android_config->GetString("Camera", Settings::HKeys::camera_inner_config.c_str(),
std::string{Camera::NDK::FrontCameraPlaceholder});
Settings::values.camera_flip[InnerCamera] =
sdl2_config->GetInteger("Camera", "camera_inner_flip", 0);
android_config->GetInteger("Camera", Settings::HKeys::camera_inner_flip.c_str(), 0);
Settings::values.camera_name[OuterLeftCamera] =
sdl2_config->GetString("Camera", "camera_outer_left_name", "ndk");
Settings::values.camera_config[OuterLeftCamera] = sdl2_config->GetString(
"Camera", "camera_outer_left_config", std::string{Camera::NDK::BackCameraPlaceholder});
android_config->GetString("Camera", Settings::HKeys::camera_outer_left_name.c_str(), "ndk");
Settings::values.camera_config[OuterLeftCamera] =
android_config->GetString("Camera", Settings::HKeys::camera_outer_left_config.c_str(),
std::string{Camera::NDK::BackCameraPlaceholder});
Settings::values.camera_flip[OuterLeftCamera] =
sdl2_config->GetInteger("Camera", "camera_outer_left_flip", 0);
android_config->GetInteger("Camera", Settings::HKeys::camera_outer_left_flip.c_str(), 0);
// Miscellaneous
ReadSetting("Miscellaneous", Settings::values.log_filter);
@ -300,7 +309,7 @@ void Config::ReadValues() {
// Debugging
Settings::values.record_frame_times =
sdl2_config->GetBoolean("Debugging", "record_frame_times", false);
android_config->GetBoolean("Debugging", Settings::HKeys::record_frame_times.c_str(), false);
ReadSetting("Debugging", Settings::values.renderer_debug);
ReadSetting("Debugging", Settings::values.use_gdbstub);
ReadSetting("Debugging", Settings::values.gdbstub_port);
@ -308,18 +317,34 @@ void Config::ReadValues() {
ReadSetting("Debugging", Settings::values.enable_rpc_server);
for (const auto& service_module : Service::service_module_map) {
bool use_lle = sdl2_config->GetBoolean("Debugging", "LLE\\" + service_module.name, false);
bool use_lle =
android_config->GetBoolean("Debugging", "LLE\\" + service_module.name, false);
Settings::values.lle_modules.emplace(service_module.name, use_lle);
}
// Web Service
NetSettings::values.web_api_url =
sdl2_config->GetString("WebService", "web_api_url", "https://api.citra-emu.org");
NetSettings::values.citra_username = sdl2_config->GetString("WebService", "citra_username", "");
NetSettings::values.citra_token = sdl2_config->GetString("WebService", "citra_token", "");
android_config->GetString("WebService", "web_api_url", "https://api.citra-emu.org");
NetSettings::values.citra_username =
android_config->GetString("WebService", "citra_username", "");
NetSettings::values.citra_token = android_config->GetString("WebService", "citra_token", "");
}
void Config::Reload() {
LoadINI(DefaultINI::sdl2_config_file);
for (auto key = Settings::Keys::keys_array.begin(); key != Settings::Keys::keys_array.end();
++key) {
const auto key_declaration_string = std::string(*key) + " =";
// FIXME: This code looks so ass when formatted by clang-format -OS
if (std::ranges::find(DefaultINI::android_config_omitted_keys, *key) ==
std::end(DefaultINI::android_config_omitted_keys) &&
std::string(DefaultINI::android_config_default_file_content)
.find(key_declaration_string) == std::string::npos) {
ASSERT_MSG(false,
"Validation of default content config failed: Missing or malformed key "
"declaration {}",
*key);
}
}
LoadINI(DefaultINI::android_config_default_file_content);
ReadValues();
}

View File

@ -1,4 +1,4 @@
// Copyright 2014 Citra Emulator Project
// Copyright Citra Emulator Project / Azahar Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
@ -12,8 +12,8 @@ class INIReader;
class Config {
private:
std::unique_ptr<INIReader> sdl2_config;
std::string sdl2_config_loc;
std::unique_ptr<INIReader> android_config;
std::string android_config_loc;
bool LoadINI(const std::string& default_contents = "", bool retry = true);
void ReadValues();
@ -26,7 +26,7 @@ public:
private:
/**
* Applies a value read from the sdl2_config to a Setting.
* Applies a value read from the android_config to a Setting.
*
* @param group The name of the INI group
* @param setting The yuzu setting to modify

View File

@ -4,73 +4,61 @@
#pragma once
#include <boost/hana/string.hpp>
#include "common/setting_keys.h"
namespace Keys = Settings::Keys;
namespace DefaultINI {
const char* sdl2_config_file = R"(
// All of these setting keys are either not currently used by Android or are too niche to bother
// documenting (people can contribute documentation if they care), or some other explained reason
constexpr std::array android_config_omitted_keys = {
Keys::enable_gamemode,
Keys::use_custom_storage,
Keys::init_time_offset,
Keys::physical_device,
Keys::use_gles, // Niche
Keys::dump_command_buffers,
Keys::use_display_refresh_rate_detection,
Keys::screen_top_stretch,
Keys::screen_top_leftright_padding,
Keys::screen_top_topbottom_padding,
Keys::screen_bottom_stretch,
Keys::screen_bottom_leftright_padding,
Keys::screen_bottom_topbottom_padding,
Keys::mono_render_option,
Keys::log_regex_filter, // Niche
Keys::video_encoder,
Keys::video_encoder_options,
Keys::video_bitrate,
Keys::audio_encoder,
Keys::audio_encoder_options,
Keys::audio_bitrate,
Keys::last_artic_base_addr, // On Android, this value is stored as a "preference"
};
// clang-format off
// Is this macro nasty? Yes.
// Does it make the code way more readable? Also yes.
#define DECLARE_KEY(KEY) +Settings::HKeys::KEY+BOOST_HANA_STRING(" =")+
static const char* android_config_default_file_content = (BOOST_HANA_STRING(R"(
[Controls]
# The input devices and parameters for each 3DS native input
# It should be in the format of "engine:[engine_name],[param1]:[value1],[param2]:[value2]..."
# Escape characters $0 (for ':'), $1 (for ',') and $2 (for '$') can be used in values
# for button input, the following devices are available:
# - "keyboard" (default) for keyboard input. Required parameters:
# - "code": the code of the key to bind
# - "sdl" for joystick input using SDL. Required parameters:
# - "joystick": the index of the joystick to bind
# - "button"(optional): the index of the button to bind
# - "hat"(optional): the index of the hat to bind as direction buttons
# - "axis"(optional): the index of the axis to bind
# - "direction"(only used for hat): the direction name of the hat to bind. Can be "up", "down", "left" or "right"
# - "threshold"(only used for axis): a float value in (-1.0, 1.0) which the button is
# triggered if the axis value crosses
# - "direction"(only used for axis): "+" means the button is triggered when the axis value
# is greater than the threshold; "-" means the button is triggered when the axis value
# is smaller than the threshold
button_a=
button_b=
button_x=
button_y=
button_up=
button_down=
button_left=
button_right=
button_l=
button_r=
button_start=
button_select=
button_debug=
button_gpio14=
button_zl=
button_zr=
button_home=
# for analog input, the following devices are available:
# - "analog_from_button" (default) for emulating analog input from direction buttons. Required parameters:
# - "up", "down", "left", "right": sub-devices for each direction.
# Should be in the format as a button input devices using escape characters, for example, "engine$0keyboard$1code$00"
# - "modifier": sub-devices as a modifier.
# - "modifier_scale": a float number representing the applied modifier scale to the analog input.
# Must be in range of 0.0-1.0. Defaults to 0.5
# - "sdl" for joystick input using SDL. Required parameters:
# - "joystick": the index of the joystick to bind
# - "axis_x": the index of the axis to bind as x-axis (default to 0)
# - "axis_y": the index of the axis to bind as y-axis (default to 1)
circle_pad=
c_stick=
# for motion input, the following devices are available:
# - "motion_emu" (default) for emulating motion input from mouse input. Required parameters:
# - "update_period": update period in milliseconds (default to 100)
# - "sensitivity": the coefficient converting mouse movement to tilting angle (default to 0.01)
# - "tilt_clamp": the max value of the tilt angle in degrees (default to 90)
# - "cemuhookudp" reads motion input from a udp server that uses cemuhook's udp protocol
motion_device=
)") DECLARE_KEY(motion_device) BOOST_HANA_STRING(R"(
# for touch input, the following devices are available:
# - "emu_window" (default) for emulating touch input from mouse input to the emulation window. No parameters required
# - "cemuhookudp" reads touch input from a udp server that uses cemuhook's udp protocol
# - "min_x", "min_y", "max_x", "max_y": defines the udp device's touch screen coordinate system
touch_device= engine:emu_window
)") DECLARE_KEY(touch_device) BOOST_HANA_STRING(R"(
# Most desktop operating systems do not expose a way to poll the motion state of the controllers
# so as a way around it, cemuhook created a udp client/server protocol to broadcast the data directly
@ -78,140 +66,155 @@ touch_device= engine:emu_window
# from any cemuhook compatible motion program.
# IPv4 address of the udp input server (Default "127.0.0.1")
udp_input_address=
)") DECLARE_KEY(udp_input_address) BOOST_HANA_STRING(R"(
# Port of the udp input server. (Default 26760)
udp_input_port=
)") DECLARE_KEY(udp_input_port) BOOST_HANA_STRING(R"(
# The pad to request data on. Should be between 0 (Pad 1) and 3 (Pad 4). (Default 0)
udp_pad_index=
)") DECLARE_KEY(udp_pad_index) BOOST_HANA_STRING(R"(
# Use Artic Controller when connected to Artic Base Server. (Default 0)
use_artic_base_controller=
)") DECLARE_KEY(use_artic_base_controller) BOOST_HANA_STRING(R"(
[Core]
# Whether to use the Just-In-Time (JIT) compiler for CPU emulation
# 0: Interpreter (slow), 1 (default): JIT (fast)
use_cpu_jit =
)") DECLARE_KEY(use_cpu_jit) BOOST_HANA_STRING(R"(
# Change the Clock Frequency of the emulated 3DS CPU.
# Underclocking can increase the performance of the game at the risk of freezing.
# Overclocking may fix lag that happens on console, but also comes with the risk of freezing.
# Range is any positive integer (but we suspect 25 - 400 is a good idea) Default is 100
cpu_clock_percentage =
)") DECLARE_KEY(cpu_clock_percentage) BOOST_HANA_STRING(R"(
[Renderer]
# Whether to render using OpenGL
# 1: OpenGL ES (default), 2: Vulkan
graphics_api =
)") DECLARE_KEY(graphics_api) BOOST_HANA_STRING(R"(
# Whether to compile shaders on multiple worker threads (Vulkan only)
# 0: Off, 1: On (default)
async_shader_compilation =
)") DECLARE_KEY(async_shader_compilation) BOOST_HANA_STRING(R"(
# Whether to emit PICA fragment shader using SPIRV or GLSL (Vulkan only)
# 0: GLSL, 1: SPIR-V (default)
spirv_shader_gen =
)") DECLARE_KEY(spirv_shader_gen) BOOST_HANA_STRING(R"(
# Whether to disable the SPIRV optimizer. Disabling it reduces stutter, but may slightly worsen performance
# 0: Enabled, 1: Disabled (default)
disable_spirv_optimizer =
)") DECLARE_KEY(disable_spirv_optimizer) BOOST_HANA_STRING(R"(
# Whether to use hardware shaders to emulate 3DS shaders
# 0: Software, 1 (default): Hardware
use_hw_shader =
)") DECLARE_KEY(use_hw_shader) BOOST_HANA_STRING(R"(
# Whether to use accurate multiplication in hardware shaders
# 0: Off (Default. Faster, but causes issues in some games) 1: On (Slower, but correct)
shaders_accurate_mul =
)") DECLARE_KEY(shaders_accurate_mul) BOOST_HANA_STRING(R"(
# Whether to use the Just-In-Time (JIT) compiler for shader emulation
# 0: Interpreter (slow), 1 (default): JIT (fast)
use_shader_jit =
)") DECLARE_KEY(use_shader_jit) BOOST_HANA_STRING(R"(
# Overrides the sampling filter used by games. This can be useful in certain
# cases with poorly behaved games when upscaling.
# 0 (default): Game Controlled, 1: Nearest Neighbor, 2: Linear
texture_sampling =
)") DECLARE_KEY(texture_sampling) BOOST_HANA_STRING(R"(
# Forces VSync on the display thread. Can cause input delay, so only turn this on
# if you have screen tearing, which is unusual on Android
# 0 (default): Off, 1: On
use_vsync =
)") DECLARE_KEY(use_vsync) BOOST_HANA_STRING(R"(
# Reduce stuttering by storing and loading generated shaders to disk
# 0: Off, 1 (default. On)
use_disk_shader_cache =
)") DECLARE_KEY(use_disk_shader_cache) BOOST_HANA_STRING(R"(
# Resolution scale factor
# 0: Auto (scales resolution to window size), 1: Native 3DS screen resolution, Otherwise a scale
# factor for the 3DS resolution
resolution_factor =
)") DECLARE_KEY(resolution_factor) BOOST_HANA_STRING(R"(
# Use Integer Scaling when the layout allows
# 0: Off (default), 1: On
use_integer_scaling =
)") DECLARE_KEY(use_integer_scaling) BOOST_HANA_STRING(R"(
# Turns on the frame limiter, which will limit frames output to the target game speed
# 0: Off, 1: On (default)
use_frame_limit =
)") DECLARE_KEY(use_frame_limit) BOOST_HANA_STRING(R"(
# Limits the speed of the game to run no faster than this value as a percentage of target speed
# 1 - 9999: Speed limit as a percentage of target game speed. 100 (default)
frame_limit =
)") DECLARE_KEY(frame_limit) BOOST_HANA_STRING(R"(
# Alternative frame limit which can be triggered by the user
# 1 - 9999: Speed limit as a percentage of target game speed. 100 (default)
turbo_limit =
)") DECLARE_KEY(turbo_limit) BOOST_HANA_STRING(R"(
# The clear color for the renderer. What shows up on the sides of the bottom screen.
# Must be in range of 0.0-1.0. Defaults to 0.0 for all.
bg_red =
bg_blue =
bg_green =
)") DECLARE_KEY(bg_red) BOOST_HANA_STRING(R"(
)") DECLARE_KEY(bg_blue) BOOST_HANA_STRING(R"(
)") DECLARE_KEY(bg_green) BOOST_HANA_STRING(R"(
# Opacity of second layer when using custom layout option (bottom screen unless swapped). Useful if positioning on top of the first layer.
custom_second_layer_opacity =
)") DECLARE_KEY(custom_second_layer_opacity) BOOST_HANA_STRING(R"(
# Whether and how Stereoscopic 3D should be rendered
# 0: Off, 1: Half Width Side by Side, 2 (default): Full Width Side by Side, 3: Anaglyph, 4: Interlaced, 5: Reverse Interlaced, 6: Cardboard VR
# 0 is no longer supported in the interface, as using render_3d_which_display = 0 has the same effect, but supported here for backwards compatibility
render_3d =
)") DECLARE_KEY(render_3d) BOOST_HANA_STRING(R"(
# Change 3D Intensity
# 0 - 255: Intensity. 0 (default)
factor_3d =
)") DECLARE_KEY(factor_3d) BOOST_HANA_STRING(R"(
# Swap Eyes in 3d
# true: Swap eyes, false (default): Do not swap eyes
swap_eyes_3d =
)") DECLARE_KEY(swap_eyes_3d) BOOST_HANA_STRING(R"(
# Which Display to render 3d mode to
# 0 (default) - None. Equivalent to render_3d=0
# 1: Both, 2: Primary Only, 3: Secondary Only
render_3d_which_display =
)") DECLARE_KEY(render_3d_which_display) BOOST_HANA_STRING(R"(
# The name of the post processing shader to apply.
# Loaded from shaders if render_3d is off or side by side.
pp_shader_name =
)") DECLARE_KEY(pp_shader_name) BOOST_HANA_STRING(R"(
# The name of the shader to apply when render_3d is anaglyph.
# Loaded from shaders/anaglyph
anaglyph_shader_name =
)") DECLARE_KEY(anaglyph_shader_name) BOOST_HANA_STRING(R"(
# Whether to enable linear filtering or not
# This is required for some shaders to work correctly
# 0: Nearest, 1 (default): Linear
filter_mode =
)") DECLARE_KEY(filter_mode) BOOST_HANA_STRING(R"(
# Delays the game render thread by the specified amount of microseconds
# Set to 0 for no delay, only useful in dynamic-fps games to simulate GPU delay.
delay_game_render_thread_us =
)") DECLARE_KEY(delay_game_render_thread_us) BOOST_HANA_STRING(R"(
# Disables rendering the right eye image.
# Disables rendering the right eye image
# Greatly improves performance in some games, but can cause flickering in others.
# 0 (default): Enable right eye rendering, 1: Disable right eye rendering
disable_right_eye_render =
# 0 : Enable right eye rendering, 1: Disable right eye rendering
)") DECLARE_KEY(disable_right_eye_render) BOOST_HANA_STRING(R"(
# Perform presentation on separate threads
# Improves performance when using Vulkan in most applications.
# Adds ~1 frame of input lag.
# 0: Enable async presentation, 1 (default): Disable async presentation
)") DECLARE_KEY(async_presentation) BOOST_HANA_STRING(R"(
# Which texture filter should be used
# 0 (default): NoFilter
# 1: Anime4K
# 2: Bicubic
# 3: ScaleForce
# 4: xBRZ
# 5: MMPX
)") DECLARE_KEY(texture_filter) BOOST_HANA_STRING(R"(
[Layout]
# Layout for the screen inside the render window, landscape mode
@ -221,12 +224,52 @@ disable_right_eye_render =
# 3: Side by Side
# 4: Hybrid
# 5: Custom Layout
layout_option =
)") DECLARE_KEY(layout_option) BOOST_HANA_STRING(R"(
# Whether or not the screens should be rotated upright
# 0 (default): Not rotated, 1: Rotated upright
)") DECLARE_KEY(upright_screen) BOOST_HANA_STRING(R"(
# Which aspect ratio should be used by the emulated 3DS screens
# 0: (default): Default
# 1: 16:9
# 2: 4:3
# 3: 21:9
# 4: 16:10
# 5: Stretch
)") DECLARE_KEY(aspect_ratio) BOOST_HANA_STRING(R"(
# Whether or not the performance overlay should be displayed
# 0 (default): Hidden, 1: Shown
)") DECLARE_KEY(performance_overlay_enable) BOOST_HANA_STRING(R"(
# Whether or not the emulation framerate should be displayed in the performance overlay
# 0: Hidden, 1 (default): Shown
)") DECLARE_KEY(performance_overlay_show_fps) BOOST_HANA_STRING(R"(
# Whether or not the emulation frame time should be displayed in the performance overlay
# 0 (default): Hidden, 1: Shown
)") DECLARE_KEY(performance_overlay_show_frame_time) BOOST_HANA_STRING(R"(
# Whether or not the emulation speed should be displayed as a percentage in the performance overlay
)") DECLARE_KEY(performance_overlay_show_speed) BOOST_HANA_STRING(R"(
# Whether or not Azahar's RAM usage should be displayed in the performance overlay
)") DECLARE_KEY(performance_overlay_show_app_ram_usage) BOOST_HANA_STRING(R"(
# Whether or not the amount of available RAM should be displayed in the performance overlay
)") DECLARE_KEY(performance_overlay_show_available_ram) BOOST_HANA_STRING(R"(
# Whether or not the battery's current temperature should be displayed in the performance overlay
)") DECLARE_KEY(performance_overlay_show_battery_temp) BOOST_HANA_STRING(R"(
# Whether or not the performance overlay should have a transparent background to aid visibility
)") DECLARE_KEY(performance_overlay_background) BOOST_HANA_STRING(R"(
[Storage]
# Whether to compress the installed CIA contents
# 0 (default): Do not compress, 1: Compress
compress_cia_installs =
)") DECLARE_KEY(compress_cia_installs) BOOST_HANA_STRING(R"(
# Position of the performance overlay
# 0: Top Left
@ -235,38 +278,37 @@ compress_cia_installs =
# 3: Bottom Left
# 4: Center Bottom
# 5: Bottom Right
performance_overlay_position =
)") DECLARE_KEY(performance_overlay_position) BOOST_HANA_STRING(R"(
# Screen Gap - adds a gap between screens in all two-screen modes
# Measured in pixels relative to the 240px default height of the screens
# Scales with the larger screen (so 24 is 10% of the larger screen height)
# Default value is 0.0
screen_gap =
)") DECLARE_KEY(screen_gap) BOOST_HANA_STRING(R"(
# Large Screen Proportion - Relative size of large:small in large screen mode
# Default value is 2.25
large_screen_proportion =
)") DECLARE_KEY(large_screen_proportion) BOOST_HANA_STRING(R"(
# Small Screen Position - where is the small screen relative to the large
# Default value is 0
# 0: Top Right 1: Middle Right 2: Bottom Right
# 3: Top Left 4: Middle left 5: Bottom Left
# 6: Above the large screen 7: Below the large screen
small_screen_position =
)") DECLARE_KEY(small_screen_position) BOOST_HANA_STRING(R"(
# Screen placement when using Custom layout option
# 0x, 0y is the top left corner of the render window.
# suggested aspect ratio for top screen is 5:3
# suggested aspect ratio for bottom screen is 4:3
custom_top_x =
custom_top_y =
custom_top_width =
custom_top_height =
custom_bottom_x =
custom_bottom_y =
custom_bottom_width =
custom_bottom_height =
)") DECLARE_KEY(custom_top_x) BOOST_HANA_STRING(R"(
)") DECLARE_KEY(custom_top_y) BOOST_HANA_STRING(R"(
)") DECLARE_KEY(custom_top_width) BOOST_HANA_STRING(R"(
)") DECLARE_KEY(custom_top_height) BOOST_HANA_STRING(R"(
)") DECLARE_KEY(custom_bottom_x) BOOST_HANA_STRING(R"(
)") DECLARE_KEY(custom_bottom_y) BOOST_HANA_STRING(R"(
)") DECLARE_KEY(custom_bottom_width) BOOST_HANA_STRING(R"(
)") DECLARE_KEY(custom_bottom_height) BOOST_HANA_STRING(R"(
# Orientation option for the emulator
# 2 (default): Automatic
@ -274,32 +316,32 @@ custom_bottom_height =
# 8: Landscape (Flipped)
# 1: Portrait
# 9: Portrait (Flipped)
screen_orientation =
)") DECLARE_KEY(screen_orientation) BOOST_HANA_STRING(R"(
# Layout for the portrait mode
# 0 (default): Top and bottom screens at top, full width
# 1: Custom Layout
portrait_layout_option =
)") DECLARE_KEY(portrait_layout_option) BOOST_HANA_STRING(R"(
# Screen placement when using Portrait Custom layout option
# 0x, 0y is the top left corner of the render window.
custom_portrait_top_x =
custom_portrait_top_y =
custom_portrait_top_width =
custom_portrait_top_height =
custom_portrait_bottom_x =
custom_portrait_bottom_y =
custom_portrait_bottom_width =
custom_portrait_bottom_height =
)") DECLARE_KEY(custom_portrait_top_x) BOOST_HANA_STRING(R"(
)") DECLARE_KEY(custom_portrait_top_y) BOOST_HANA_STRING(R"(
)") DECLARE_KEY(custom_portrait_top_width) BOOST_HANA_STRING(R"(
)") DECLARE_KEY(custom_portrait_top_height) BOOST_HANA_STRING(R"(
)") DECLARE_KEY(custom_portrait_bottom_x) BOOST_HANA_STRING(R"(
)") DECLARE_KEY(custom_portrait_bottom_y) BOOST_HANA_STRING(R"(
)") DECLARE_KEY(custom_portrait_bottom_width) BOOST_HANA_STRING(R"(
)") DECLARE_KEY(custom_portrait_bottom_height) BOOST_HANA_STRING(R"(
# Swaps the prominent screen with the other screen.
# For example, if Single Screen is chosen, setting this to 1 will display the bottom screen instead of the top screen.
# 0 (default): Top Screen is prominent, 1: Bottom Screen is prominent
swap_screen =
)") DECLARE_KEY(swap_screen) BOOST_HANA_STRING(R"(
# Expands the display area to include the cutout (or notch) area
# 0 (default): Off, 1: On
expand_to_cutout_area =
)") DECLARE_KEY(expand_to_cutout_area) BOOST_HANA_STRING(R"(
# Secondary Display Layout
# What the game should do if a secondary display is connected physically or using
@ -308,129 +350,137 @@ expand_to_cutout_area =
# 1 - Show Top Screen Only
# 2 - Show Bottom Screen Only
# 3 - Show both screens side by side
secondary_display_layout =
)") DECLARE_KEY(secondary_display_layout) BOOST_HANA_STRING(R"(
# Screen placement settings when using Cardboard VR (render3d = 4)
# 30 - 100: Screen size as a percentage of the viewport. 85 (default)
cardboard_screen_size =
)") DECLARE_KEY(cardboard_screen_size) BOOST_HANA_STRING(R"(
# -100 - 100: Screen X-Coordinate shift as a percentage of empty space. 0 (default)
cardboard_x_shift =
)") DECLARE_KEY(cardboard_x_shift) BOOST_HANA_STRING(R"(
# -100 - 100: Screen Y-Coordinate shift as a percentage of empty space. 0 (default)
cardboard_y_shift =
)") DECLARE_KEY(cardboard_y_shift) BOOST_HANA_STRING(R"(
# Which of the available layouts should be cycled by Cycle Layouts
# A list of any values from 0 to 5 inclusive (e.g. 0, 1, 2, 5)
# Default: 0, 1, 2, 3, 4, 5
# 0: Default,
# 1: Single Screen,
# 2: Large Screen,
# 3: Side by Side,
# 4: Hybrid Screens,
# 5: Custom Layout,
)") DECLARE_KEY(layouts_to_cycle) BOOST_HANA_STRING(R"(
[Utility]
# Dumps textures as PNG to dump/textures/[Title ID]/.
# 0 (default): Off, 1: On
dump_textures =
)") DECLARE_KEY(dump_textures) BOOST_HANA_STRING(R"(
# Reads PNG files from load/textures/[Title ID]/ and replaces textures.
# 0 (default): Off, 1: On
custom_textures =
)") DECLARE_KEY(custom_textures) BOOST_HANA_STRING(R"(
# Loads all custom textures into memory before booting.
# 0 (default): Off, 1: On
preload_textures =
)") DECLARE_KEY(preload_textures) BOOST_HANA_STRING(R"(
# Loads custom textures asynchronously with background threads.
# 0: Off, 1 (default): On
async_custom_loading =
)") DECLARE_KEY(async_custom_loading) BOOST_HANA_STRING(R"(
[Audio]
# Whether or not to enable DSP LLE
# 0 (default): No, 1: Yes
enable_dsp_lle =
# Whether or not to run DSP LLE on a different thread
# 0 (default): No, 1: Yes
enable_dsp_lle_thread =
# Whether or not audio emulation should be enabled
# 0: Disabled, 1 (default): Enabled
)") DECLARE_KEY(audio_emulation) BOOST_HANA_STRING(R"(
# Whether or not to enable the audio-stretching post-processing effect.
# Whether or not to enable the audio-stretching post-processing effect
# This effect adjusts audio speed to match emulation speed and helps prevent audio stutter,
# at the cost of increasing audio latency.
# 0: No, 1 (default): Yes
enable_audio_stretching =
)") DECLARE_KEY(enable_audio_stretching) BOOST_HANA_STRING(R"(
# Scales audio playback speed to account for drops in emulation framerate
# 0 (default): No, 1: Yes
enable_realtime_audio =
)") DECLARE_KEY(enable_realtime_audio) BOOST_HANA_STRING(R"(
# Output volume.
# 1.0 (default): 100%, 0.0; mute
volume =
)") DECLARE_KEY(volume) BOOST_HANA_STRING(R"(
# Which audio output type to use.
# 0 (default): Auto-select, 1: No audio output, 2: Cubeb (if available), 3: OpenAL (if available), 4: SDL2 (if available)
output_type =
)") DECLARE_KEY(output_type) BOOST_HANA_STRING(R"(
# Which audio output device to use.
# auto (default): Auto-select
output_device =
)") DECLARE_KEY(output_device) BOOST_HANA_STRING(R"(
# Which audio input type to use.
# 0 (default): Auto-select, 1: No audio input, 2: Static noise, 3: Cubeb (if available), 4: OpenAL (if available)
input_type =
)") DECLARE_KEY(input_type) BOOST_HANA_STRING(R"(
# Which audio input device to use.
# auto (default): Auto-select
input_device =
)") DECLARE_KEY(input_device) BOOST_HANA_STRING(R"(
[Data Storage]
# Whether to create a virtual SD card.
# 1 (default): Yes, 0: No
use_virtual_sd =
)") DECLARE_KEY(use_virtual_sd) BOOST_HANA_STRING(R"(
[System]
# The system model that Citra will try to emulate
# 0: Old 3DS (default), 1: New 3DS
is_new_3ds =
)") DECLARE_KEY(is_new_3ds) BOOST_HANA_STRING(R"(
# Whether to use LLE system applets, if installed
# 0: No, 1 (default): Yes
lle_applets =
)") DECLARE_KEY(lle_applets) BOOST_HANA_STRING(R"(
# Whether to enable LLE modules for online play
# 0 (default): No, 1: Yes
enable_required_online_lle_modules =
)") DECLARE_KEY(enable_required_online_lle_modules) BOOST_HANA_STRING(R"(
# The system region that Citra will use during emulation
# -1: Auto-select (default), 0: Japan, 1: USA, 2: Europe, 3: Australia, 4: China, 5: Korea, 6: Taiwan
region_value =
)") DECLARE_KEY(region_value) BOOST_HANA_STRING(R"(
# The system language that Citra will use during emulation
# 0: Japanese, 1: English (default), 2: French, 3: German, 4: Italian, 5: Spanish,
# 6: Simplified Chinese, 7: Korean, 8: Dutch, 9: Portuguese, 10: Russian, 11: Traditional Chinese
language =
)") DECLARE_KEY(language) BOOST_HANA_STRING(R"(
# The clock to use when citra starts
# 0: System clock (default), 1: fixed time
init_clock =
)") DECLARE_KEY(init_clock) BOOST_HANA_STRING(R"(
# Time used when init_clock is set to fixed_time in the format %Y-%m-%d %H:%M:%S
# set to fixed time. Default 2000-01-01 00:00:01
# Note: 3DS can only handle times later then Jan 1 2000
init_time =
)") DECLARE_KEY(init_time) BOOST_HANA_STRING(R"(
# The system ticks count to use when citra starts
# 0: Random (default), 1: Fixed
init_ticks_type =
)") DECLARE_KEY(init_ticks_type) BOOST_HANA_STRING(R"(
# Tick count to use when init_ticks_type is set to Fixed.
# Defaults to 0.
init_ticks_override =
)") DECLARE_KEY(init_ticks_override) BOOST_HANA_STRING(R"(
# Number of steps per hour reported by the pedometer. Range from 0 to 65,535.
# Defaults to 0.
steps_per_hour =
)") DECLARE_KEY(steps_per_hour) BOOST_HANA_STRING(R"(
# Plugin loader state, if enabled plugins will be loaded from the SD card.
# You can also set if homebrew apps are allowed to enable the plugin loader
plugin_loader =
allow_plugin_loader =
)") DECLARE_KEY(plugin_loader) BOOST_HANA_STRING(R"(
)") DECLARE_KEY(allow_plugin_loader) BOOST_HANA_STRING(R"(
# Apply region free patch to installed applications
# Patches the region of installed applications to be region free, so that they always appear on the home menu.
# 0: Disabled, 1 (default): Enabled
apply_region_free_patch =
)") DECLARE_KEY(apply_region_free_patch) BOOST_HANA_STRING(R"(
[Camera]
# Which camera engine to use for the right outer camera
@ -441,66 +491,71 @@ apply_region_free_patch =
# If you don't specify an ID, the default setting will be used. For outer cameras,
# the back-facing camera will be used. For the inner camera, the front-facing
# camera will be used. Please note that 'Legacy' cameras are not supported.
camera_outer_right_name =
)") DECLARE_KEY(camera_outer_right_name) BOOST_HANA_STRING(R"(
# A config string for the right outer camera. Its meaning is defined by the camera engine
camera_outer_right_config =
)") DECLARE_KEY(camera_outer_right_config) BOOST_HANA_STRING(R"(
# The image flip to apply
# 0: None (default), 1: Horizontal, 2: Vertical, 3: Reverse
camera_outer_right_flip =
)") DECLARE_KEY(camera_outer_right_flip) BOOST_HANA_STRING(R"(
# ... for the left outer camera
camera_outer_left_name =
camera_outer_left_config =
camera_outer_left_flip =
)") DECLARE_KEY(camera_outer_left_name) BOOST_HANA_STRING(R"(
)") DECLARE_KEY(camera_outer_left_config) BOOST_HANA_STRING(R"(
)") DECLARE_KEY(camera_outer_left_flip) BOOST_HANA_STRING(R"(
# ... for the inner camera
camera_inner_name =
camera_inner_config =
camera_inner_flip =
)") DECLARE_KEY(camera_inner_name) BOOST_HANA_STRING(R"(
)") DECLARE_KEY(camera_inner_config) BOOST_HANA_STRING(R"(
)") DECLARE_KEY(camera_inner_flip) BOOST_HANA_STRING(R"(
[Miscellaneous]
# A filter which removes logs below a certain logging level.
# Examples: *:Debug Kernel.SVC:Trace Service.*:Critical
log_filter = *:Info
)") DECLARE_KEY(log_filter) BOOST_HANA_STRING(R"(
# Whether or not Azahar-related images should be hidden from the Android gallery
# 0 (default): No, 1: Yes
)") DECLARE_KEY(android_hide_images) BOOST_HANA_STRING(R"(
[Debugging]
# Record frame time data, can be found in the log directory. Boolean value
record_frame_times =
)") DECLARE_KEY(record_frame_times) BOOST_HANA_STRING(R"(
# Whether to enable additional debugging information during emulation
# 0 (default): Off, 1: On
renderer_debug =
)") DECLARE_KEY(renderer_debug) BOOST_HANA_STRING(R"(
# Port for listening to GDB connections.
use_gdbstub=false
gdbstub_port=24689
)") DECLARE_KEY(use_gdbstub) BOOST_HANA_STRING(R"(
# Flush log output on every message
# Immediately commits the debug log to file. Use this if Azahar crashes and the log output is being cut.
instant_debug_log =
)") DECLARE_KEY(instant_debug_log) BOOST_HANA_STRING(R"(
# Enable RPC server for scripting purposes. Allows accessing guest memory remotely.
# 0 (default): Off, 1: On
enable_rpc_server =
)") DECLARE_KEY(enable_rpc_server) BOOST_HANA_STRING(R"(
# Delay the start of apps when LLE modules are enabled
# 0: Off, 1 (default): On
delay_start_for_lle_modules =
)") DECLARE_KEY(delay_start_for_lle_modules) BOOST_HANA_STRING(R"(
# Force deterministic async operations
# Only needed for debugging, makes performance worse if enabled
# 0: Off (default), 1: On
deterministic_async_operations =
)") DECLARE_KEY(deterministic_async_operations) BOOST_HANA_STRING(R"(
# To LLE a service module add "LLE\<module name>=true"
[WebService]
# URL for Web API
web_api_url =
)") DECLARE_KEY(web_api_url) BOOST_HANA_STRING(R"(
# Username and token for Citra Web Service
citra_username =
citra_token =
)";
}
)") DECLARE_KEY(citra_username) BOOST_HANA_STRING(R"(
)") DECLARE_KEY(citra_token) BOOST_HANA_STRING("\n")).c_str();
// clang-format on
} // namespace DefaultINI

View File

@ -0,0 +1,19 @@
// Copyright Citra Emulator Project / Azahar Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <jni.h>
#define JNI_DEFINE_KEY(KEY, KEY_JNI_ESCAPED) \
JNIEXPORT jstring JNICALL \
Java_org_citra_citra_1emu_features_settings_SettingKeys_##KEY_JNI_ESCAPED( \
JNIEnv* env, jobject obj \
) { \
return env->NewStringUTF(#KEY); \
}
extern "C" {
@JNI_SETTING_KEY_DEFINITIONS@
}

View File

@ -261,16 +261,16 @@ void retro_run() {
}
// Check if the screen swap button is pressed
static bool screen_swap_btn_state = false;
static bool screen_swap_toggled = false;
static bool screen_swap_button_state = false;
static bool screens_swapped = false;
bool screen_swap_btn =
!!LibRetro::CheckInput(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_L3);
if (screen_swap_btn != screen_swap_btn_state) {
if (LibRetro::settings.toggle_swap_screen) {
if (!screen_swap_btn_state)
screen_swap_toggled = !screen_swap_toggled;
if (screen_swap_btn != screen_swap_button_state) {
if (LibRetro::settings.swap_screen_mode == "Toggle") {
if (!screen_swap_button_state)
screens_swapped = !screens_swapped;
if (screen_swap_toggled)
if (screens_swapped)
Settings::values.swap_screen =
LibRetro::FetchVariable("citra_swap_screen", "Top") != "Bottom";
else
@ -290,7 +290,7 @@ void retro_run() {
// Update the framebuffer sizing.
emu_instance->emu_window->UpdateLayout();
screen_swap_btn_state = screen_swap_btn;
screen_swap_button_state = screen_swap_btn;
}
#ifdef ENABLE_OPENGL

View File

@ -2,6 +2,8 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <boost/hana/string.hpp>
#include "citra_libretro/core_settings.h"
#include "citra_libretro/environment.h"
@ -9,12 +11,19 @@
#include "common/settings.h"
#include "core/hle/service/cfg/cfg.h"
namespace BaseKeys = Settings::HKeys;
namespace LibRetro {
CoreSettings settings = {};
namespace config {
template <typename HanaString>
constexpr const char* citra_setting(HanaString key) {
return (BOOST_HANA_STRING("citra_") + key).c_str();
}
static constexpr const char* enabled = "enabled";
static constexpr const char* disabled = "disabled";
@ -29,53 +38,56 @@ static constexpr const char* input = "input";
} // namespace category
namespace cpu {
static constexpr const char* use_cpu_jit = "citra_use_cpu_jit";
static constexpr const char* cpu_clock_percentage = "citra_cpu_scale";
static constexpr const char* use_cpu_jit = citra_setting(BaseKeys::use_cpu_jit);
static constexpr const char* cpu_clock_percentage = citra_setting(BaseKeys::cpu_clock_percentage);
} // namespace cpu
namespace system {
static constexpr const char* is_new_3ds = "citra_is_new_3ds";
static constexpr const char* region = "citra_region_value";
static constexpr const char* language = "citra_language";
static constexpr const char* is_new_3ds = citra_setting(BaseKeys::is_new_3ds);
static constexpr const char* region_value = citra_setting(BaseKeys::region_value);
static constexpr const char* language_value = citra_setting(BaseKeys::language_value);
} // namespace system
namespace audio {
static constexpr const char* audio_emulation = "citra_audio_emulation";
static constexpr const char* input_type = "citra_input_type";
static constexpr const char* audio_emulation = citra_setting(BaseKeys::audio_emulation);
static constexpr const char* input_type = citra_setting(BaseKeys::input_type);
} // namespace audio
namespace graphics {
static constexpr const char* graphics_api = "citra_graphics_api";
static constexpr const char* use_hw_shader = "citra_use_hw_shaders";
static constexpr const char* use_shader_jit = "citra_use_shader_jit";
static constexpr const char* shaders_accurate_mul = "citra_use_acc_mul";
static constexpr const char* use_disk_shader_cache = "citra_use_hw_shader_cache";
static constexpr const char* resolution_factor = "citra_resolution_factor";
static constexpr const char* texture_filter = "citra_texture_filter";
static constexpr const char* texture_sampling = "citra_texture_sampling";
static constexpr const char* custom_textures = "citra_custom_textures";
static constexpr const char* dump_textures = "citra_dump_textures";
static constexpr const char* graphics_api = citra_setting(BaseKeys::graphics_api);
static constexpr const char* use_hw_shader = citra_setting(BaseKeys::use_hw_shader);
static constexpr const char* use_shader_jit = citra_setting(BaseKeys::use_shader_jit);
static constexpr const char* shaders_accurate_mul = citra_setting(BaseKeys::shaders_accurate_mul);
static constexpr const char* use_disk_shader_cache = citra_setting(BaseKeys::use_disk_shader_cache);
static constexpr const char* resolution_factor = citra_setting(BaseKeys::resolution_factor);
static constexpr const char* texture_filter = citra_setting(BaseKeys::texture_filter);
static constexpr const char* texture_sampling = citra_setting(BaseKeys::texture_sampling);
static constexpr const char* custom_textures = citra_setting(BaseKeys::custom_textures);
static constexpr const char* dump_textures = citra_setting(BaseKeys::dump_textures);
} // namespace graphics
namespace layout {
static constexpr const char* layout_option = "citra_layout_option";
static constexpr const char* swap_screen = "citra_swap_screen";
static constexpr const char* toggle_swap_screen = "citra_swap_screen_mode";
static constexpr const char* layout_option = citra_setting(BaseKeys::layout_option);
static constexpr const char* swap_screen = citra_setting(BaseKeys::swap_screen);
static constexpr const char* swap_screen_mode = citra_setting(BaseKeys::swap_screen_mode);
} // namespace layout
namespace storage {
static constexpr const char* use_virtual_sd = "citra_use_virtual_sd";
static constexpr const char* use_libretro_save_path = "citra_use_libretro_save_path";
static constexpr const char* use_virtual_sd = citra_setting(BaseKeys::use_virtual_sd);
static constexpr const char* use_libretro_save_path =
citra_setting(BaseKeys::use_libretro_save_path);
} // namespace storage
namespace input {
static constexpr const char* analog_function = "citra_analog_function";
static constexpr const char* deadzone = "citra_deadzone";
static constexpr const char* mouse_touchscreen = "citra_mouse_touchscreen";
static constexpr const char* touch_touchscreen = "citra_touch_touchscreen";
static constexpr const char* render_touchscreen = "citra_render_touchscreen";
static constexpr const char* motion_enabled = "citra_motion_enabled";
static constexpr const char* motion_sensitivity = "citra_motion_sensitivity";
static constexpr const char* analog_function = citra_setting(BaseKeys::analog_function);
static constexpr const char* analog_deadzone = citra_setting(BaseKeys::analog_deadzone);
static constexpr const char* enable_mouse_touchscreen =
citra_setting(BaseKeys::enable_mouse_touchscreen);
static constexpr const char* enable_touch_touchscreen =
citra_setting(BaseKeys::enable_touch_touchscreen);
static constexpr const char* render_touchscreen = citra_setting(BaseKeys::render_touchscreen);
static constexpr const char* enable_motion = citra_setting(BaseKeys::enable_motion);
static constexpr const char* motion_sensitivity = citra_setting(BaseKeys::motion_sensitivity);
} // namespace input
} // namespace config
@ -179,7 +191,7 @@ static constexpr retro_core_option_v2_definition option_definitions[] = {
"New 3DS"
},
{
config::system::region,
config::system::region_value,
"3DS System Region",
"System Region",
"Set the 3DS system region. Auto-select will choose based on the game. "
@ -200,7 +212,7 @@ static constexpr retro_core_option_v2_definition option_definitions[] = {
"Auto"
},
{
config::system::language,
config::system::language_value,
"3DS System Language",
"System Language",
"Set the system language for the emulated 3DS. "
@ -458,7 +470,7 @@ static constexpr retro_core_option_v2_definition option_definitions[] = {
"Top"
},
{
config::layout::toggle_swap_screen,
config::layout::swap_screen_mode,
"Screen Swap Mode",
"Swap Mode",
"How screen swapping behaves when using the screen swap hotkey.",
@ -519,7 +531,7 @@ static constexpr retro_core_option_v2_definition option_definitions[] = {
"c_stick_and_touchscreen"
},
{
config::input::deadzone,
config::input::analog_deadzone,
"Analog Deadzone",
"Analog Deadzone",
"Set the deadzone percentage for analog input to reduce drift.",
@ -533,7 +545,7 @@ static constexpr retro_core_option_v2_definition option_definitions[] = {
"15"
},
{
config::input::mouse_touchscreen,
config::input::enable_mouse_touchscreen,
"Mouse Touchscreen Support",
"Mouse Touchscreen",
"Enable mouse input for touchscreen interactions.",
@ -547,7 +559,7 @@ static constexpr retro_core_option_v2_definition option_definitions[] = {
config::enabled
},
{
config::input::touch_touchscreen,
config::input::enable_touch_touchscreen,
"Touch Device Support",
"Touch Support",
"Enable touch device input for touchscreen interactions.",
@ -575,7 +587,7 @@ static constexpr retro_core_option_v2_definition option_definitions[] = {
config::disabled
},
{
config::input::motion_enabled,
config::input::enable_motion,
"Gyroscope/Accelerometer Support",
"Motion Support",
"Enable gyroscope and accelerometer input for games that support motion controls.",
@ -782,10 +794,10 @@ static void ParseSystemOptions(void) {
LibRetro::FetchVariable(config::system::is_new_3ds, "New 3DS") == "New 3DS";
Settings::values.region_value =
GetRegionValue(LibRetro::FetchVariable("citra_region_value", "Auto"));
GetRegionValue(LibRetro::FetchVariable(config::system::region_value, "Auto"));
LibRetro::settings.language_value =
GetLanguageValue(LibRetro::FetchVariable(config::system::language, "English"));
GetLanguageValue(LibRetro::FetchVariable(config::system::language_value, "English"));
}
static Settings::AudioEmulation GetAudioEmulation(const std::string& name) {
@ -906,8 +918,8 @@ static void ParseLayoutOptions(void) {
Settings::values.swap_screen =
LibRetro::FetchVariable(config::layout::swap_screen, "Top") == "Bottom";
LibRetro::settings.toggle_swap_screen =
LibRetro::FetchVariable(config::layout::toggle_swap_screen, "Toggle") == "Toggle";
LibRetro::settings.swap_screen_mode =
LibRetro::FetchVariable(config::layout::swap_screen_mode, "Toggle");
}
static void ParseStorageOptions(void) {
@ -962,27 +974,27 @@ static void ParseInputOptions(void) {
Settings::values.current_input_profile.analogs[1] = "";
}
auto deadzone = LibRetro::FetchVariable(config::input::deadzone, "15");
LibRetro::settings.deadzone = static_cast<float>(std::stoi(deadzone)) / 100.0f;
auto analog_deadzone = LibRetro::FetchVariable(config::input::analog_deadzone, "15");
LibRetro::settings.analog_deadzone = static_cast<float>(std::stoi(analog_deadzone)) / 100.0f;
LibRetro::settings.mouse_touchscreen =
LibRetro::FetchVariable(config::input::mouse_touchscreen, config::enabled) ==
LibRetro::settings.enable_mouse_touchscreen =
LibRetro::FetchVariable(config::input::enable_mouse_touchscreen, config::enabled) ==
config::enabled;
LibRetro::settings.touch_touchscreen =
LibRetro::FetchVariable(config::input::touch_touchscreen, config::enabled) ==
LibRetro::settings.enable_touch_touchscreen =
LibRetro::FetchVariable(config::input::enable_touch_touchscreen, config::enabled) ==
config::enabled;
LibRetro::settings.render_touchscreen =
LibRetro::FetchVariable(config::input::render_touchscreen, config::disabled) ==
config::enabled;
LibRetro::settings.motion_enabled =
LibRetro::FetchVariable(config::input::motion_enabled, config::enabled) == config::enabled;
LibRetro::settings.enable_motion =
LibRetro::FetchVariable(config::input::enable_motion, config::enabled) == config::enabled;
auto motion_sens = LibRetro::FetchVariable(config::input::motion_sensitivity, "1.0");
LibRetro::settings.motion_sensitivity = std::stof(motion_sens);
// Configure motion device based on user settings
if (LibRetro::settings.motion_enabled) {
if (LibRetro::settings.enable_motion) {
Settings::values.current_input_profile.motion_device =
"port:0,sensitivity:" + std::to_string(LibRetro::settings.motion_sensitivity) +
",engine:libretro";

View File

@ -15,21 +15,21 @@ struct CoreSettings {
std::string file_path;
float deadzone = 1.f;
float analog_deadzone = 1.f;
LibRetro::CStickFunction analog_function;
bool mouse_touchscreen;
bool enable_mouse_touchscreen;
Service::CFG::SystemLanguage language_value;
bool touch_touchscreen;
bool enable_touch_touchscreen;
bool render_touchscreen;
bool toggle_swap_screen;
std::string swap_screen_mode;
bool motion_enabled;
bool enable_motion;
float motion_sensitivity;

View File

@ -130,7 +130,7 @@ void MouseTracker::Update(int bufferWidth, int bufferHeight,
const Layout::FramebufferLayout& layout) {
bool state = false;
if (LibRetro::settings.mouse_touchscreen) {
if (LibRetro::settings.enable_mouse_touchscreen) {
// Check mouse input
state |= LibRetro::CheckInput(0, RETRO_DEVICE_MOUSE, 0, RETRO_DEVICE_ID_MOUSE_LEFT);
@ -157,7 +157,7 @@ void MouseTracker::Update(int bufferWidth, int bufferHeight,
}
}
if (LibRetro::settings.touch_touchscreen) {
if (LibRetro::settings.enable_touch_touchscreen) {
// Check touchscreen input
state |= LibRetro::CheckInput(0, RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_PRESSED);
@ -206,10 +206,10 @@ void MouseTracker::Update(int bufferWidth, int bufferHeight,
float smoothedX = std::abs(controllerX);
float smoothedY = std::abs(controllerY);
if (smoothedX < LibRetro::settings.deadzone) {
if (smoothedX < LibRetro::settings.analog_deadzone) {
controllerX = 0;
}
if (smoothedY < LibRetro::settings.deadzone) {
if (smoothedY < LibRetro::settings.analog_deadzone) {
controllerY = 0;
}

View File

@ -43,7 +43,7 @@ if (APPLE)
endif()
endif()
target_link_libraries(citra_meta PRIVATE fmt)
target_link_libraries(citra_meta PRIVATE citra_common fmt)
if (ENABLE_QT)
target_link_libraries(citra_meta PRIVATE citra_qt)

View File

@ -177,6 +177,7 @@ add_library(citra_qt STATIC EXCLUDE_FROM_ALL
precompiled_headers.h
qt_image_interface.cpp
qt_image_interface.h
setting_qkeys.h
uisettings.cpp
uisettings.h
user_data_migration.cpp
@ -193,6 +194,8 @@ add_library(citra_qt STATIC EXCLUDE_FROM_ALL
util/util.h
)
target_include_directories(citra_qt PUBLIC ${CMAKE_BINARY_DIR}/src)
if (APPLE)
target_sources(citra_qt PUBLIC
qt_swizzle.h

View File

@ -9,6 +9,7 @@
#include <QVariant>
#include <QVector>
#include "citra_qt/configuration/config.h"
#include "citra_qt/setting_qkeys.h"
#include "common/file_util.h"
#include "common/settings.h"
#include "core/hle/service/service.h"
@ -303,31 +304,29 @@ void QtConfig::ReadCameraValues() {
qt_config->beginGroup(QStringLiteral("Camera"));
Settings::values.camera_name[OuterRightCamera] =
ReadSetting(QStringLiteral("camera_outer_right_name"), QStringLiteral("blank"))
ReadSetting(Settings::QKeys::camera_inner_flip, QStringLiteral("blank"))
.toString()
.toStdString();
Settings::values.camera_config[OuterRightCamera] =
ReadSetting(QStringLiteral("camera_outer_right_config"), QString{})
.toString()
.toStdString();
ReadSetting(Settings::QKeys::camera_outer_right_config, QString{}).toString().toStdString();
Settings::values.camera_flip[OuterRightCamera] =
ReadSetting(QStringLiteral("camera_outer_right_flip"), 0).toInt();
ReadSetting(Settings::QKeys::camera_outer_right_flip, 0).toInt();
Settings::values.camera_name[InnerCamera] =
ReadSetting(QStringLiteral("camera_inner_name"), QStringLiteral("blank"))
ReadSetting(Settings::QKeys::camera_inner_name, QStringLiteral("blank"))
.toString()
.toStdString();
Settings::values.camera_config[InnerCamera] =
ReadSetting(QStringLiteral("camera_inner_config"), QString{}).toString().toStdString();
ReadSetting(Settings::QKeys::camera_inner_config, QString{}).toString().toStdString();
Settings::values.camera_flip[InnerCamera] =
ReadSetting(QStringLiteral("camera_inner_flip"), 0).toInt();
ReadSetting(Settings::QKeys::camera_inner_flip, 0).toInt();
Settings::values.camera_name[OuterLeftCamera] =
ReadSetting(QStringLiteral("camera_outer_left_name"), QStringLiteral("blank"))
ReadSetting(Settings::QKeys::camera_outer_left_name, QStringLiteral("blank"))
.toString()
.toStdString();
Settings::values.camera_config[OuterLeftCamera] =
ReadSetting(QStringLiteral("camera_outer_left_config"), QString{}).toString().toStdString();
ReadSetting(Settings::QKeys::camera_outer_left_config, QString{}).toString().toStdString();
Settings::values.camera_flip[OuterLeftCamera] =
ReadSetting(QStringLiteral("camera_outer_left_flip"), 0).toInt();
ReadSetting(Settings::QKeys::camera_outer_left_flip, 0).toInt();
qt_config->endGroup();
}
@ -338,12 +337,12 @@ void QtConfig::ReadControlValues() {
ReadBasicSetting(Settings::values.use_artic_base_controller);
int num_touch_from_button_maps =
qt_config->beginReadArray(QStringLiteral("touch_from_button_maps"));
qt_config->beginReadArray(Settings::QKeys::touch_from_button_maps);
if (num_touch_from_button_maps > 0) {
const auto append_touch_from_button_map = [this] {
Settings::TouchFromButtonMap map;
map.name = ReadSetting(QStringLiteral("name"), QStringLiteral("default"))
map.name = ReadSetting(Settings::QKeys::name, QStringLiteral("default"))
.toString()
.toStdString();
const int num_touch_maps = qt_config->beginReadArray(QStringLiteral("entries"));
@ -351,7 +350,7 @@ void QtConfig::ReadControlValues() {
for (int i = 0; i < num_touch_maps; i++) {
qt_config->setArrayIndex(i);
std::string touch_mapping =
ReadSetting(QStringLiteral("bind")).toString().toStdString();
ReadSetting(Settings::QKeys::bind).toString().toStdString();
map.buttons.emplace_back(std::move(touch_mapping));
}
qt_config->endArray(); // entries
@ -369,13 +368,12 @@ void QtConfig::ReadControlValues() {
}
qt_config->endArray();
Settings::values.current_input_profile_index =
ReadSetting(QStringLiteral("profile"), 0).toInt();
Settings::values.current_input_profile_index = ReadSetting(Settings::QKeys::profile, 0).toInt();
const auto append_profile = [this, num_touch_from_button_maps] {
Settings::InputProfile profile;
profile.name =
ReadSetting(QStringLiteral("name"), QStringLiteral("Default")).toString().toStdString();
ReadSetting(Settings::QKeys::name, QStringLiteral("Default")).toString().toStdString();
for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) {
std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]);
profile.buttons[i] = ReadSetting(QString::fromUtf8(Settings::NativeButton::mapping[i]),
@ -398,31 +396,31 @@ void QtConfig::ReadControlValues() {
profile.analogs[i] = default_param;
}
profile.motion_device =
ReadSetting(QStringLiteral("motion_device"),
ReadSetting(Settings::QKeys::motion_device,
QStringLiteral(
"engine:motion_emu,update_period:100,sensitivity:0.01,tilt_clamp:90.0"))
.toString()
.toStdString();
profile.touch_device =
ReadSetting(QStringLiteral("touch_device"), QStringLiteral("engine:emu_window"))
ReadSetting(Settings::QKeys::touch_device, QStringLiteral("engine:emu_window"))
.toString()
.toStdString();
profile.use_touch_from_button =
ReadSetting(QStringLiteral("use_touch_from_button"), false).toBool();
ReadSetting(Settings::QKeys::use_touch_from_button, false).toBool();
profile.touch_from_button_map_index =
ReadSetting(QStringLiteral("touch_from_button_map"), 0).toInt();
ReadSetting(Settings::QKeys::touch_from_button_map, 0).toInt();
profile.touch_from_button_map_index =
std::clamp(profile.touch_from_button_map_index, 0, num_touch_from_button_maps - 1);
profile.udp_input_address =
ReadSetting(QStringLiteral("udp_input_address"),
ReadSetting(Settings::QKeys::udp_input_address,
QString::fromUtf8(InputCommon::CemuhookUDP::DEFAULT_ADDR))
.toString()
.toStdString();
profile.udp_input_port = static_cast<u16>(
ReadSetting(QStringLiteral("udp_input_port"), InputCommon::CemuhookUDP::DEFAULT_PORT)
ReadSetting(Settings::QKeys::udp_input_port, InputCommon::CemuhookUDP::DEFAULT_PORT)
.toInt());
profile.udp_pad_index =
static_cast<u8>(ReadSetting(QStringLiteral("udp_pad_index"), 0).toUInt());
static_cast<u8>(ReadSetting(Settings::QKeys::udp_pad_index, 0).toUInt());
Settings::values.input_profiles.emplace_back(std::move(profile));
};
@ -482,9 +480,9 @@ void QtConfig::ReadDataStorageValues() {
ReadBasicSetting(Settings::values.compress_cia_installs);
const std::string nand_dir =
ReadSetting(QStringLiteral("nand_directory"), QStringLiteral("")).toString().toStdString();
ReadSetting(Settings::QKeys::nand_directory, QStringLiteral("")).toString().toStdString();
const std::string sdmc_dir =
ReadSetting(QStringLiteral("sdmc_directory"), QStringLiteral("")).toString().toStdString();
ReadSetting(Settings::QKeys::sdmc_directory, QStringLiteral("")).toString().toStdString();
if (Settings::values.use_custom_storage) {
FileUtil::UpdateUserPath(FileUtil::UserPath::NANDDir, nand_dir);
@ -499,7 +497,7 @@ void QtConfig::ReadDebuggingValues() {
// Intentionally not using the QT default setting as this is intended to be changed in the ini
Settings::values.record_frame_times =
qt_config->value(QStringLiteral("record_frame_times"), false).toBool();
qt_config->value(Settings::QKeys::record_frame_times, false).toBool();
ReadBasicSetting(Settings::values.use_gdbstub);
ReadBasicSetting(Settings::values.gdbstub_port);
ReadBasicSetting(Settings::values.renderer_debug);
@ -584,48 +582,48 @@ void QtConfig::ReadMiscellaneousValues() {
void QtConfig::ReadMultiplayerValues() {
qt_config->beginGroup(QStringLiteral("Multiplayer"));
UISettings::values.nickname = ReadSetting(QStringLiteral("nickname"), QString{}).toString();
UISettings::values.ip = ReadSetting(QStringLiteral("ip"), QString{}).toString();
UISettings::values.nickname = ReadSetting(Settings::QKeys::nickname, QString{}).toString();
UISettings::values.ip = ReadSetting(Settings::QKeys::ip, QString{}).toString();
UISettings::values.port =
ReadSetting(QStringLiteral("port"), Network::DefaultRoomPort).toString();
ReadSetting(Settings::QKeys::port, Network::DefaultRoomPort).toString();
UISettings::values.room_nickname =
ReadSetting(QStringLiteral("room_nickname"), QString{}).toString();
UISettings::values.room_name = ReadSetting(QStringLiteral("room_name"), QString{}).toString();
ReadSetting(Settings::QKeys::room_nickname, QString{}).toString();
UISettings::values.room_name = ReadSetting(Settings::QKeys::room_name, QString{}).toString();
UISettings::values.room_port =
ReadSetting(QStringLiteral("room_port"), QStringLiteral("24872")).toString();
ReadSetting(Settings::QKeys::room_port, QStringLiteral("24872")).toString();
bool ok;
UISettings::values.host_type = ReadSetting(QStringLiteral("host_type"), 0).toUInt(&ok);
UISettings::values.host_type = ReadSetting(Settings::QKeys::host_type, 0).toUInt(&ok);
if (!ok) {
UISettings::values.host_type = 0;
}
UISettings::values.max_player = ReadSetting(QStringLiteral("max_player"), 8).toUInt();
UISettings::values.game_id = ReadSetting(QStringLiteral("game_id"), 0).toULongLong();
UISettings::values.max_player = ReadSetting(Settings::QKeys::max_player, 8).toUInt();
UISettings::values.game_id = ReadSetting(Settings::QKeys::game_id, 0).toULongLong();
UISettings::values.room_description =
ReadSetting(QStringLiteral("room_description"), QString{}).toString();
ReadSetting(Settings::QKeys::room_description, QString{}).toString();
UISettings::values.multiplayer_filter_text =
ReadSetting(QStringLiteral("multiplayer_filter_text"), QString{}).toString();
ReadSetting(Settings::QKeys::multiplayer_filter_text, QString{}).toString();
UISettings::values.multiplayer_filter_games_owned =
ReadSetting(QStringLiteral("multiplayer_filter_games_owned"), false).toBool();
ReadSetting(Settings::QKeys::multiplayer_filter_games_owned, false).toBool();
UISettings::values.multiplayer_filter_hide_empty =
ReadSetting(QStringLiteral("multiplayer_filter_hide_empty"), false).toBool();
ReadSetting(Settings::QKeys::multiplayer_filter_hide_empty, false).toBool();
UISettings::values.multiplayer_filter_hide_full =
ReadSetting(QStringLiteral("multiplayer_filter_hide_full"), false).toBool();
ReadSetting(Settings::QKeys::multiplayer_filter_hide_full, false).toBool();
// Read ban list back
int size = qt_config->beginReadArray(QStringLiteral("username_ban_list"));
int size = qt_config->beginReadArray(Settings::QKeys::username_ban_list);
UISettings::values.ban_list.first.resize(size);
for (int i = 0; i < size; ++i) {
qt_config->setArrayIndex(i);
UISettings::values.ban_list.first[i] =
ReadSetting(QStringLiteral("username")).toString().toStdString();
ReadSetting(Settings::QKeys::username).toString().toStdString();
}
qt_config->endArray();
size = qt_config->beginReadArray(QStringLiteral("ip_ban_list"));
size = qt_config->beginReadArray(Settings::QKeys::ip_ban_list);
UISettings::values.ban_list.second.resize(size);
for (int i = 0; i < size; ++i) {
qt_config->setArrayIndex(i);
UISettings::values.ban_list.second[i] =
ReadSetting(QStringLiteral("ip")).toString().toStdString();
ReadSetting(Settings::QKeys::ip).toString().toStdString();
}
qt_config->endArray();
@ -638,25 +636,25 @@ void QtConfig::ReadPathValues() {
ReadGlobalSetting(UISettings::values.screenshot_path);
if (global) {
UISettings::values.roms_path = ReadSetting(QStringLiteral("romsPath")).toString();
UISettings::values.symbols_path = ReadSetting(QStringLiteral("symbolsPath")).toString();
UISettings::values.roms_path = ReadSetting(Settings::QKeys::romsPath).toString();
UISettings::values.symbols_path = ReadSetting(Settings::QKeys::symbolsPath).toString();
UISettings::values.movie_record_path =
ReadSetting(QStringLiteral("movieRecordPath")).toString();
ReadSetting(Settings::QKeys::movieRecordPath).toString();
UISettings::values.movie_playback_path =
ReadSetting(QStringLiteral("moviePlaybackPath")).toString();
ReadSetting(Settings::QKeys::moviePlaybackPath).toString();
UISettings::values.video_dumping_path =
ReadSetting(QStringLiteral("videoDumpingPath")).toString();
ReadSetting(Settings::QKeys::videoDumpingPath).toString();
UISettings::values.game_dir_deprecated =
ReadSetting(QStringLiteral("gameListRootDir"), QStringLiteral(".")).toString();
ReadSetting(Settings::QKeys::gameListRootDir, QStringLiteral(".")).toString();
UISettings::values.game_dir_deprecated_deepscan =
ReadSetting(QStringLiteral("gameListDeepScan"), false).toBool();
ReadSetting(Settings::QKeys::gameListDeepScan, false).toBool();
int size = qt_config->beginReadArray(QStringLiteral("gamedirs"));
for (int i = 0; i < size; ++i) {
qt_config->setArrayIndex(i);
UISettings::GameDir game_dir;
game_dir.path = ReadSetting(QStringLiteral("path")).toString();
game_dir.deep_scan = ReadSetting(QStringLiteral("deep_scan"), false).toBool();
game_dir.expanded = ReadSetting(QStringLiteral("expanded"), true).toBool();
game_dir.path = ReadSetting(Settings::QKeys::path).toString();
game_dir.deep_scan = ReadSetting(Settings::QKeys::deep_scan, false).toBool();
game_dir.expanded = ReadSetting(Settings::QKeys::expanded, true).toBool();
UISettings::values.game_dirs.append(game_dir);
}
qt_config->endArray();
@ -676,9 +674,9 @@ void QtConfig::ReadPathValues() {
}
}
UISettings::values.last_artic_base_addr =
ReadSetting(QStringLiteral("last_artic_base_addr"), QString{}).toString();
UISettings::values.recent_files = ReadSetting(QStringLiteral("recentFiles")).toStringList();
UISettings::values.language = ReadSetting(QStringLiteral("language"), QString{}).toString();
ReadSetting(Settings::QKeys::last_artic_base_addr, QString{}).toString();
UISettings::values.recent_files = ReadSetting(Settings::QKeys::recentFiles).toStringList();
UISettings::values.language = ReadSetting(Settings::QKeys::language, QString{}).toString();
ReadBasicSetting(UISettings::values.inserted_cartridge);
if (!FileUtil::Exists(UISettings::values.inserted_cartridge.GetValue())) {
@ -737,8 +735,7 @@ void QtConfig::ReadShortcutValues() {
UISettings::values.shortcuts.push_back(
{name,
group,
{ReadSetting(QStringLiteral("KeySeq"), shortcut.keyseq).toString(),
shortcut.context}});
{ReadSetting(Settings::QKeys::KeySeq, shortcut.keyseq).toString(), shortcut.context}});
qt_config->endGroup();
qt_config->endGroup();
}
@ -779,35 +776,35 @@ void QtConfig::ReadVideoDumpingValues() {
qt_config->beginGroup(QStringLiteral("VideoDumping"));
Settings::values.output_format =
ReadSetting(QStringLiteral("output_format"), QStringLiteral("webm"))
ReadSetting(Settings::QKeys::output_format, QStringLiteral("webm"))
.toString()
.toStdString();
Settings::values.format_options =
ReadSetting(QStringLiteral("format_options")).toString().toStdString();
ReadSetting(Settings::QKeys::format_options).toString().toStdString();
Settings::values.video_encoder =
ReadSetting(QStringLiteral("video_encoder"), QStringLiteral("libvpx-vp9"))
ReadSetting(Settings::QKeys::video_encoder, QStringLiteral("libvpx-vp9"))
.toString()
.toStdString();
Settings::values.video_encoder_options =
ReadSetting(QStringLiteral("video_encoder_options"), DEFAULT_VIDEO_ENCODER_OPTIONS)
ReadSetting(Settings::QKeys::video_encoder_options, DEFAULT_VIDEO_ENCODER_OPTIONS)
.toString()
.toStdString();
Settings::values.video_bitrate =
ReadSetting(QStringLiteral("video_bitrate"), 2500000).toULongLong();
ReadSetting(Settings::QKeys::video_bitrate, 2500000).toULongLong();
Settings::values.audio_encoder =
ReadSetting(QStringLiteral("audio_encoder"), QStringLiteral("libvorbis"))
ReadSetting(Settings::QKeys::audio_encoder, QStringLiteral("libvorbis"))
.toString()
.toStdString();
Settings::values.audio_encoder_options =
ReadSetting(QStringLiteral("audio_encoder_options"), DEFAULT_AUDIO_ENCODER_OPTIONS)
ReadSetting(Settings::QKeys::audio_encoder_options, DEFAULT_AUDIO_ENCODER_OPTIONS)
.toString()
.toStdString();
Settings::values.audio_bitrate =
ReadSetting(QStringLiteral("audio_bitrate"), 64000).toULongLong();
ReadSetting(Settings::QKeys::audio_bitrate, 64000).toULongLong();
qt_config->endGroup();
}
@ -819,7 +816,7 @@ void QtConfig::ReadUIValues() {
if (global) {
UISettings::values.theme =
ReadSetting(QStringLiteral("theme"), QString::fromUtf8(UISettings::themes[0].second))
ReadSetting(Settings::QKeys::theme, QString::fromUtf8(UISettings::themes[0].second))
.toString();
#ifdef USE_DISCORD_PRESENCE
ReadBasicSetting(UISettings::values.enable_discord_presence);
@ -869,7 +866,7 @@ void QtConfig::ReadUIGameListValues() {
for (int i = 0; i < favorites_size; i++) {
qt_config->setArrayIndex(i);
UISettings::values.favorited_ids.append(
ReadSetting(QStringLiteral("program_id")).toULongLong());
ReadSetting(Settings::QKeys::program_id).toULongLong());
}
qt_config->endArray();
@ -879,14 +876,14 @@ void QtConfig::ReadUIGameListValues() {
void QtConfig::ReadUILayoutValues() {
qt_config->beginGroup(QStringLiteral("UILayout"));
UISettings::values.geometry = ReadSetting(QStringLiteral("geometry")).toByteArray();
UISettings::values.state = ReadSetting(QStringLiteral("state")).toByteArray();
UISettings::values.geometry = ReadSetting(Settings::QKeys::geometry).toByteArray();
UISettings::values.state = ReadSetting(Settings::QKeys::state).toByteArray();
UISettings::values.renderwindow_geometry =
ReadSetting(QStringLiteral("geometryRenderWindow")).toByteArray();
ReadSetting(Settings::QKeys::geometryRenderWindow).toByteArray();
UISettings::values.gamelist_header_state =
ReadSetting(QStringLiteral("gameListHeaderState")).toByteArray();
ReadSetting(Settings::QKeys::gameListHeaderState).toByteArray();
UISettings::values.microprofile_geometry =
ReadSetting(QStringLiteral("microProfileDialogGeometry")).toByteArray();
ReadSetting(Settings::QKeys::microProfileDialogGeometry).toByteArray();
ReadBasicSetting(UISettings::values.microprofile_visible);
qt_config->endGroup();
@ -896,13 +893,13 @@ void QtConfig::ReadWebServiceValues() {
qt_config->beginGroup(QStringLiteral("WebService"));
NetSettings::values.web_api_url =
ReadSetting(QStringLiteral("web_api_url"), QStringLiteral("https://api.citra-emu.org"))
ReadSetting(Settings::QKeys::web_api_url, QStringLiteral("https://api.citra-emu.org"))
.toString()
.toStdString();
NetSettings::values.citra_username =
ReadSetting(QStringLiteral("citra_username")).toString().toStdString();
ReadSetting(Settings::QKeys::citra_username).toString().toStdString();
NetSettings::values.citra_token =
ReadSetting(QStringLiteral("citra_token")).toString().toStdString();
ReadSetting(Settings::QKeys::citra_token).toString().toStdString();
qt_config->endGroup();
}
@ -950,27 +947,27 @@ void QtConfig::SaveCameraValues() {
using namespace Service::CAM;
qt_config->beginGroup(QStringLiteral("Camera"));
WriteSetting(QStringLiteral("camera_outer_right_name"),
WriteSetting(Settings::QKeys::camera_outer_right_name,
QString::fromStdString(Settings::values.camera_name[OuterRightCamera]),
QStringLiteral("blank"));
WriteSetting(QStringLiteral("camera_outer_right_config"),
WriteSetting(Settings::QKeys::camera_outer_right_config,
QString::fromStdString(Settings::values.camera_config[OuterRightCamera]),
QString{});
WriteSetting(QStringLiteral("camera_outer_right_flip"),
WriteSetting(Settings::QKeys::camera_outer_right_flip,
Settings::values.camera_flip[OuterRightCamera], 0);
WriteSetting(QStringLiteral("camera_inner_name"),
WriteSetting(Settings::QKeys::camera_inner_name,
QString::fromStdString(Settings::values.camera_name[InnerCamera]),
QStringLiteral("blank"));
WriteSetting(QStringLiteral("camera_inner_config"),
WriteSetting(Settings::QKeys::camera_inner_config,
QString::fromStdString(Settings::values.camera_config[InnerCamera]), QString{});
WriteSetting(QStringLiteral("camera_inner_flip"), Settings::values.camera_flip[InnerCamera], 0);
WriteSetting(QStringLiteral("camera_outer_left_name"),
WriteSetting(Settings::QKeys::camera_inner_flip, Settings::values.camera_flip[InnerCamera], 0);
WriteSetting(Settings::QKeys::camera_outer_left_name,
QString::fromStdString(Settings::values.camera_name[OuterLeftCamera]),
QStringLiteral("blank"));
WriteSetting(QStringLiteral("camera_outer_left_config"),
WriteSetting(Settings::QKeys::camera_outer_left_config,
QString::fromStdString(Settings::values.camera_config[OuterLeftCamera]),
QString{});
WriteSetting(QStringLiteral("camera_outer_left_flip"),
WriteSetting(Settings::QKeys::camera_outer_left_flip,
Settings::values.camera_flip[OuterLeftCamera], 0);
qt_config->endGroup();
@ -981,12 +978,12 @@ void QtConfig::SaveControlValues() {
WriteBasicSetting(Settings::values.use_artic_base_controller);
WriteSetting(QStringLiteral("profile"), Settings::values.current_input_profile_index, 0);
WriteSetting(Settings::QKeys::profile, Settings::values.current_input_profile_index, 0);
qt_config->beginWriteArray(QStringLiteral("profiles"));
for (std::size_t p = 0; p < Settings::values.input_profiles.size(); ++p) {
qt_config->setArrayIndex(static_cast<int>(p));
const auto& profile = Settings::values.input_profiles[p];
WriteSetting(QStringLiteral("name"), QString::fromStdString(profile.name),
WriteSetting(Settings::QKeys::name, QString::fromStdString(profile.name),
QStringLiteral("default"));
for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) {
std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]);
@ -1003,32 +1000,32 @@ void QtConfig::SaveControlValues() {
QString::fromStdString(default_param));
}
WriteSetting(
QStringLiteral("motion_device"), QString::fromStdString(profile.motion_device),
Settings::QKeys::motion_device, QString::fromStdString(profile.motion_device),
QStringLiteral("engine:motion_emu,update_period:100,sensitivity:0.01,tilt_clamp:90.0"));
WriteSetting(QStringLiteral("touch_device"), QString::fromStdString(profile.touch_device),
WriteSetting(Settings::QKeys::touch_device, QString::fromStdString(profile.touch_device),
QStringLiteral("engine:emu_window"));
WriteSetting(QStringLiteral("use_touch_from_button"), profile.use_touch_from_button, false);
WriteSetting(QStringLiteral("touch_from_button_map"), profile.touch_from_button_map_index,
WriteSetting(Settings::QKeys::use_touch_from_button, profile.use_touch_from_button, false);
WriteSetting(Settings::QKeys::touch_from_button_map, profile.touch_from_button_map_index,
0);
WriteSetting(QStringLiteral("udp_input_address"),
WriteSetting(Settings::QKeys::udp_input_address,
QString::fromStdString(profile.udp_input_address),
QString::fromUtf8(InputCommon::CemuhookUDP::DEFAULT_ADDR));
WriteSetting(QStringLiteral("udp_input_port"), profile.udp_input_port,
WriteSetting(Settings::QKeys::udp_input_port, profile.udp_input_port,
InputCommon::CemuhookUDP::DEFAULT_PORT);
WriteSetting(QStringLiteral("udp_pad_index"), profile.udp_pad_index, 0);
WriteSetting(Settings::QKeys::udp_pad_index, profile.udp_pad_index, 0);
}
qt_config->endArray();
qt_config->beginWriteArray(QStringLiteral("touch_from_button_maps"));
qt_config->beginWriteArray(Settings::QKeys::touch_from_button_maps);
for (std::size_t p = 0; p < Settings::values.touch_from_button_maps.size(); ++p) {
qt_config->setArrayIndex(static_cast<int>(p));
const auto& map = Settings::values.touch_from_button_maps[p];
WriteSetting(QStringLiteral("name"), QString::fromStdString(map.name),
WriteSetting(Settings::QKeys::name, QString::fromStdString(map.name),
QStringLiteral("default"));
qt_config->beginWriteArray(QStringLiteral("entries"));
for (std::size_t q = 0; q < map.buttons.size(); ++q) {
qt_config->setArrayIndex(static_cast<int>(q));
WriteSetting(QStringLiteral("bind"), QString::fromStdString(map.buttons[q]));
WriteSetting(Settings::QKeys::bind, QString::fromStdString(map.buttons[q]));
}
qt_config->endArray();
}
@ -1067,10 +1064,10 @@ void QtConfig::SaveDataStorageValues() {
WriteBasicSetting(Settings::values.use_virtual_sd);
WriteBasicSetting(Settings::values.use_custom_storage);
WriteBasicSetting(Settings::values.compress_cia_installs);
WriteSetting(QStringLiteral("nand_directory"),
WriteSetting(Settings::QKeys::nand_directory,
QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::NANDDir)),
QStringLiteral(""));
WriteSetting(QStringLiteral("sdmc_directory"),
WriteSetting(Settings::QKeys::sdmc_directory,
QString::fromStdString(FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir)),
QStringLiteral(""));
@ -1081,7 +1078,7 @@ void QtConfig::SaveDebuggingValues() {
qt_config->beginGroup(QStringLiteral("Debugging"));
// Intentionally not using the QT default setting as this is intended to be changed in the ini
qt_config->setValue(QStringLiteral("record_frame_times"), Settings::values.record_frame_times);
qt_config->setValue(Settings::QKeys::record_frame_times, Settings::values.record_frame_times);
WriteBasicSetting(Settings::values.use_gdbstub);
WriteBasicSetting(Settings::values.gdbstub_port);
WriteBasicSetting(Settings::values.renderer_debug);
@ -1163,39 +1160,37 @@ void QtConfig::SaveMiscellaneousValues() {
void QtConfig::SaveMultiplayerValues() {
qt_config->beginGroup(QStringLiteral("Multiplayer"));
WriteSetting(QStringLiteral("nickname"), UISettings::values.nickname, QString{});
WriteSetting(QStringLiteral("ip"), UISettings::values.ip, QString{});
WriteSetting(QStringLiteral("port"), UISettings::values.port, Network::DefaultRoomPort);
WriteSetting(QStringLiteral("room_nickname"), UISettings::values.room_nickname, QString{});
WriteSetting(QStringLiteral("room_name"), UISettings::values.room_name, QString{});
WriteSetting(QStringLiteral("room_port"), UISettings::values.room_port,
QStringLiteral("24872"));
WriteSetting(QStringLiteral("host_type"), UISettings::values.host_type, 0);
WriteSetting(QStringLiteral("max_player"), UISettings::values.max_player, 8);
WriteSetting(QStringLiteral("game_id"), UISettings::values.game_id, 0);
WriteSetting(QStringLiteral("room_description"), UISettings::values.room_description,
QString{});
WriteSetting(QStringLiteral("multiplayer_filter_text"),
WriteSetting(Settings::QKeys::nickname, UISettings::values.nickname, QString{});
WriteSetting(Settings::QKeys::ip, UISettings::values.ip, QString{});
WriteSetting(Settings::QKeys::port, UISettings::values.port, Network::DefaultRoomPort);
WriteSetting(Settings::QKeys::room_nickname, UISettings::values.room_nickname, QString{});
WriteSetting(Settings::QKeys::room_name, UISettings::values.room_name, QString{});
WriteSetting(Settings::QKeys::room_port, UISettings::values.room_port, QStringLiteral("24872"));
WriteSetting(Settings::QKeys::host_type, UISettings::values.host_type, 0);
WriteSetting(Settings::QKeys::max_player, UISettings::values.max_player, 8);
WriteSetting(Settings::QKeys::game_id, UISettings::values.game_id, 0);
WriteSetting(Settings::QKeys::room_description, UISettings::values.room_description, QString{});
WriteSetting(Settings::QKeys::multiplayer_filter_text,
UISettings::values.multiplayer_filter_text, QString{});
WriteSetting(QStringLiteral("multiplayer_filter_games_owned"),
WriteSetting(Settings::QKeys::multiplayer_filter_games_owned,
UISettings::values.multiplayer_filter_games_owned, false);
WriteSetting(QStringLiteral("multiplayer_filter_hide_empty"),
WriteSetting(Settings::QKeys::multiplayer_filter_hide_empty,
UISettings::values.multiplayer_filter_hide_empty, false);
WriteSetting(QStringLiteral("multiplayer_filter_hide_full"),
WriteSetting(Settings::QKeys::multiplayer_filter_hide_full,
UISettings::values.multiplayer_filter_hide_full, false);
// Write ban list
qt_config->beginWriteArray(QStringLiteral("username_ban_list"));
qt_config->beginWriteArray(Settings::QKeys::username_ban_list);
for (std::size_t i = 0; i < UISettings::values.ban_list.first.size(); ++i) {
qt_config->setArrayIndex(static_cast<int>(i));
WriteSetting(QStringLiteral("username"),
WriteSetting(Settings::QKeys::username,
QString::fromStdString(UISettings::values.ban_list.first[i]));
}
qt_config->endArray();
qt_config->beginWriteArray(QStringLiteral("ip_ban_list"));
qt_config->beginWriteArray(Settings::QKeys::ip_ban_list);
for (std::size_t i = 0; i < UISettings::values.ban_list.second.size(); ++i) {
qt_config->setArrayIndex(static_cast<int>(i));
WriteSetting(QStringLiteral("ip"),
WriteSetting(Settings::QKeys::ip,
QString::fromStdString(UISettings::values.ban_list.second[i]));
}
qt_config->endArray();
@ -1208,24 +1203,24 @@ void QtConfig::SavePathValues() {
WriteGlobalSetting(UISettings::values.screenshot_path);
if (global) {
WriteSetting(QStringLiteral("romsPath"), UISettings::values.roms_path);
WriteSetting(QStringLiteral("symbolsPath"), UISettings::values.symbols_path);
WriteSetting(QStringLiteral("movieRecordPath"), UISettings::values.movie_record_path);
WriteSetting(QStringLiteral("moviePlaybackPath"), UISettings::values.movie_playback_path);
WriteSetting(QStringLiteral("videoDumpingPath"), UISettings::values.video_dumping_path);
qt_config->beginWriteArray(QStringLiteral("gamedirs"));
WriteSetting(Settings::QKeys::romsPath, UISettings::values.roms_path);
WriteSetting(Settings::QKeys::symbolsPath, UISettings::values.symbols_path);
WriteSetting(Settings::QKeys::movieRecordPath, UISettings::values.movie_record_path);
WriteSetting(Settings::QKeys::moviePlaybackPath, UISettings::values.movie_playback_path);
WriteSetting(Settings::QKeys::videoDumpingPath, UISettings::values.video_dumping_path);
qt_config->beginWriteArray(Settings::QKeys::gamedirs);
for (int i = 0; i < UISettings::values.game_dirs.size(); ++i) {
qt_config->setArrayIndex(i);
const auto& game_dir = UISettings::values.game_dirs[i];
WriteSetting(QStringLiteral("path"), game_dir.path);
WriteSetting(QStringLiteral("deep_scan"), game_dir.deep_scan, false);
WriteSetting(QStringLiteral("expanded"), game_dir.expanded, true);
WriteSetting(Settings::QKeys::path, game_dir.path);
WriteSetting(Settings::QKeys::deep_scan, game_dir.deep_scan, false);
WriteSetting(Settings::QKeys::expanded, game_dir.expanded, true);
}
qt_config->endArray();
WriteSetting(QStringLiteral("last_artic_base_addr"),
UISettings::values.last_artic_base_addr, QString{});
WriteSetting(QStringLiteral("recentFiles"), UISettings::values.recent_files);
WriteSetting(QStringLiteral("language"), UISettings::values.language, QString{});
WriteSetting(Settings::QKeys::last_artic_base_addr, UISettings::values.last_artic_base_addr,
QString{});
WriteSetting(Settings::QKeys::recentFiles, UISettings::values.recent_files);
WriteSetting(Settings::QKeys::language, UISettings::values.language, QString{});
WriteBasicSetting(UISettings::values.inserted_cartridge);
}
@ -1262,7 +1257,7 @@ void QtConfig::SaveRendererValues() {
WriteGlobalSetting(Settings::values.disable_right_eye_render);
if (global) {
WriteSetting(QStringLiteral("use_shader_jit"), Settings::values.use_shader_jit.GetValue(),
WriteSetting(Settings::QKeys::use_shader_jit, Settings::values.use_shader_jit.GetValue(),
true);
}
@ -1280,8 +1275,8 @@ void QtConfig::SaveShortcutValues() {
qt_config->beginGroup(group);
qt_config->beginGroup(name);
WriteSetting(QStringLiteral("KeySeq"), shortcut.keyseq, default_hotkey.keyseq);
WriteSetting(QStringLiteral("Context"), shortcut.context, default_hotkey.context);
WriteSetting(Settings::QKeys::KeySeq, shortcut.keyseq, default_hotkey.keyseq);
WriteSetting(Settings::QKeys::Context, shortcut.context, default_hotkey.context);
qt_config->endGroup();
qt_config->endGroup();
}
@ -1315,25 +1310,25 @@ void QtConfig::SaveSystemValues() {
void QtConfig::SaveVideoDumpingValues() {
qt_config->beginGroup(QStringLiteral("VideoDumping"));
WriteSetting(QStringLiteral("output_format"),
WriteSetting(Settings::QKeys::output_format,
QString::fromStdString(Settings::values.output_format), QStringLiteral("webm"));
WriteSetting(QStringLiteral("format_options"),
WriteSetting(Settings::QKeys::format_options,
QString::fromStdString(Settings::values.format_options));
WriteSetting(QStringLiteral("video_encoder"),
WriteSetting(Settings::QKeys::video_encoder,
QString::fromStdString(Settings::values.video_encoder),
QStringLiteral("libvpx-vp9"));
WriteSetting(QStringLiteral("video_encoder_options"),
WriteSetting(Settings::QKeys::video_encoder_options,
QString::fromStdString(Settings::values.video_encoder_options),
DEFAULT_VIDEO_ENCODER_OPTIONS);
WriteSetting(QStringLiteral("video_bitrate"),
WriteSetting(Settings::QKeys::video_bitrate,
static_cast<unsigned long long>(Settings::values.video_bitrate), 2500000);
WriteSetting(QStringLiteral("audio_encoder"),
WriteSetting(Settings::QKeys::audio_encoder,
QString::fromStdString(Settings::values.audio_encoder),
QStringLiteral("libvorbis"));
WriteSetting(QStringLiteral("audio_encoder_options"),
WriteSetting(Settings::QKeys::audio_encoder_options,
QString::fromStdString(Settings::values.audio_encoder_options),
DEFAULT_AUDIO_ENCODER_OPTIONS);
WriteSetting(QStringLiteral("audio_bitrate"),
WriteSetting(Settings::QKeys::audio_bitrate,
static_cast<unsigned long long>(Settings::values.audio_bitrate), 64000);
qt_config->endGroup();
@ -1345,7 +1340,7 @@ void QtConfig::SaveUIValues() {
SavePathValues();
if (global) {
WriteSetting(QStringLiteral("theme"), UISettings::values.theme,
WriteSetting(Settings::QKeys::theme, UISettings::values.theme,
QString::fromUtf8(UISettings::themes[0].second));
#ifdef USE_DISCORD_PRESENCE
WriteBasicSetting(UISettings::values.enable_discord_presence);
@ -1391,10 +1386,10 @@ void QtConfig::SaveUIGameListValues() {
WriteBasicSetting(UISettings::values.show_size_column);
WriteBasicSetting(UISettings::values.show_play_time_column);
qt_config->beginWriteArray(QStringLiteral("favorites"));
qt_config->beginWriteArray(Settings::QKeys::favorites);
for (int i = 0; i < UISettings::values.favorited_ids.size(); i++) {
qt_config->setArrayIndex(i);
WriteSetting(QStringLiteral("program_id"),
WriteSetting(Settings::QKeys::program_id,
QVariant::fromValue(UISettings::values.favorited_ids[i]));
}
qt_config->endArray();
@ -1405,11 +1400,11 @@ void QtConfig::SaveUIGameListValues() {
void QtConfig::SaveUILayoutValues() {
qt_config->beginGroup(QStringLiteral("UILayout"));
WriteSetting(QStringLiteral("geometry"), UISettings::values.geometry);
WriteSetting(QStringLiteral("state"), UISettings::values.state);
WriteSetting(QStringLiteral("geometryRenderWindow"), UISettings::values.renderwindow_geometry);
WriteSetting(QStringLiteral("gameListHeaderState"), UISettings::values.gamelist_header_state);
WriteSetting(QStringLiteral("microProfileDialogGeometry"),
WriteSetting(Settings::QKeys::geometry, UISettings::values.geometry);
WriteSetting(Settings::QKeys::state, UISettings::values.state);
WriteSetting(Settings::QKeys::geometryRenderWindow, UISettings::values.renderwindow_geometry);
WriteSetting(Settings::QKeys::gameListHeaderState, UISettings::values.gamelist_header_state);
WriteSetting(Settings::QKeys::microProfileDialogGeometry,
UISettings::values.microprofile_geometry);
WriteBasicSetting(UISettings::values.microprofile_visible);
@ -1419,12 +1414,12 @@ void QtConfig::SaveUILayoutValues() {
void QtConfig::SaveWebServiceValues() {
qt_config->beginGroup(QStringLiteral("WebService"));
WriteSetting(QStringLiteral("web_api_url"),
WriteSetting(Settings::QKeys::web_api_url,
QString::fromStdString(NetSettings::values.web_api_url),
QStringLiteral("https://api.citra-emu.org"));
WriteSetting(QStringLiteral("citra_username"),
WriteSetting(Settings::QKeys::citra_username,
QString::fromStdString(NetSettings::values.citra_username));
WriteSetting(QStringLiteral("citra_token"),
WriteSetting(Settings::QKeys::citra_token,
QString::fromStdString(NetSettings::values.citra_token));
qt_config->endGroup();

View File

@ -0,0 +1,19 @@
// Copyright Citra Emulator Project / Azahar Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <QString>
#define DEFINE_KEY(KEY) static const auto KEY = QStringLiteral(#KEY);
namespace Settings {
namespace QKeys {
@SETTING_KEY_DEFINITIONS@
}
}
#undef DEFINE_KEY

View File

@ -127,6 +127,7 @@ add_library(citra_common STATIC
scm_rev.cpp
scm_rev.h
scope_exit.h
setting_keys.h
settings.cpp
settings.h
slot_vector.h
@ -161,6 +162,8 @@ add_library(citra_common STATIC
zstd_compression.h
)
target_include_directories(citra_common PUBLIC ${CMAKE_BINARY_DIR}/src)
if (UNIX AND NOT APPLE)
target_sources(citra_common PRIVATE
linux/gamemode.cpp

View File

@ -0,0 +1,32 @@
// Copyright Citra Emulator Project / Azahar Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <boost/hana/string.hpp>
namespace Settings {
namespace Keys {
#define DEFINE_KEY(KEY) static constexpr char KEY[] = #KEY;
@SETTING_KEY_DEFINITIONS@
static const std::array keys_array = {
@SETTING_KEY_LIST@
};
#undef DEFINE_KEY
}
namespace HKeys {
#define DEFINE_KEY(KEY) static constexpr auto KEY = BOOST_HANA_STRING(#KEY);
@SETTING_KEY_DEFINITIONS@
#undef DEFINE_KEY
}
}

View File

@ -13,6 +13,8 @@
#include "audio_core/input_details.h"
#include "audio_core/sink_details.h"
#include "common/common_types.h"
#include "common/setting_keys.h"
#include "common/string_util.h"
#include "core/hle/service/cam/cam_params.h"
namespace Settings {
@ -34,7 +36,8 @@ enum class InitTicks : u32 {
};
/** Defines the layout option for desktop and mobile landscape */
enum class LayoutOption : u32 {
enum class LayoutOption : u32 { // Shouldn't these have set numbers to prevent last two from
// shifting? -OS
Default,
SingleScreen,
LargeScreen,
@ -224,7 +227,7 @@ public:
* @param default_val Intial value of the setting, and default value of the setting
* @param name Label for the setting
*/
explicit Setting(const Type& default_val, const std::string& name)
explicit Setting(const Type& default_val, const std::string_view& name)
requires(!ranged)
: value{default_val}, default_value{default_val}, label{name} {}
virtual ~Setting() = default;
@ -238,10 +241,10 @@ public:
* @param name Label for the setting
*/
explicit Setting(const Type& default_val, const Type& min_val, const Type& max_val,
const std::string& name)
const std::string_view& name)
requires(ranged)
: value{default_val}, default_value{default_val}, maximum{max_val}, minimum{min_val},
label{name} {}
label{std::string(name)} {}
/**
* Returns a reference to the setting's value.
@ -327,7 +330,7 @@ public:
* @param default_val Intial value of the setting, and default value of the setting
* @param name Label for the setting
*/
explicit SwitchableSetting(const Type& default_val, const std::string& name)
explicit SwitchableSetting(const Type& default_val, const std::string_view& name)
requires(!ranged)
: Setting<Type>{default_val, name} {}
virtual ~SwitchableSetting() = default;
@ -341,7 +344,7 @@ public:
* @param name Label for the setting
*/
explicit SwitchableSetting(const Type& default_val, const Type& min_val, const Type& max_val,
const std::string& name)
const std::string_view& name)
requires(ranged)
: Setting<Type, true>{default_val, min_val, max_val, name} {}
@ -461,35 +464,36 @@ struct Values {
int current_input_profile_index; ///< The current input profile index
std::vector<InputProfile> input_profiles; ///< The list of input profiles
std::vector<TouchFromButtonMap> touch_from_button_maps;
Setting<bool> use_artic_base_controller{false, "use_artic_base_controller"};
Setting<bool> use_artic_base_controller{false, Keys::use_artic_base_controller};
SwitchableSetting<bool> enable_gamemode{true, "enable_gamemode"};
SwitchableSetting<bool> enable_gamemode{true, Keys::enable_gamemode};
// Core
Setting<bool> use_cpu_jit{true, "use_cpu_jit"};
SwitchableSetting<s32, true> cpu_clock_percentage{100, 5, 400, "cpu_clock_percentage"};
SwitchableSetting<bool> is_new_3ds{true, "is_new_3ds"};
SwitchableSetting<bool> lle_applets{true, "lle_applets"};
SwitchableSetting<bool> deterministic_async_operations{false, "deterministic_async_operations"};
Setting<bool> use_cpu_jit{true, Keys::use_cpu_jit};
SwitchableSetting<s32, true> cpu_clock_percentage{100, 5, 400, Keys::cpu_clock_percentage};
SwitchableSetting<bool> is_new_3ds{true, Keys::is_new_3ds};
SwitchableSetting<bool> lle_applets{true, Keys::lle_applets};
SwitchableSetting<bool> deterministic_async_operations{false,
Keys::deterministic_async_operations};
SwitchableSetting<bool> enable_required_online_lle_modules{
false, "enable_required_online_lle_modules"};
false, Keys::enable_required_online_lle_modules};
// Data Storage
Setting<bool> use_virtual_sd{true, "use_virtual_sd"};
Setting<bool> use_custom_storage{false, "use_custom_storage"};
Setting<bool> compress_cia_installs{false, "compress_cia_installs"};
Setting<bool> use_virtual_sd{true, Keys::use_virtual_sd};
Setting<bool> use_custom_storage{false, Keys::use_custom_storage};
Setting<bool> compress_cia_installs{false, Keys::compress_cia_installs};
// System
SwitchableSetting<s32> region_value{REGION_VALUE_AUTO_SELECT, "region_value"};
Setting<InitClock> init_clock{InitClock::SystemTime, "init_clock"};
Setting<u64> init_time{946681277ULL, "init_time"};
Setting<s64> init_time_offset{0, "init_time_offset"};
Setting<InitTicks> init_ticks_type{InitTicks::Random, "init_ticks_type"};
Setting<s64> init_ticks_override{0, "init_ticks_override"};
Setting<bool> plugin_loader_enabled{false, "plugin_loader"};
Setting<bool> allow_plugin_loader{true, "allow_plugin_loader"};
Setting<u16> steps_per_hour{0, "steps_per_hour"};
Setting<bool> apply_region_free_patch{true, "apply_region_free_patch"};
SwitchableSetting<s32> region_value{REGION_VALUE_AUTO_SELECT, Keys::region_value};
Setting<InitClock> init_clock{InitClock::SystemTime, Keys::init_clock};
Setting<u64> init_time{946681277ULL, Keys::init_time};
Setting<s64> init_time_offset{0, Keys::init_time_offset};
Setting<InitTicks> init_ticks_type{InitTicks::Random, Keys::init_ticks_type};
Setting<s64> init_ticks_override{0, Keys::init_ticks_override};
Setting<bool> plugin_loader_enabled{false, Keys::plugin_loader};
Setting<bool> allow_plugin_loader{true, Keys::allow_plugin_loader};
Setting<u16> steps_per_hour{0, Keys::steps_per_hour};
Setting<bool> apply_region_free_patch{true, Keys::apply_region_free_patch};
// Renderer
SwitchableSetting<GraphicsAPI, true> graphics_api{
@ -503,41 +507,41 @@ struct Values {
// TODO: Add a null renderer backend for this, perhaps.
#error "At least one renderer must be enabled."
#endif
GraphicsAPI::Software, GraphicsAPI::Vulkan, "graphics_api"};
SwitchableSetting<u32> physical_device{0, "physical_device"};
Setting<bool> use_gles{false, "use_gles"};
Setting<bool> renderer_debug{false, "renderer_debug"};
Setting<bool> dump_command_buffers{false, "dump_command_buffers"};
SwitchableSetting<bool> spirv_shader_gen{true, "spirv_shader_gen"};
SwitchableSetting<bool> disable_spirv_optimizer{true, "disable_spirv_optimizer"};
SwitchableSetting<bool> async_shader_compilation{false, "async_shader_compilation"};
SwitchableSetting<bool> async_presentation{true, "async_presentation"};
SwitchableSetting<bool> use_hw_shader{true, "use_hw_shader"};
SwitchableSetting<bool> use_disk_shader_cache{true, "use_disk_shader_cache"};
SwitchableSetting<bool> shaders_accurate_mul{true, "shaders_accurate_mul"};
GraphicsAPI::Software, GraphicsAPI::Vulkan, Keys::graphics_api};
SwitchableSetting<u32> physical_device{0, Keys::physical_device};
Setting<bool> use_gles{false, Keys::use_gles};
Setting<bool> renderer_debug{false, Keys::renderer_debug};
Setting<bool> dump_command_buffers{false, Keys::dump_command_buffers};
SwitchableSetting<bool> spirv_shader_gen{true, Keys::spirv_shader_gen};
SwitchableSetting<bool> disable_spirv_optimizer{true, Keys::disable_spirv_optimizer};
SwitchableSetting<bool> async_shader_compilation{false, Keys::async_shader_compilation};
SwitchableSetting<bool> async_presentation{true, Keys::async_presentation};
SwitchableSetting<bool> use_hw_shader{true, Keys::use_hw_shader};
SwitchableSetting<bool> use_disk_shader_cache{true, Keys::use_disk_shader_cache};
SwitchableSetting<bool> shaders_accurate_mul{true, Keys::shaders_accurate_mul};
#ifdef ANDROID // TODO: Fuck this -OS
SwitchableSetting<bool> use_vsync{false, "use_vsync"};
SwitchableSetting<bool> use_vsync{false, Keys::use_vsync};
#else
SwitchableSetting<bool> use_vsync{true, "use_vsync"};
SwitchableSetting<bool> use_vsync{true, Keys::use_vsync};
#endif
SwitchableSetting<bool> use_display_refresh_rate_detection{
true, "use_display_refresh_rate_detection"};
Setting<bool> use_shader_jit{true, "use_shader_jit"};
SwitchableSetting<u32, true> resolution_factor{1, 0, 10, "resolution_factor"};
SwitchableSetting<bool> use_integer_scaling{false, "use_integer_scaling"};
SwitchableSetting<double, true> frame_limit{100, 0, 1000, "frame_limit"};
SwitchableSetting<double, true> turbo_limit{200, 0, 1000, "turbo_limit"};
SwitchableSetting<TextureFilter> texture_filter{TextureFilter::NoFilter, "texture_filter"};
true, Keys::use_display_refresh_rate_detection};
Setting<bool> use_shader_jit{true, Keys::use_shader_jit};
SwitchableSetting<u32, true> resolution_factor{1, 0, 10, Keys::resolution_factor};
SwitchableSetting<bool> use_integer_scaling{false, Keys::use_integer_scaling};
SwitchableSetting<double, true> frame_limit{100, 0, 1000, Keys::frame_limit};
SwitchableSetting<double, true> turbo_limit{200, 0, 1000, Keys::turbo_limit};
SwitchableSetting<TextureFilter> texture_filter{TextureFilter::NoFilter, Keys::texture_filter};
SwitchableSetting<TextureSampling> texture_sampling{TextureSampling::GameControlled,
"texture_sampling"};
Keys::texture_sampling};
SwitchableSetting<u16, true> delay_game_render_thread_us{0, 0, 16000,
"delay_game_render_thread_us"};
Keys::delay_game_render_thread_us};
SwitchableSetting<LayoutOption> layout_option{LayoutOption::Default, "layout_option"};
SwitchableSetting<bool> swap_screen{false, "swap_screen"};
SwitchableSetting<bool> upright_screen{false, "upright_screen"};
SwitchableSetting<SecondaryDisplayLayout> secondary_display_layout{SecondaryDisplayLayout::None,
"secondary_display_layout"};
SwitchableSetting<LayoutOption> layout_option{LayoutOption::Default, Keys::layout_option};
SwitchableSetting<bool> swap_screen{false, Keys::swap_screen};
SwitchableSetting<bool> upright_screen{false, Keys::upright_screen};
SwitchableSetting<SecondaryDisplayLayout> secondary_display_layout{
SecondaryDisplayLayout::None, Keys::secondary_display_layout};
SwitchableSetting<std::vector<LayoutOption>> layouts_to_cycle{
{LayoutOption::Default, LayoutOption::SingleScreen, LayoutOption::LargeScreen,
LayoutOption::SideScreen,
@ -545,77 +549,78 @@ struct Values {
LayoutOption::SeparateWindows,
#endif
LayoutOption::HybridScreen, LayoutOption::CustomLayout},
"layouts_to_cycle"};
Keys::layouts_to_cycle};
SwitchableSetting<float, true> large_screen_proportion{4.f, 1.f, 16.f,
"large_screen_proportion"};
SwitchableSetting<int> screen_gap{0, "screen_gap"};
Keys::large_screen_proportion};
SwitchableSetting<int> screen_gap{0, Keys::screen_gap};
SwitchableSetting<SmallScreenPosition> small_screen_position{SmallScreenPosition::BottomRight,
"small_screen_position"};
Setting<u16> custom_top_x{0, "custom_top_x"};
Setting<u16> custom_top_y{0, "custom_top_y"};
Setting<u16> custom_top_width{800, "custom_top_width"};
Setting<u16> custom_top_height{480, "custom_top_height"};
Setting<u16> custom_bottom_x{80, "custom_bottom_x"};
Setting<u16> custom_bottom_y{500, "custom_bottom_y"};
Setting<u16> custom_bottom_width{640, "custom_bottom_width"};
Setting<u16> custom_bottom_height{480, "custom_bottom_height"};
Setting<u16> custom_second_layer_opacity{100, "custom_second_layer_opacity"};
SwitchableSetting<AspectRatio> aspect_ratio{AspectRatio::Default, "aspect_ratio"};
SwitchableSetting<bool> screen_top_stretch{false, "screen_top_stretch"};
Setting<u16> screen_top_leftright_padding{0, "screen_top_leftright_padding"};
Setting<u16> screen_top_topbottom_padding{0, "screen_top_topbottom_padding"};
SwitchableSetting<bool> screen_bottom_stretch{false, "screen_bottom_stretch"};
Setting<u16> screen_bottom_leftright_padding{0, "screen_bottom_leftright_padding"};
Setting<u16> screen_bottom_topbottom_padding{0, "screen_bottom_topbottom_padding"};
Keys::small_screen_position};
Setting<u16> custom_top_x{0, Keys::custom_top_x};
Setting<u16> custom_top_y{0, Keys::custom_top_y};
Setting<u16> custom_top_width{800, Keys::custom_top_width};
Setting<u16> custom_top_height{480, Keys::custom_top_height};
Setting<u16> custom_bottom_x{80, Keys::custom_bottom_x};
Setting<u16> custom_bottom_y{500, Keys::custom_bottom_y};
Setting<u16> custom_bottom_width{640, Keys::custom_bottom_width};
Setting<u16> custom_bottom_height{480, Keys::custom_bottom_height};
Setting<u16> custom_second_layer_opacity{100, Keys::custom_second_layer_opacity};
SwitchableSetting<AspectRatio> aspect_ratio{AspectRatio::Default, Keys::aspect_ratio};
SwitchableSetting<bool> screen_top_stretch{false, Keys::screen_top_stretch};
Setting<u16> screen_top_leftright_padding{0, Keys::screen_top_leftright_padding};
Setting<u16> screen_top_topbottom_padding{0, Keys::screen_top_topbottom_padding};
SwitchableSetting<bool> screen_bottom_stretch{false, Keys::screen_bottom_stretch};
Setting<u16> screen_bottom_leftright_padding{0, Keys::screen_bottom_leftright_padding};
Setting<u16> screen_bottom_topbottom_padding{0, Keys::screen_bottom_topbottom_padding};
SwitchableSetting<PortraitLayoutOption> portrait_layout_option{
PortraitLayoutOption::PortraitTopFullWidth, "portrait_layout_option"};
Setting<u16> custom_portrait_top_x{0, "custom_portrait_top_x"};
Setting<u16> custom_portrait_top_y{0, "custom_portrait_top_y"};
Setting<u16> custom_portrait_top_width{800, "custom_portrait_top_width"};
Setting<u16> custom_portrait_top_height{480, "custom_portrait_top_height"};
Setting<u16> custom_portrait_bottom_x{80, "custom_portrait_bottom_x"};
Setting<u16> custom_portrait_bottom_y{500, "custom_portrait_bottom_y"};
Setting<u16> custom_portrait_bottom_width{640, "custom_portrait_bottom_width"};
Setting<u16> custom_portrait_bottom_height{480, "custom_portrait_bottom_height"};
PortraitLayoutOption::PortraitTopFullWidth, Keys::portrait_layout_option};
Setting<u16> custom_portrait_top_x{0, Keys::custom_portrait_top_x};
Setting<u16> custom_portrait_top_y{0, Keys::custom_portrait_top_y};
Setting<u16> custom_portrait_top_width{800, Keys::custom_portrait_top_width};
Setting<u16> custom_portrait_top_height{480, Keys::custom_portrait_top_height};
Setting<u16> custom_portrait_bottom_x{80, Keys::custom_portrait_bottom_x};
Setting<u16> custom_portrait_bottom_y{500, Keys::custom_portrait_bottom_y};
Setting<u16> custom_portrait_bottom_width{640, Keys::custom_portrait_bottom_width};
Setting<u16> custom_portrait_bottom_height{480, Keys::custom_portrait_bottom_height};
SwitchableSetting<float> bg_red{0.f, "bg_red"};
SwitchableSetting<float> bg_green{0.f, "bg_green"};
SwitchableSetting<float> bg_blue{0.f, "bg_blue"};
SwitchableSetting<float> bg_red{0.f, Keys::bg_red};
SwitchableSetting<float> bg_green{0.f, Keys::bg_green};
SwitchableSetting<float> bg_blue{0.f, Keys::bg_blue};
SwitchableSetting<StereoRenderOption> render_3d{StereoRenderOption::Off, "render_3d"};
SwitchableSetting<u32> factor_3d{0, "factor_3d"};
SwitchableSetting<bool> swap_eyes_3d{false, "swap_eyes_3d"};
SwitchableSetting<StereoRenderOption> render_3d{StereoRenderOption::Off, Keys::render_3d};
SwitchableSetting<u32> factor_3d{0, Keys::factor_3d};
SwitchableSetting<bool> swap_eyes_3d{false, Keys::swap_eyes_3d};
SwitchableSetting<StereoWhichDisplay> render_3d_which_display{StereoWhichDisplay::None,
"render_3d_which_display"};
Keys::render_3d_which_display};
SwitchableSetting<MonoRenderOption> mono_render_option{MonoRenderOption::LeftEye,
"mono_render_option"};
Keys::mono_render_option};
Setting<u32> cardboard_screen_size{85, "cardboard_screen_size"};
Setting<s32> cardboard_x_shift{0, "cardboard_x_shift"};
Setting<s32> cardboard_y_shift{0, "cardboard_y_shift"};
Setting<u32> cardboard_screen_size{85, Keys::cardboard_screen_size};
Setting<s32> cardboard_x_shift{0, Keys::cardboard_x_shift};
Setting<s32> cardboard_y_shift{0, Keys::cardboard_y_shift};
SwitchableSetting<bool> filter_mode{true, "filter_mode"};
SwitchableSetting<std::string> pp_shader_name{"None (builtin)", "pp_shader_name"};
SwitchableSetting<std::string> anaglyph_shader_name{"Dubois (builtin)", "anaglyph_shader_name"};
SwitchableSetting<bool> filter_mode{true, Keys::filter_mode};
SwitchableSetting<std::string> pp_shader_name{"None (builtin)", Keys::pp_shader_name};
SwitchableSetting<std::string> anaglyph_shader_name{"Dubois (builtin)",
Keys::anaglyph_shader_name};
SwitchableSetting<bool> dump_textures{false, "dump_textures"};
SwitchableSetting<bool> custom_textures{false, "custom_textures"};
SwitchableSetting<bool> preload_textures{false, "preload_textures"};
SwitchableSetting<bool> async_custom_loading{true, "async_custom_loading"};
SwitchableSetting<bool> disable_right_eye_render{false, "disable_right_eye_render"};
SwitchableSetting<bool> dump_textures{false, Keys::dump_textures};
SwitchableSetting<bool> custom_textures{false, Keys::custom_textures};
SwitchableSetting<bool> preload_textures{false, Keys::preload_textures};
SwitchableSetting<bool> async_custom_loading{true, Keys::async_custom_loading};
SwitchableSetting<bool> disable_right_eye_render{false, Keys::disable_right_eye_render};
// Audio
bool audio_muted;
SwitchableSetting<AudioEmulation> audio_emulation{AudioEmulation::HLE, "audio_emulation"};
SwitchableSetting<bool> enable_audio_stretching{true, "enable_audio_stretching"};
SwitchableSetting<bool> enable_realtime_audio{false, "enable_realtime_audio"};
SwitchableSetting<float, true> volume{1.f, 0.f, 1.f, "volume"};
Setting<AudioCore::SinkType> output_type{AudioCore::SinkType::Auto, "output_type"};
Setting<std::string> output_device{"Auto", "output_device"};
Setting<AudioCore::InputType> input_type{AudioCore::InputType::Auto, "input_type"};
Setting<std::string> input_device{"Auto", "input_device"};
SwitchableSetting<AudioEmulation> audio_emulation{AudioEmulation::HLE, Keys::audio_emulation};
SwitchableSetting<bool> enable_audio_stretching{true, Keys::enable_audio_stretching};
SwitchableSetting<bool> enable_realtime_audio{false, Keys::enable_realtime_audio};
SwitchableSetting<float, true> volume{1.f, 0.f, 1.f, Keys::volume};
Setting<AudioCore::SinkType> output_type{AudioCore::SinkType::Auto, Keys::output_type};
Setting<std::string> output_device{"Auto", Keys::output_device};
Setting<AudioCore::InputType> input_type{AudioCore::InputType::Auto, Keys::input_type};
Setting<std::string> input_device{"Auto", Keys::input_device};
// Camera
std::array<std::string, Service::CAM::NumCameras> camera_name;
@ -625,15 +630,15 @@ struct Values {
// Debugging
bool record_frame_times;
std::unordered_map<std::string, bool> lle_modules;
Setting<bool> delay_start_for_lle_modules{true, "delay_start_for_lle_modules"};
Setting<bool> use_gdbstub{false, "use_gdbstub"};
Setting<u16> gdbstub_port{24689, "gdbstub_port"};
Setting<bool> instant_debug_log{false, "instant_debug_log"};
Setting<bool> enable_rpc_server{false, "enable_rpc_server"};
Setting<bool> delay_start_for_lle_modules{true, Keys::delay_start_for_lle_modules};
Setting<bool> use_gdbstub{false, Keys::use_gdbstub};
Setting<u16> gdbstub_port{24689, Keys::gdbstub_port};
Setting<bool> instant_debug_log{false, Keys::instant_debug_log};
Setting<bool> enable_rpc_server{false, Keys::enable_rpc_server};
// Miscellaneous
Setting<std::string> log_filter{"*:Info", "log_filter"};
Setting<std::string> log_regex_filter{"", "log_regex_filter"};
Setting<std::string> log_filter{"*:Info", Keys::log_filter};
Setting<std::string> log_regex_filter{"", Keys::log_regex_filter};
// Video Dumping
std::string output_format;

View File

@ -1,4 +1,4 @@
// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project
// Copyright Citra Emulator Project / Azahar Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
@ -101,4 +101,6 @@ inline void TruncateString(std::string& str) {
[[nodiscard]] std::string StringFromFixedZeroTerminatedBuffer(const char* buffer,
std::size_t max_len);
#define HANA_TO_STD_STRING(hana_string) std::string(hana_string.c_str())
} // namespace Common