#pragma once #include "ConfigValue.h" #include "XMLConfig.h" #include "util/math/vector2.h" #include "Cafe/Account/Account.h" #include struct GameEntry { GameEntry() = default; std::wstring rpx_file; std::wstring legacy_name; std::string product_code; std::string company_code; std::string custom_name; sint32 icon = -1; sint32 icon_small = -1; sint32 legacy_version = 0; sint32 legacy_update_version = -1; sint32 legacy_dlc_version = -1; uint64 title_id = 0; uint32 legacy_region = 0; std::wstring save_folder; std::wstring update_folder; std::wstring dlc_folder; uint64 legacy_time_played = 0; uint64 legacy_last_played = 0; bool favorite = false; bool is_update = false; }; struct GraphicPackEntry { GraphicPackEntry(std::wstring_view filename,std::string_view category, std::string_view preset) : filename(filename) { presets[std::string{category}] = preset; } GraphicPackEntry(std::wstring_view filename, std::string_view preset) : filename(filename) { presets[""] = preset; } GraphicPackEntry(std::wstring filename) : filename(std::move(filename)) {} struct Preset { std::string name; std::string category; }; std::unordered_map presets; // category, active_preset std::wstring filename; bool enabled = true; }; enum GraphicAPI { kOpenGL = 0, kVulkan, }; enum AudioChannels { kMono = 0, kStereo, kSurround, }; enum UpscalingFilter { kLinearFilter, kBicubicFilter, kBicubicHermiteFilter, kNearestNeighborFilter, }; enum FullscreenScaling { kKeepAspectRatio, kStretch, }; enum class ScreenPosition { kDisabled = 0, kTopLeft, kTopCenter, kTopRight, kBottomLeft, kBottomCenter, kBottomRight, }; enum class PrecompiledShaderOption { Auto, Enable, Disable, }; ENABLE_ENUM_ITERATORS(PrecompiledShaderOption, PrecompiledShaderOption::Auto, PrecompiledShaderOption::Disable); enum class AccurateShaderMulOption { False = 0, // always use standard multiplication True = 1 // fully emulate non-ieee MUL special cases (0*anything = 0) }; ENABLE_ENUM_ITERATORS(AccurateShaderMulOption, AccurateShaderMulOption::False, AccurateShaderMulOption::True); enum class CPUMode { SinglecoreInterpreter = 0, SinglecoreRecompiler = 1, DualcoreRecompiler = 2, // deprecated and not used anymore MulticoreRecompiler = 3, Auto = 4, }; ENABLE_ENUM_ITERATORS(CPUMode, CPUMode::SinglecoreInterpreter, CPUMode::Auto); enum class CPUModeLegacy { SinglecoreInterpreter = 0, SinglecoreRecompiler = 1, DualcoreRecompiler = 2, TriplecoreRecompiler = 3, Auto = 4 }; ENABLE_ENUM_ITERATORS(CPUModeLegacy, CPUModeLegacy::SinglecoreInterpreter, CPUModeLegacy::Auto); enum class CafeConsoleRegion { JPN = 0x1, USA = 0x2, EUR = 0x4, AUS_DEPR = 0x8, CHN = 0x10, KOR = 0x20, TWN = 0x40, Auto = 0xFF, }; ENABLE_BITMASK_OPERATORS(CafeConsoleRegion); enum class CafeConsoleLanguage { JA = 0, EN = 1, FR = 2, DE = 3, IT = 4, ES = 5, ZH = 6, KO = 7, NL = 8, PT = 9, RU = 10, TW = 11, }; ENABLE_ENUM_ITERATORS(CafeConsoleLanguage, CafeConsoleLanguage::JA, CafeConsoleLanguage::TW); #if BOOST_OS_WINDOWS enum class CrashDump { Disabled, Lite, Full }; ENABLE_ENUM_ITERATORS(CrashDump, CrashDump::Disabled, CrashDump::Full); #elif BOOST_OS_UNIX enum class CrashDump { Disabled, Enabled }; ENABLE_ENUM_ITERATORS(CrashDump, CrashDump::Disabled, CrashDump::Enabled); #endif template <> struct fmt::formatter : formatter { template auto format(const PrecompiledShaderOption c, FormatContext &ctx) { string_view name; switch (c) { case PrecompiledShaderOption::Auto: name = "auto"; break; case PrecompiledShaderOption::Enable: name = "true"; break; case PrecompiledShaderOption::Disable: name = "false"; break; default: name = "unknown"; break; } return formatter::format(name, ctx); } }; template <> struct fmt::formatter : formatter { template auto format(const AccurateShaderMulOption c, FormatContext &ctx) { string_view name; switch (c) { case AccurateShaderMulOption::True: name = "true"; break; case AccurateShaderMulOption::False: name = "false"; break; default: name = "unknown"; break; } return formatter::format(name, ctx); } }; template <> struct fmt::formatter : formatter { template auto format(const CPUMode c, FormatContext &ctx) { string_view name; switch (c) { case CPUMode::SinglecoreInterpreter: name = "Single-core interpreter"; break; case CPUMode::SinglecoreRecompiler: name = "Single-core recompiler"; break; case CPUMode::DualcoreRecompiler: name = "Dual-core recompiler"; break; case CPUMode::MulticoreRecompiler: name = "Multi-core recompiler"; break; case CPUMode::Auto: name = "Auto"; break; default: name = "unknown"; break; } return formatter::format(name, ctx); } }; template <> struct fmt::formatter : formatter { template auto format(const CPUModeLegacy c, FormatContext &ctx) { string_view name; switch (c) { case CPUModeLegacy::SinglecoreInterpreter: name = "Singlecore-Interpreter"; break; case CPUModeLegacy::SinglecoreRecompiler: name = "Singlecore-Recompiler"; break; case CPUModeLegacy::DualcoreRecompiler: name = "Dualcore-Recompiler"; break; case CPUModeLegacy::TriplecoreRecompiler: name = "Triplecore-Recompiler"; break; case CPUModeLegacy::Auto: name = "Auto"; break; default: name = "unknown"; break; } return formatter::format(name, ctx); } }; template <> struct fmt::formatter : formatter { template auto format(const CafeConsoleRegion v, FormatContext &ctx) { string_view name; switch (v) { case CafeConsoleRegion::JPN: name = "Japan"; break; case CafeConsoleRegion::USA: name = "USA"; break; case CafeConsoleRegion::EUR: name = "Europe"; break; case CafeConsoleRegion::AUS_DEPR: name = "Australia"; break; case CafeConsoleRegion::CHN: name = "China"; break; case CafeConsoleRegion::KOR: name = "Korea"; break; case CafeConsoleRegion::TWN: name = "Taiwan"; break; case CafeConsoleRegion::Auto: name = "Auto"; break; default: name = "many"; break; } return formatter::format(name, ctx); } }; template <> struct fmt::formatter : formatter { template auto format(const CafeConsoleLanguage v, FormatContext &ctx) { string_view name; switch (v) { case CafeConsoleLanguage::JA: name = "Japanese"; break; case CafeConsoleLanguage::EN: name = "English"; break; case CafeConsoleLanguage::FR: name = "French"; break; case CafeConsoleLanguage::DE: name = "German"; break; case CafeConsoleLanguage::IT: name = "Italian"; break; case CafeConsoleLanguage::ES: name = "Spanish"; break; case CafeConsoleLanguage::ZH: name = "Chinese"; break; case CafeConsoleLanguage::KO: name = "Korean"; break; case CafeConsoleLanguage::NL: name = "Dutch"; break; case CafeConsoleLanguage::PT: name = "Portugese"; break; case CafeConsoleLanguage::RU: name = "Russian"; break; case CafeConsoleLanguage::TW: name = "Taiwanese"; break; default: name = "unknown"; break; } return formatter::format(name, ctx); } }; #if BOOST_OS_WINDOWS template <> struct fmt::formatter : formatter { template auto format(const CrashDump v, FormatContext &ctx) { string_view name; switch (v) { case CrashDump::Disabled: name = "Disabled"; break; case CrashDump::Lite: name = "Lite"; break; case CrashDump::Full: name = "Full"; break; default: name = "unknown"; break; } return formatter::format(name, ctx); } }; #elif BOOST_OS_UNIX template <> struct fmt::formatter : formatter { template auto format(const CrashDump v, FormatContext &ctx) { string_view name; switch (v) { case CrashDump::Disabled: name = "Disabled"; break; case CrashDump::Enabled: name = "Enabled"; break; default: name = "unknown"; break; } return formatter::format(name, ctx); } }; #endif namespace DefaultColumnSize { enum : uint32 { name = 500u, version = 60u, dlc = 50u, game_time = 140u, game_started = 160u, region = 80u, }; }; struct CemuConfig { CemuConfig() { }; CemuConfig(const CemuConfig&) = delete; // // sets mlc path, updates permanent config value, saves config void SetMLCPath(fs::path path, bool save = true); ConfigValue log_flag{ 0 }; ConfigValue advanced_ppc_logging{ false }; ConfigValue permanent_storage{ true }; ConfigValue language{ wxLANGUAGE_DEFAULT }; ConfigValue use_discord_presence{ true }; ConfigValue mlc_path {}; ConfigValue fullscreen_menubar{ false }; ConfigValue fullscreen{ false }; ConfigValue proxy_server{}; // temporary workaround because feature crashes on macOS #if BOOST_OS_MACOS #define DISABLE_SCREENSAVER_DEFAULT false #else #define DISABLE_SCREENSAVER_DEFAULT true #endif ConfigValue disable_screensaver{DISABLE_SCREENSAVER_DEFAULT}; #undef DISABLE_SCREENSAVER_DEFAULT std::vector game_paths; std::mutex game_cache_entries_mutex; std::vector game_cache_entries; // optimized access std::set game_cache_favorites; // per titleId struct _path_hash { std::size_t operator()(const fs::path& path) const { return fs::hash_value(path); } }; // > std::unordered_map, _path_hash> graphic_pack_entries; ConfigValueBounds cpu_mode{ CPUMode::Auto }; ConfigValueBounds console_language{ CafeConsoleLanguage::EN }; // max 15 entries static constexpr size_t kMaxRecentEntries = 15; std::vector recent_launch_files; std::vector recent_nfc_files; Vector2i window_position{-1,-1}; Vector2i window_size{ -1,-1 }; ConfigValue window_maximized; ConfigValue pad_open; Vector2i pad_position{ -1,-1 }; Vector2i pad_size{ -1,-1 }; ConfigValue pad_maximized; ConfigValue check_update{false}; ConfigValue save_screenshot{true}; ConfigValue did_show_vulkan_warning{false}; ConfigValue did_show_graphic_pack_download{false}; ConfigValue did_show_macos_disclaimer{false}; int game_list_style = 0; std::string game_list_column_order; struct { uint32 name = DefaultColumnSize::name; uint32 version = DefaultColumnSize::version; uint32 dlc = DefaultColumnSize::dlc; uint32 game_time = DefaultColumnSize::game_time; uint32 game_started = DefaultColumnSize::game_started; uint32 region = DefaultColumnSize::region; } column_width{}; // graphics ConfigValue graphic_api{ kVulkan }; std::array graphic_device_uuid; ConfigValue vsync{ 0 }; // 0 = off, 1+ = on depending on render backend ConfigValue gx2drawdone_sync {true}; ConfigValue render_upside_down{ false }; ConfigValue async_compile{ false }; ConfigValue vk_accurate_barriers{ true }; struct { ScreenPosition position = ScreenPosition::kDisabled; uint32 text_color = 0xFFFFFFFF; sint32 text_scale = 100; bool fps = true; bool drawcalls = false; bool cpu_usage = false; bool cpu_per_core_usage = false; bool ram_usage = false; bool vram_usage = false; bool debug = false; } overlay{}; struct { ScreenPosition position = ScreenPosition::kTopLeft; uint32 text_color = 0xFFFFFFFF; sint32 text_scale = 100; bool controller_profiles = true; bool controller_battery = false; bool shader_compiling = true; bool friends = true; } notification{}; ConfigValue upscale_filter{kBicubicFilter}; ConfigValue downscale_filter{kLinearFilter}; ConfigValue fullscreen_scaling{kKeepAspectRatio}; // audio sint32 audio_api = 0; sint32 audio_delay = 2; AudioChannels tv_channels = kStereo, pad_channels = kStereo, input_channels = kMono; sint32 tv_volume = 50, pad_volume = 0, input_volume = 50; std::wstring tv_device{ L"default" }, pad_device, input_device; // account struct { ConfigValueBounds m_persistent_id{ Account::kMinPersistendId, Account::kMinPersistendId, 0xFFFFFFFF }; ConfigValue online_enabled{false}; ConfigValue active_service{0}; }account{}; // input struct { ConfigValue host{"127.0.0.1"}; ConfigValue port{ 26760 }; }dsu_client{}; // debug ConfigValueBounds crash_dump{ CrashDump::Disabled }; ConfigValue gdb_port{ 1337 }; void Load(XMLConfigParser& parser); void Save(XMLConfigParser& parser); void AddRecentlyLaunchedFile(std::wstring_view file); void AddRecentNfcFile(std::wstring_view file); bool IsGameListFavorite(uint64 titleId); void SetGameListFavorite(uint64 titleId, bool isFavorite); bool GetGameListCustomName(uint64 titleId, std::string& customName); void SetGameListCustomName(uint64 titleId, std::string customName); private: GameEntry* GetGameEntryByTitleId(uint64 titleId); GameEntry* CreateGameEntry(uint64 titleId); }; typedef XMLDataConfig XMLCemuConfig_t; extern XMLCemuConfig_t g_config; inline CemuConfig& GetConfig() { return g_config.data(); }