From 3fffde306109e73aec4fe8dce1a63260ea705890 Mon Sep 17 00:00:00 2001 From: sspacelynx <37104290+sspacelynx@users.noreply.github.com> Date: Sat, 28 Aug 2021 12:30:34 +0200 Subject: [PATCH] Rework OS to allow passing a language --- app/src/main/cpp/emu_jni.cpp | 23 +++++++- app/src/main/cpp/skyline/common/languages.h | 41 +++++++++++++ app/src/main/cpp/skyline/os.cpp | 16 +++++- app/src/main/cpp/skyline/os.h | 12 +++- .../am/controller/IApplicationFunctions.cpp | 6 +- .../services/settings/ISettingsServer.cpp | 27 ++------- .../services/settings/ISettingsServer.h | 57 ++++++++----------- .../java/emu/skyline/EmulationActivity.kt | 4 +- .../main/java/emu/skyline/utils/Settings.kt | 2 + app/src/main/res/values/array.xml | 40 +++++++++++++ app/src/main/res/values/strings.xml | 1 + app/src/main/res/xml/preferences.xml | 7 +++ 12 files changed, 173 insertions(+), 63 deletions(-) create mode 100644 app/src/main/cpp/skyline/common/languages.h diff --git a/app/src/main/cpp/emu_jni.cpp b/app/src/main/cpp/emu_jni.cpp index 28184e12..11fea9b7 100644 --- a/app/src/main/cpp/emu_jni.cpp +++ b/app/src/main/cpp/emu_jni.cpp @@ -8,6 +8,7 @@ #include #include #include "skyline/common.h" +#include "skyline/common/languages.h" #include "skyline/common/signal.h" #include "skyline/common/settings.h" #include "skyline/common/trace.h" @@ -52,7 +53,16 @@ static std::string GetTimeZoneName() { return "GMT"; } -extern "C" JNIEXPORT void Java_emu_skyline_EmulationActivity_executeApplication(JNIEnv *env, jobject instance, jstring romUriJstring, jint romType, jint romFd, jint preferenceFd, jstring appFilesPathJstring, jobject assetManager) { +extern "C" JNIEXPORT void Java_emu_skyline_EmulationActivity_executeApplication( + JNIEnv *env, jobject instance, + jstring romUriJstring, + jint romType, + jint romFd, + jint preferenceFd, + jint systemLanguage, + jstring appFilesPathJstring, + jobject assetManager +) { skyline::signal::ScopedStackBlocker stackBlocker; // We do not want anything to unwind past JNI code as there are invalid stack frames which can lead to a segmentation fault Fps = AverageFrametimeMs = AverageFrametimeDeviationMs = 0; @@ -74,7 +84,16 @@ extern "C" JNIEXPORT void Java_emu_skyline_EmulationActivity_executeApplication( perfetto::TrackEvent::Register(); try { - auto os{std::make_shared(jvmManager, logger, settings, std::string(appFilesPath), GetTimeZoneName(), std::make_shared(AAssetManager_fromJava(env, assetManager)))}; + auto os{ + std::make_shared( + jvmManager, + logger, + settings, + std::string(appFilesPath), + GetTimeZoneName(), + static_cast(systemLanguage), + std::make_shared(AAssetManager_fromJava(env, assetManager)) + )}; OsWeak = os; GpuWeak = os->state.gpu; InputWeak = os->state.input; diff --git a/app/src/main/cpp/skyline/common/languages.h b/app/src/main/cpp/skyline/common/languages.h new file mode 100644 index 00000000..ce6e40ef --- /dev/null +++ b/app/src/main/cpp/skyline/common/languages.h @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: MPL-2.0 +// Copyright © 2021 Skyline Team and Contributors (https://github.com/skyline-emu/) + +#pragma once + +#include + +namespace skyline { + using LanguageCode = u64; + + namespace constant { + constexpr size_t OldLanguageCodeListSize{15}; //!< The size of the pre 4.0.0 language code list + constexpr size_t NewLanguageCodeListSize{17}; //!< The size of the post 4.0.0 language code list + } + + namespace languages { + 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"), + }; + + constexpr LanguageCode GetLanguageCode(SystemLanguage language) { + return LanguageCodeList.at(static_cast(language)); + } + } +} \ No newline at end of file diff --git a/app/src/main/cpp/skyline/os.cpp b/app/src/main/cpp/skyline/os.cpp index 228f37e5..a270865a 100644 --- a/app/src/main/cpp/skyline/os.cpp +++ b/app/src/main/cpp/skyline/os.cpp @@ -13,7 +13,21 @@ #include "os.h" namespace skyline::kernel { - OS::OS(std::shared_ptr &jvmManager, std::shared_ptr &logger, std::shared_ptr &settings, std::string appFilesPath, std::string deviceTimeZone, std::shared_ptr assetFileSystem) : state(this, jvmManager, settings, logger), appFilesPath(std::move(appFilesPath)), deviceTimeZone(std::move(deviceTimeZone)), assetFileSystem(std::move(assetFileSystem)), serviceManager(state) {} + OS::OS( + std::shared_ptr &jvmManager, + std::shared_ptr &logger, + std::shared_ptr &settings, + std::string appFilesPath, + std::string deviceTimeZone, + languages::SystemLanguage systemLanguage, + std::shared_ptr assetFileSystem + ) + : state(this, jvmManager, settings, logger), + appFilesPath(std::move(appFilesPath)), + deviceTimeZone(std::move(deviceTimeZone)), + assetFileSystem(std::move(assetFileSystem)), + serviceManager(state), + systemLanguage(systemLanguage) {} void OS::Execute(int romFd, loader::RomFormat romType) { auto romFile{std::make_shared(romFd)}; diff --git a/app/src/main/cpp/skyline/os.h b/app/src/main/cpp/skyline/os.h index 1e25cd5d..d989e05f 100644 --- a/app/src/main/cpp/skyline/os.h +++ b/app/src/main/cpp/skyline/os.h @@ -3,6 +3,7 @@ #pragma once +#include #include "vfs/filesystem.h" #include "loader/loader.h" #include "services/serviceman.h" @@ -18,13 +19,22 @@ namespace skyline::kernel { std::string deviceTimeZone; //!< The timezone name (e.g. Europe/London) std::shared_ptr assetFileSystem; //!< A filesystem to be used for accessing emulator assets (like tzdata) service::ServiceManager serviceManager; + languages::SystemLanguage systemLanguage; /** * @param logger An instance of the Logger class * @param settings An instance of the Settings class * @param window The ANativeWindow object to draw the screen to */ - OS(std::shared_ptr &jvmManager, std::shared_ptr &logger, std::shared_ptr &settings, std::string appFilesPath, std::string deviceTimeZone, std::shared_ptr assetFileSystem); + OS( + std::shared_ptr &jvmManager, + std::shared_ptr &logger, + std::shared_ptr &settings, + std::string appFilesPath, + std::string deviceTimeZone, + languages::SystemLanguage systemLanguage, + std::shared_ptr assetFileSystem + ); /** * @brief Execute a particular ROM file diff --git a/app/src/main/cpp/skyline/services/am/controller/IApplicationFunctions.cpp b/app/src/main/cpp/skyline/services/am/controller/IApplicationFunctions.cpp index 5424aa3e..cfb684bb 100644 --- a/app/src/main/cpp/skyline/services/am/controller/IApplicationFunctions.cpp +++ b/app/src/main/cpp/skyline/services/am/controller/IApplicationFunctions.cpp @@ -4,13 +4,15 @@ #include #include #include +#include #include #include #include #include "IApplicationFunctions.h" namespace skyline::service::am { - IApplicationFunctions::IApplicationFunctions(const DeviceState &state, ServiceManager &manager) : gpuErrorEvent(std::make_shared(state, false)), BaseService(state, manager) {} + IApplicationFunctions::IApplicationFunctions(const DeviceState &state, ServiceManager &manager) + : gpuErrorEvent(std::make_shared(state, false)), BaseService(state, manager) {} Result IApplicationFunctions::PopLaunchParameter(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { constexpr u32 LaunchParameterMagic{0xC79497CA}; //!< The magic of the application launch parameters @@ -32,7 +34,7 @@ namespace skyline::service::am { } Result IApplicationFunctions::GetDesiredLanguage(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { - response.Push(util::MakeMagic("en-US")); + response.Push(languages::GetLanguageCode(state.os->systemLanguage)); return {}; } diff --git a/app/src/main/cpp/skyline/services/settings/ISettingsServer.cpp b/app/src/main/cpp/skyline/services/settings/ISettingsServer.cpp index d3940666..d094063a 100644 --- a/app/src/main/cpp/skyline/services/settings/ISettingsServer.cpp +++ b/app/src/main/cpp/skyline/services/settings/ISettingsServer.cpp @@ -1,44 +1,25 @@ // SPDX-License-Identifier: MPL-2.0 // Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/) +#include #include "ISettingsServer.h" namespace skyline::service::settings { ISettingsServer::ISettingsServer(const DeviceState &state, ServiceManager &manager) : BaseService(state, manager) {} - 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"), - }; - Result ISettingsServer::GetAvailableLanguageCodes(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { - request.outputBuf.at(0).copy_from(span(LanguageCodeList).first(constant::OldLanguageCodeListSize)); + request.outputBuf.at(0).copy_from(span(languages::LanguageCodeList).first(constant::OldLanguageCodeListSize)); response.Push(constant::OldLanguageCodeListSize); return {}; } Result ISettingsServer::MakeLanguageCode(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { - response.Push(LanguageCodeList.at(request.Pop())); + response.Push(languages::LanguageCodeList.at(request.Pop())); return {}; } Result ISettingsServer::GetAvailableLanguageCodes2(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { - request.outputBuf.at(0).copy_from(LanguageCodeList); + request.outputBuf.at(0).copy_from(languages::LanguageCodeList); response.Push(constant::NewLanguageCodeListSize); return {}; } diff --git a/app/src/main/cpp/skyline/services/settings/ISettingsServer.h b/app/src/main/cpp/skyline/services/settings/ISettingsServer.h index 57325c41..ad2e42c8 100644 --- a/app/src/main/cpp/skyline/services/settings/ISettingsServer.h +++ b/app/src/main/cpp/skyline/services/settings/ISettingsServer.h @@ -3,43 +3,36 @@ #pragma once -#include +#include -namespace skyline::service { - namespace constant { - constexpr size_t OldLanguageCodeListSize{15}; //!< The size of the pre 4.0.0 language code list - constexpr size_t NewLanguageCodeListSize{17}; //!< The size of the post 4.0.0 language code list - } +namespace skyline::service::settings { + /** + * @brief ISettingsServer or 'set' provides access to user settings + * @url https://switchbrew.org/wiki/Settings_services#set + */ + class ISettingsServer : public BaseService { + public: + ISettingsServer(const DeviceState &state, ServiceManager &manager); - namespace settings { /** - * @brief ISettingsServer or 'set' provides access to user settings - * @url https://switchbrew.org/wiki/Settings_services#set + * @brief Reads the available language codes that an application can use (pre 4.0.0) */ - class ISettingsServer : public BaseService { - public: - ISettingsServer(const DeviceState &state, ServiceManager &manager); + Result GetAvailableLanguageCodes(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); - /** - * @brief Reads the available language codes that an application can use (pre 4.0.0) - */ - Result GetAvailableLanguageCodes(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); + /** + * @brief Converts a language code list index to its corresponding language code + */ + Result MakeLanguageCode(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); - /** - * @brief Converts a language code list index to its corresponding language code - */ - Result MakeLanguageCode(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); + /** + * @brief Reads the available language codes that an application can use (post 4.0.0) + */ + Result GetAvailableLanguageCodes2(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); - /** - * @brief Reads the available language codes that an application can use (post 4.0.0) - */ - Result GetAvailableLanguageCodes2(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); - - SERVICE_DECL( - SFUNC(0x1, ISettingsServer, GetAvailableLanguageCodes), - SFUNC(0x2, ISettingsServer, MakeLanguageCode), - SFUNC(0x5, ISettingsServer, GetAvailableLanguageCodes2) - ) - }; - } + SERVICE_DECL( + SFUNC(0x1, ISettingsServer, GetAvailableLanguageCodes), + SFUNC(0x2, ISettingsServer, MakeLanguageCode), + SFUNC(0x5, ISettingsServer, GetAvailableLanguageCodes2) + ) + }; } diff --git a/app/src/main/java/emu/skyline/EmulationActivity.kt b/app/src/main/java/emu/skyline/EmulationActivity.kt index d472109a..ce131dc8 100644 --- a/app/src/main/java/emu/skyline/EmulationActivity.kt +++ b/app/src/main/java/emu/skyline/EmulationActivity.kt @@ -70,7 +70,7 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback, View.OnTo * @param appFilesPath The full path to the app files directory * @param assetManager The asset manager used for accessing app assets */ - private external fun executeApplication(romUri : String, romType : Int, romFd : Int, preferenceFd : Int, appFilesPath : String, assetManager : AssetManager) + private external fun executeApplication(romUri : String, romType : Int, romFd : Int, preferenceFd : Int, language : Int, appFilesPath : String, assetManager : AssetManager) /** * @return If it successfully caused the [emulationThread] to gracefully stop @@ -173,7 +173,7 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback, View.OnTo val preferenceFd = ParcelFileDescriptor.open(File("${applicationInfo.dataDir}/shared_prefs/${applicationInfo.packageName}_preferences.xml"), ParcelFileDescriptor.MODE_READ_WRITE) emulationThread = Thread { - executeApplication(rom.toString(), romType, romFd.detachFd(), preferenceFd.detachFd(), applicationContext.filesDir.canonicalPath + "/", assets) + executeApplication(rom.toString(), romType, romFd.detachFd(), preferenceFd.detachFd(), Integer.parseInt(settings.systemLanguage), applicationContext.filesDir.canonicalPath + "/", assets) if (shouldFinish) runOnUiThread { emulationThread.join() diff --git a/app/src/main/java/emu/skyline/utils/Settings.kt b/app/src/main/java/emu/skyline/utils/Settings.kt index 1be797dd..7ddba2bc 100644 --- a/app/src/main/java/emu/skyline/utils/Settings.kt +++ b/app/src/main/java/emu/skyline/utils/Settings.kt @@ -37,4 +37,6 @@ class Settings @Inject constructor(@ApplicationContext private val context : Con var filter by sharedPreferences(context, 0) var maxRefreshRate by sharedPreferences(context, false) + + var systemLanguage by sharedPreferences(context, "1") } diff --git a/app/src/main/res/values/array.xml b/app/src/main/res/values/array.xml index 3a43fcd7..3a52726d 100644 --- a/app/src/main/res/values/array.xml +++ b/app/src/main/res/values/array.xml @@ -34,4 +34,44 @@ 1 2 + + Japanese (日本語) + English + French (français) + German (Deutsch) + Italian (italiano) + Spanish (español) + Chinese + Korean (한국어) + Dutch (Nederlands) + Portuguese (português) + Russian (Русский) + Taiwanese + British English + Canadian English + Latin American Spanish + Simplified Chinese + Traditional Chinese (正體中文) + Brazilian Portuguese (português do Brasil) + + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index fdd0de05..2a1ff37c 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -43,6 +43,7 @@ The system will emulate being in docked mode Username @string/app_name + System language Keys Production Keys diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index 86d6f35c..93fecb4d 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -72,6 +72,13 @@ app:key="username_value" app:limit="31" app:title="@string/username" /> +