diff --git a/app/src/main/cpp/skyline/common/languages.h b/app/src/main/cpp/skyline/common/languages.h index 3cbca3ad..56c7c51c 100644 --- a/app/src/main/cpp/skyline/common/languages.h +++ b/app/src/main/cpp/skyline/common/languages.h @@ -5,6 +5,7 @@ #include #include +#include namespace skyline { namespace constant { @@ -13,121 +14,94 @@ namespace skyline { } namespace languages { + /** + * @brief The list of all languages. Entries parameters are language, language code, system language index, application language index and map which holds a macro used for filtering some application languages that don't have a direct corresponding system language + * @example #define LANG_ENTRY(lang, code, sysIndex, appIndex, map) func(lang, code, sysIndex, appIndex, map)
LANGUAGES
#undef LANG_ENTRY + */ + #define LANGUAGES \ + LANG_ENTRY(Japanese, ja, 0, 2, MAP) \ + LANG_ENTRY(AmericanEnglish, en-us, 1, 0, MAP) \ + LANG_ENTRY(French, fr, 2, 3, MAP) \ + LANG_ENTRY(German, de, 3, 4, MAP) \ + LANG_ENTRY(Italian, it, 4, 7, MAP) \ + LANG_ENTRY(Spanish, es, 5, 6, MAP) \ + LANG_ENTRY(Chinese, zh-CN, 6, 14, DONT_MAP) \ + LANG_ENTRY(Korean, ko, 7, 12, MAP) \ + LANG_ENTRY(Dutch, nl, 8, 8, MAP) \ + LANG_ENTRY(Portuguese, pt, 9, 10, MAP) \ + LANG_ENTRY(Russian, ru, 10, 11, MAP) \ + LANG_ENTRY(Taiwanese, zh-TW, 11, 13, DONT_MAP) \ + LANG_ENTRY(BritishEnglish, en-GB, 12, 1, MAP) \ + LANG_ENTRY(CanadianFrench, fr-CA, 13, 9, MAP) \ + LANG_ENTRY(LatinAmericanSpanish, es-419, 14, 5, MAP) \ + LANG_ENTRY(SimplifiedChinese, zh-Hans, 15, 14, MAP) \ + LANG_ENTRY(TraditionalChinese, zh-Hant, 16, 13, MAP) \ + LANG_ENTRY(BrazilianPortuguese, pt-BR, 17, 10, DONT_MAP) + + /** + * @brief Enumeration of system languages + * @url https://switchbrew.org/wiki/Settings_services#Language + */ enum class SystemLanguage : u32 { - Japanese = 0, - AmericanEnglish, - French, - German, - Italian, - Spanish, - Chinese, - Korean, - Dutch, - Portuguese, - Russian, - Taiwanese, - BritishEnglish, - CanadianFrench, - LatinAmericanSpanish, - SimplifiedChinese, - TraditionalChinese, - BrazilianPortuguese, + #define LANG_ENTRY(lang, code, sysIndex, appIndex, map) lang = sysIndex, + LANGUAGES + #undef LANG_ENTRY }; + #define LANG_ENTRY(lang, code, sysIndex, appIndex, map) ENUM_CASE(lang); + ENUM_STRING(SystemLanguage, LANGUAGES) + #undef LANG_ENTRY + + /** + * @brief Enumeration of application languages + * @url https://switchbrew.org/wiki/NACP#ApplicationTitle + */ enum class ApplicationLanguage : u32 { - AmericanEnglish = 0, - BritishEnglish, - Japanese, - French, - German, - LatinAmericanSpanish, - Spanish, - Italian, - Dutch, - CanadianFrench, - Portuguese, - Russian, - Korean, - TraditionalChinese, - SimplifiedChinese, + #define LANG_ENTRY(lang, code, sysIndex, appIndex, map) lang = appIndex, + LANGUAGES + #undef LANG_ENTRY }; + #define LANG_ENTRY(lang, code, sysIndex, appIndex, map) map(lang); + #define MAP(key) ENUM_CASE(key) + #define DONT_MAP(key) + ENUM_STRING(ApplicationLanguage, LANGUAGES) + #undef LANG_ENTRY + #undef MAP + #undef DONT_MAP + constexpr std::array LanguageCodeList{ - util::MakeMagic("ja"), - util::MakeMagic("en-US"), - util::MakeMagic("fr"), - util::MakeMagic("de"), - util::MakeMagic("it"), - util::MakeMagic("es"), - util::MakeMagic("zh-CN"), - util::MakeMagic("ko"), - util::MakeMagic("nl"), - util::MakeMagic("pt"), - util::MakeMagic("ru"), - util::MakeMagic("zh-TW"), - util::MakeMagic("en-GB"), - util::MakeMagic("fr-CA"), - util::MakeMagic("es-419"), - util::MakeMagic("zh-Hans"), - util::MakeMagic("zh-Hant"), - util::MakeMagic("pt-BR"), + #define LANG_ENTRY(lang, code, sysIndex, appIndex, map) util::MakeMagic(#code), + LANGUAGES + #undef LANG_ENTRY }; constexpr u64 GetLanguageCode(SystemLanguage language) { return LanguageCodeList.at(static_cast(language)); } - #define LANG_MAP_ENTRY(lang) {SystemLanguage::lang, ApplicationLanguage::lang} - #define LANG_MAP_ENTRY_CST(sysLang, appLang) {SystemLanguage::sysLang, ApplicationLanguage::appLang} - constexpr frz::unordered_map SystemToAppMap{ - LANG_MAP_ENTRY(Japanese), - LANG_MAP_ENTRY(AmericanEnglish), - LANG_MAP_ENTRY(French), - LANG_MAP_ENTRY(German), - LANG_MAP_ENTRY(Italian), - LANG_MAP_ENTRY(Spanish), - LANG_MAP_ENTRY_CST(Chinese, SimplifiedChinese), - LANG_MAP_ENTRY(Korean), - LANG_MAP_ENTRY(Dutch), - LANG_MAP_ENTRY(Portuguese), - LANG_MAP_ENTRY(Russian), - LANG_MAP_ENTRY_CST(Taiwanese, TraditionalChinese), - LANG_MAP_ENTRY(BritishEnglish), - LANG_MAP_ENTRY(CanadianFrench), - LANG_MAP_ENTRY(LatinAmericanSpanish), - LANG_MAP_ENTRY(SimplifiedChinese), - LANG_MAP_ENTRY(TraditionalChinese), - LANG_MAP_ENTRY_CST(BrazilianPortuguese, Portuguese), - }; - #undef LANG_MAP_ENTRY - #undef LANG_MAP_ENTRY_CST - + /** + * @brief Maps a system language to its corresponding application language + */ constexpr ApplicationLanguage GetApplicationLanguage(SystemLanguage systemLanguage) { - return SystemToAppMap.at(systemLanguage); + #define LANG_ENTRY(lang, code, sysIndex, appIndex, map) ENUM_CASE_PAIR(lang, ApplicationLanguage::lang); + ENUM_SWITCH(SystemLanguage, systemLanguage, LANGUAGES, ApplicationLanguage::AmericanEnglish) + #undef LANG_ENTRY } - #define LANG_MAP_ENTRY_REVERSE(lang) {ApplicationLanguage::lang, SystemLanguage::lang} - constexpr frz::unordered_map AppToSystemMap{ - LANG_MAP_ENTRY_REVERSE(Japanese), - LANG_MAP_ENTRY_REVERSE(AmericanEnglish), - LANG_MAP_ENTRY_REVERSE(French), - LANG_MAP_ENTRY_REVERSE(German), - LANG_MAP_ENTRY_REVERSE(Italian), - LANG_MAP_ENTRY_REVERSE(Spanish), - LANG_MAP_ENTRY_REVERSE(Korean), - LANG_MAP_ENTRY_REVERSE(Dutch), - LANG_MAP_ENTRY_REVERSE(Portuguese), - LANG_MAP_ENTRY_REVERSE(Russian), - LANG_MAP_ENTRY_REVERSE(BritishEnglish), - LANG_MAP_ENTRY_REVERSE(CanadianFrench), - LANG_MAP_ENTRY_REVERSE(LatinAmericanSpanish), - LANG_MAP_ENTRY_REVERSE(SimplifiedChinese), - LANG_MAP_ENTRY_REVERSE(TraditionalChinese), - }; - #undef LANG_MAP_ENTRY_REVERSE - + /** + * @brief Maps an application language to its corresponding system language + */ constexpr SystemLanguage GetSystemLanguage(ApplicationLanguage applicationLanguage) { - return AppToSystemMap.at(applicationLanguage); + #define LANG_ENTRY(lang, code, sysIndex, appIndex, map) map(lang, SystemLanguage::lang); + #define MAP(key, value) ENUM_CASE_PAIR(key, value) + #define DONT_MAP(key, value) + ENUM_SWITCH(ApplicationLanguage, applicationLanguage, LANGUAGES, SystemLanguage::AmericanEnglish) + #undef LANG_ENTRY + #undef MAP + #undef DONT_MAP } + + #undef LANGUAGES } } \ No newline at end of file diff --git a/app/src/main/cpp/skyline/common/macros.h b/app/src/main/cpp/skyline/common/macros.h index 4a6c4dd0..51c55336 100644 --- a/app/src/main/cpp/skyline/common/macros.h +++ b/app/src/main/cpp/skyline/common/macros.h @@ -21,5 +21,24 @@ cases \ default: \ return "Unknown"; \ - }; \ - }; + } \ + } + +/** + * @brief A case statement for an enumerant value to use alongside ENUM_SWITCH + */ +#define ENUM_CASE_PAIR(key, value) \ + case ENUM_TYPE::key: \ + return value + +/** + * @brief Creates a switch case statement to convert an enumerant to the given values + * @example ENUM_SWITCH(Example, value, { ENUM_CASE_PAIR(keyA, valueA); ENUM_CASE_PAIR(keyB, valueB); }, defaultValue) + */ +#define ENUM_SWITCH(name, value, cases, defaultValue) \ + using ENUM_TYPE = name; \ + switch (value) { \ + cases \ + default: \ + return defaultValue; \ + } \ No newline at end of file diff --git a/app/src/main/cpp/skyline/vfs/nacp.h b/app/src/main/cpp/skyline/vfs/nacp.h index 2bc3c9f5..08521f6b 100644 --- a/app/src/main/cpp/skyline/vfs/nacp.h +++ b/app/src/main/cpp/skyline/vfs/nacp.h @@ -35,6 +35,8 @@ namespace skyline::vfs { } nacpContents{}; static_assert(sizeof(NacpData) == 0x4000); + u32 supportedTitleLanguages{0}; // &backing); languages::ApplicationLanguage GetFirstSupportedTitleLanguage(); @@ -44,7 +46,5 @@ namespace skyline::vfs { std::string GetApplicationName(languages::ApplicationLanguage language); std::string GetApplicationPublisher(languages::ApplicationLanguage language); - - u32 supportedTitleLanguages{0}; }; }