diff options
Diffstat (limited to 'src')
32 files changed, 1373 insertions, 636 deletions
diff --git a/src/audio_core/stream.cpp b/src/audio_core/stream.cpp index 22a3f8c84..11481a776 100644 --- a/src/audio_core/stream.cpp +++ b/src/audio_core/stream.cpp @@ -57,7 +57,9 @@ Stream::State Stream::GetState() const {  s64 Stream::GetBufferReleaseCycles(const Buffer& buffer) const {      const std::size_t num_samples{buffer.GetSamples().size() / GetNumChannels()}; -    return Core::Timing::usToCycles((static_cast<u64>(num_samples) * 1000000) / sample_rate); +    const auto us = +        std::chrono::microseconds((static_cast<u64>(num_samples) * 1000000) / sample_rate); +    return Core::Timing::usToCycles(us);  }  static void VolumeAdjustSamples(std::vector<s16>& samples) { diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index a56e526a6..6bf512e12 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -328,6 +328,9 @@ add_library(core STATIC      hle/service/nim/nim.h      hle/service/npns/npns.cpp      hle/service/npns/npns.h +    hle/service/ns/errors.h +    hle/service/ns/language.cpp +    hle/service/ns/language.h      hle/service/ns/ns.cpp      hle/service/ns/ns.h      hle/service/ns/pl_u.cpp diff --git a/src/core/core.cpp b/src/core/core.cpp index 7106151bd..ff0721079 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -18,11 +18,6 @@  #include "core/file_sys/registered_cache.h"  #include "core/file_sys/vfs_concat.h"  #include "core/file_sys/vfs_real.h" -#include "core/frontend/applets/error.h" -#include "core/frontend/applets/general_frontend.h" -#include "core/frontend/applets/profile_select.h" -#include "core/frontend/applets/software_keyboard.h" -#include "core/frontend/applets/web_browser.h"  #include "core/gdbstub/gdbstub.h"  #include "core/hle/kernel/client_port.h"  #include "core/hle/kernel/kernel.h" @@ -37,9 +32,6 @@  #include "core/settings.h"  #include "core/telemetry_session.h"  #include "file_sys/cheat_engine.h" -#include "frontend/applets/profile_select.h" -#include "frontend/applets/software_keyboard.h" -#include "frontend/applets/web_browser.h"  #include "video_core/debug_utils/debug_utils.h"  #include "video_core/renderer_base.h"  #include "video_core/video_core.h" @@ -144,20 +136,10 @@ struct System::Impl {      ResultStatus Load(System& system, Frontend::EmuWindow& emu_window,                        const std::string& filepath) {          app_loader = Loader::GetLoader(GetGameFileFromPath(virtual_filesystem, filepath)); -          if (!app_loader) {              LOG_CRITICAL(Core, "Failed to obtain loader for {}!", filepath);              return ResultStatus::ErrorGetLoader;          } -        std::pair<std::optional<u32>, Loader::ResultStatus> system_mode = -            app_loader->LoadKernelSystemMode(); - -        if (system_mode.second != Loader::ResultStatus::Success) { -            LOG_CRITICAL(Core, "Failed to determine system mode (Error {})!", -                         static_cast<int>(system_mode.second)); - -            return ResultStatus::ErrorSystemMode; -        }          ResultStatus init_result{Init(system, emu_window)};          if (init_result != ResultStatus::Success) { @@ -167,6 +149,7 @@ struct System::Impl {              return init_result;          } +        telemetry_session->AddInitialInfo(*app_loader);          auto main_process = Kernel::Process::Create(system, "main");          const auto [load_result, load_parameters] = app_loader->Load(*main_process);          if (load_result != Loader::ResultStatus::Success) { diff --git a/src/core/core.h b/src/core/core.h index a9a756a4c..20959de54 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -98,7 +98,6 @@ public:          Success,             ///< Succeeded          ErrorNotInitialized, ///< Error trying to use core prior to initialization          ErrorGetLoader,      ///< Error finding the correct application loader -        ErrorSystemMode,     ///< Error determining the system mode          ErrorSystemFiles,    ///< Error in finding system files          ErrorSharedFont,     ///< Error in finding shared font          ErrorVideoCore,      ///< Error in the video core diff --git a/src/core/core_timing_util.cpp b/src/core/core_timing_util.cpp index c0f08cddb..a10472a95 100644 --- a/src/core/core_timing_util.cpp +++ b/src/core/core_timing_util.cpp @@ -13,52 +13,40 @@ namespace Core::Timing {  constexpr u64 MAX_VALUE_TO_MULTIPLY = std::numeric_limits<s64>::max() / BASE_CLOCK_RATE; -s64 usToCycles(s64 us) { -    if (static_cast<u64>(us / 1000000) > MAX_VALUE_TO_MULTIPLY) { +s64 msToCycles(std::chrono::milliseconds ms) { +    if (static_cast<u64>(ms.count() / 1000) > MAX_VALUE_TO_MULTIPLY) {          LOG_ERROR(Core_Timing, "Integer overflow, use max value");          return std::numeric_limits<s64>::max();      } -    if (static_cast<u64>(us) > MAX_VALUE_TO_MULTIPLY) { +    if (static_cast<u64>(ms.count()) > MAX_VALUE_TO_MULTIPLY) {          LOG_DEBUG(Core_Timing, "Time very big, do rounding"); -        return BASE_CLOCK_RATE * (us / 1000000); +        return BASE_CLOCK_RATE * (ms.count() / 1000);      } -    return (BASE_CLOCK_RATE * us) / 1000000; +    return (BASE_CLOCK_RATE * ms.count()) / 1000;  } -s64 usToCycles(u64 us) { -    if (us / 1000000 > MAX_VALUE_TO_MULTIPLY) { +s64 usToCycles(std::chrono::microseconds us) { +    if (static_cast<u64>(us.count() / 1000000) > MAX_VALUE_TO_MULTIPLY) {          LOG_ERROR(Core_Timing, "Integer overflow, use max value");          return std::numeric_limits<s64>::max();      } -    if (us > MAX_VALUE_TO_MULTIPLY) { +    if (static_cast<u64>(us.count()) > MAX_VALUE_TO_MULTIPLY) {          LOG_DEBUG(Core_Timing, "Time very big, do rounding"); -        return BASE_CLOCK_RATE * static_cast<s64>(us / 1000000); +        return BASE_CLOCK_RATE * (us.count() / 1000000);      } -    return (BASE_CLOCK_RATE * static_cast<s64>(us)) / 1000000; +    return (BASE_CLOCK_RATE * us.count()) / 1000000;  } -s64 nsToCycles(s64 ns) { -    if (static_cast<u64>(ns / 1000000000) > MAX_VALUE_TO_MULTIPLY) { +s64 nsToCycles(std::chrono::nanoseconds ns) { +    if (static_cast<u64>(ns.count() / 1000000000) > MAX_VALUE_TO_MULTIPLY) {          LOG_ERROR(Core_Timing, "Integer overflow, use max value");          return std::numeric_limits<s64>::max();      } -    if (static_cast<u64>(ns) > MAX_VALUE_TO_MULTIPLY) { +    if (static_cast<u64>(ns.count()) > MAX_VALUE_TO_MULTIPLY) {          LOG_DEBUG(Core_Timing, "Time very big, do rounding"); -        return BASE_CLOCK_RATE * (ns / 1000000000); +        return BASE_CLOCK_RATE * (ns.count() / 1000000000);      } -    return (BASE_CLOCK_RATE * ns) / 1000000000; -} - -s64 nsToCycles(u64 ns) { -    if (ns / 1000000000 > MAX_VALUE_TO_MULTIPLY) { -        LOG_ERROR(Core_Timing, "Integer overflow, use max value"); -        return std::numeric_limits<s64>::max(); -    } -    if (ns > MAX_VALUE_TO_MULTIPLY) { -        LOG_DEBUG(Core_Timing, "Time very big, do rounding"); -        return BASE_CLOCK_RATE * (static_cast<s64>(ns) / 1000000000); -    } -    return (BASE_CLOCK_RATE * static_cast<s64>(ns)) / 1000000000; +    return (BASE_CLOCK_RATE * ns.count()) / 1000000000;  }  u64 CpuCyclesToClockCycles(u64 ticks) { diff --git a/src/core/core_timing_util.h b/src/core/core_timing_util.h index 679aa3123..cdd84d70f 100644 --- a/src/core/core_timing_util.h +++ b/src/core/core_timing_util.h @@ -4,6 +4,7 @@  #pragma once +#include <chrono>  #include "common/common_types.h"  namespace Core::Timing { @@ -13,53 +14,20 @@ namespace Core::Timing {  constexpr u64 BASE_CLOCK_RATE = 1019215872; // Switch clock speed is 1020MHz un/docked  constexpr u64 CNTFREQ = 19200000;           // Value from fusee. -inline s64 msToCycles(int ms) { -    // since ms is int there is no way to overflow -    return BASE_CLOCK_RATE * static_cast<s64>(ms) / 1000; -} - -inline s64 msToCycles(float ms) { -    return static_cast<s64>(BASE_CLOCK_RATE * (0.001f) * ms); -} - -inline s64 msToCycles(double ms) { -    return static_cast<s64>(BASE_CLOCK_RATE * (0.001) * ms); -} - -inline s64 usToCycles(float us) { -    return static_cast<s64>(BASE_CLOCK_RATE * (0.000001f) * us); -} - -inline s64 usToCycles(int us) { -    return (BASE_CLOCK_RATE * static_cast<s64>(us) / 1000000); -} - -s64 usToCycles(s64 us); - -s64 usToCycles(u64 us); - -inline s64 nsToCycles(float ns) { -    return static_cast<s64>(BASE_CLOCK_RATE * (0.000000001f) * ns); -} - -inline s64 nsToCycles(int ns) { -    return BASE_CLOCK_RATE * static_cast<s64>(ns) / 1000000000; -} - -s64 nsToCycles(s64 ns); - -s64 nsToCycles(u64 ns); +s64 msToCycles(std::chrono::milliseconds ms); +s64 usToCycles(std::chrono::microseconds us); +s64 nsToCycles(std::chrono::nanoseconds ns); -inline u64 cyclesToNs(s64 cycles) { -    return cycles * 1000000000 / BASE_CLOCK_RATE; +inline std::chrono::milliseconds CyclesToMs(s64 cycles) { +    return std::chrono::milliseconds(cycles * 1000 / BASE_CLOCK_RATE);  } -inline s64 cyclesToUs(s64 cycles) { -    return cycles * 1000000 / BASE_CLOCK_RATE; +inline std::chrono::nanoseconds CyclesToNs(s64 cycles) { +    return std::chrono::nanoseconds(cycles * 1000000000 / BASE_CLOCK_RATE);  } -inline u64 cyclesToMs(s64 cycles) { -    return cycles * 1000 / BASE_CLOCK_RATE; +inline std::chrono::microseconds CyclesToUs(s64 cycles) { +    return std::chrono::microseconds(cycles * 1000000 / BASE_CLOCK_RATE);  }  u64 CpuCyclesToClockCycles(u64 ticks); diff --git a/src/core/file_sys/control_metadata.cpp b/src/core/file_sys/control_metadata.cpp index 60ea9ad12..04da30825 100644 --- a/src/core/file_sys/control_metadata.cpp +++ b/src/core/file_sys/control_metadata.cpp @@ -87,6 +87,10 @@ u64 NACP::GetDefaultJournalSaveSize() const {      return raw.user_account_save_data_journal_size;  } +u32 NACP::GetSupportedLanguages() const { +    return raw.supported_languages; +} +  std::vector<u8> NACP::GetRawBytes() const {      std::vector<u8> out(sizeof(RawNACP));      std::memcpy(out.data(), &raw, sizeof(RawNACP)); diff --git a/src/core/file_sys/control_metadata.h b/src/core/file_sys/control_metadata.h index 280710ddf..1be34ed55 100644 --- a/src/core/file_sys/control_metadata.h +++ b/src/core/file_sys/control_metadata.h @@ -109,6 +109,7 @@ public:      std::string GetVersionString() const;      u64 GetDefaultNormalSaveSize() const;      u64 GetDefaultJournalSaveSize() const; +    u32 GetSupportedLanguages() const;      std::vector<u8> GetRawBytes() const;  private: diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 2abf9efca..c73a40977 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -75,9 +75,9 @@ void Thread::WakeAfterDelay(s64 nanoseconds) {      // This function might be called from any thread so we have to be cautious and use the      // thread-safe version of ScheduleEvent. +    const s64 cycles = Core::Timing::nsToCycles(std::chrono::nanoseconds{nanoseconds});      Core::System::GetInstance().CoreTiming().ScheduleEventThreadsafe( -        Core::Timing::nsToCycles(nanoseconds), kernel.ThreadWakeupCallbackEventType(), -        callback_handle); +        cycles, kernel.ThreadWakeupCallbackEventType(), callback_handle);  }  void Thread::CancelWakeupTimer() { diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index 1a32a109f..3f201c821 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -8,6 +8,8 @@  #include <cstring>  #include "audio_core/audio_renderer.h"  #include "core/core.h" +#include "core/file_sys/control_metadata.h" +#include "core/file_sys/patch_manager.h"  #include "core/file_sys/savedata_factory.h"  #include "core/hle/ipc_helpers.h"  #include "core/hle/kernel/kernel.h" @@ -29,9 +31,11 @@  #include "core/hle/service/am/tcap.h"  #include "core/hle/service/apm/apm.h"  #include "core/hle/service/filesystem/filesystem.h" +#include "core/hle/service/ns/ns.h"  #include "core/hle/service/nvflinger/nvflinger.h"  #include "core/hle/service/pm/pm.h"  #include "core/hle/service/set/set.h" +#include "core/hle/service/sm/sm.h"  #include "core/hle/service/vi/vi.h"  #include "core/settings.h" @@ -1100,10 +1104,42 @@ void IApplicationFunctions::GetDesiredLanguage(Kernel::HLERequestContext& ctx) {      // TODO(bunnei): This should be configurable      LOG_DEBUG(Service_AM, "called"); +    // Get supported languages from NACP, if possible +    // Default to 0 (all languages supported) +    u32 supported_languages = 0; +    FileSys::PatchManager pm{Core::System::GetInstance().CurrentProcess()->GetTitleID()}; + +    const auto res = pm.GetControlMetadata(); +    if (res.first != nullptr) { +        supported_languages = res.first->GetSupportedLanguages(); +    } + +    // Call IApplicationManagerInterface implementation. +    auto& service_manager = Core::System::GetInstance().ServiceManager(); +    auto ns_am2 = service_manager.GetService<Service::NS::NS>("ns:am2"); +    auto app_man = ns_am2->GetApplicationManagerInterface(); + +    // Get desired application language +    const auto res_lang = app_man->GetApplicationDesiredLanguage(supported_languages); +    if (res_lang.Failed()) { +        IPC::ResponseBuilder rb{ctx, 2}; +        rb.Push(res_lang.Code()); +        return; +    } + +    // Convert to settings language code. +    const auto res_code = app_man->ConvertApplicationLanguageToLanguageCode(*res_lang); +    if (res_code.Failed()) { +        IPC::ResponseBuilder rb{ctx, 2}; +        rb.Push(res_code.Code()); +        return; +    } + +    LOG_DEBUG(Service_AM, "got desired_language={:016X}", *res_code); +      IPC::ResponseBuilder rb{ctx, 4};      rb.Push(RESULT_SUCCESS); -    rb.Push( -        static_cast<u64>(Service::Set::GetLanguageCodeFromIndex(Settings::values.language_index))); +    rb.Push(*res_code);  }  void IApplicationFunctions::InitializeGamePlayRecording(Kernel::HLERequestContext& ctx) { diff --git a/src/core/hle/service/am/applets/applets.cpp b/src/core/hle/service/am/applets/applets.cpp index e812c66e9..14fa92318 100644 --- a/src/core/hle/service/am/applets/applets.cpp +++ b/src/core/hle/service/am/applets/applets.cpp @@ -121,6 +121,21 @@ void Applet::Initialize() {      initialized = true;  } +AppletFrontendSet::AppletFrontendSet() = default; + +AppletFrontendSet::AppletFrontendSet(ErrorApplet error, PhotoViewer photo_viewer, +                                     ProfileSelect profile_select, +                                     SoftwareKeyboard software_keyboard, WebBrowser web_browser) +    : error{std::move(error)}, photo_viewer{std::move(photo_viewer)}, profile_select{std::move( +                                                                          profile_select)}, +      software_keyboard{std::move(software_keyboard)}, web_browser{std::move(web_browser)} {} + +AppletFrontendSet::~AppletFrontendSet() = default; + +AppletFrontendSet::AppletFrontendSet(AppletFrontendSet&&) noexcept = default; + +AppletFrontendSet& AppletFrontendSet::operator=(AppletFrontendSet&&) noexcept = default; +  AppletManager::AppletManager() = default;  AppletManager::~AppletManager() = default; diff --git a/src/core/hle/service/am/applets/applets.h b/src/core/hle/service/am/applets/applets.h index 7f932672c..b46e10a4a 100644 --- a/src/core/hle/service/am/applets/applets.h +++ b/src/core/hle/service/am/applets/applets.h @@ -137,11 +137,28 @@ protected:  };  struct AppletFrontendSet { -    std::unique_ptr<Core::Frontend::ErrorApplet> error; -    std::unique_ptr<Core::Frontend::PhotoViewerApplet> photo_viewer; -    std::unique_ptr<Core::Frontend::ProfileSelectApplet> profile_select; -    std::unique_ptr<Core::Frontend::SoftwareKeyboardApplet> software_keyboard; -    std::unique_ptr<Core::Frontend::WebBrowserApplet> web_browser; +    using ErrorApplet = std::unique_ptr<Core::Frontend::ErrorApplet>; +    using PhotoViewer = std::unique_ptr<Core::Frontend::PhotoViewerApplet>; +    using ProfileSelect = std::unique_ptr<Core::Frontend::ProfileSelectApplet>; +    using SoftwareKeyboard = std::unique_ptr<Core::Frontend::SoftwareKeyboardApplet>; +    using WebBrowser = std::unique_ptr<Core::Frontend::WebBrowserApplet>; + +    AppletFrontendSet(); +    AppletFrontendSet(ErrorApplet error, PhotoViewer photo_viewer, ProfileSelect profile_select, +                      SoftwareKeyboard software_keyboard, WebBrowser web_browser); +    ~AppletFrontendSet(); + +    AppletFrontendSet(const AppletFrontendSet&) = delete; +    AppletFrontendSet& operator=(const AppletFrontendSet&) = delete; + +    AppletFrontendSet(AppletFrontendSet&&) noexcept; +    AppletFrontendSet& operator=(AppletFrontendSet&&) noexcept; + +    ErrorApplet error; +    PhotoViewer photo_viewer; +    ProfileSelect profile_select; +    SoftwareKeyboard software_keyboard; +    WebBrowser web_browser;  };  class AppletManager { diff --git a/src/core/hle/service/ns/errors.h b/src/core/hle/service/ns/errors.h new file mode 100644 index 000000000..f4aea8a65 --- /dev/null +++ b/src/core/hle/service/ns/errors.h @@ -0,0 +1,12 @@ +// Copyright 2019 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include "core/hle/result.h" + +namespace Service::NS { + +constexpr ResultCode ERR_APPLICATION_LANGUAGE_NOT_FOUND{ErrorModule::NS, 300}; +}
\ No newline at end of file diff --git a/src/core/hle/service/ns/language.cpp b/src/core/hle/service/ns/language.cpp new file mode 100644 index 000000000..29c4a820c --- /dev/null +++ b/src/core/hle/service/ns/language.cpp @@ -0,0 +1,392 @@ +// Copyright 2019 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "core/hle/service/ns/language.h" +#include "core/hle/service/set/set.h" + +namespace Service::NS { + +constexpr ApplicationLanguagePriorityList priority_list_american_english = {{ +    ApplicationLanguage::AmericanEnglish, +    ApplicationLanguage::BritishEnglish, +    ApplicationLanguage::LatinAmericanSpanish, +    ApplicationLanguage::CanadianFrench, +    ApplicationLanguage::French, +    ApplicationLanguage::German, +    ApplicationLanguage::Spanish, +    ApplicationLanguage::Italian, +    ApplicationLanguage::Dutch, +    ApplicationLanguage::Portuguese, +    ApplicationLanguage::Russian, +    ApplicationLanguage::Japanese, +    ApplicationLanguage::SimplifiedChinese, +    ApplicationLanguage::TraditionalChinese, +    ApplicationLanguage::Korean, +}}; + +constexpr ApplicationLanguagePriorityList priority_list_british_english = {{ +    ApplicationLanguage::BritishEnglish, +    ApplicationLanguage::AmericanEnglish, +    ApplicationLanguage::French, +    ApplicationLanguage::German, +    ApplicationLanguage::Spanish, +    ApplicationLanguage::Italian, +    ApplicationLanguage::Dutch, +    ApplicationLanguage::Portuguese, +    ApplicationLanguage::Russian, +    ApplicationLanguage::LatinAmericanSpanish, +    ApplicationLanguage::CanadianFrench, +    ApplicationLanguage::Japanese, +    ApplicationLanguage::SimplifiedChinese, +    ApplicationLanguage::TraditionalChinese, +    ApplicationLanguage::Korean, +}}; + +constexpr ApplicationLanguagePriorityList priority_list_japanese = {{ +    ApplicationLanguage::Japanese, +    ApplicationLanguage::AmericanEnglish, +    ApplicationLanguage::BritishEnglish, +    ApplicationLanguage::LatinAmericanSpanish, +    ApplicationLanguage::CanadianFrench, +    ApplicationLanguage::French, +    ApplicationLanguage::German, +    ApplicationLanguage::Spanish, +    ApplicationLanguage::Italian, +    ApplicationLanguage::Dutch, +    ApplicationLanguage::Portuguese, +    ApplicationLanguage::Russian, +    ApplicationLanguage::SimplifiedChinese, +    ApplicationLanguage::TraditionalChinese, +    ApplicationLanguage::Korean, +}}; + +constexpr ApplicationLanguagePriorityList priority_list_french = {{ +    ApplicationLanguage::French, +    ApplicationLanguage::CanadianFrench, +    ApplicationLanguage::BritishEnglish, +    ApplicationLanguage::AmericanEnglish, +    ApplicationLanguage::German, +    ApplicationLanguage::Spanish, +    ApplicationLanguage::Italian, +    ApplicationLanguage::Dutch, +    ApplicationLanguage::Portuguese, +    ApplicationLanguage::Russian, +    ApplicationLanguage::LatinAmericanSpanish, +    ApplicationLanguage::Japanese, +    ApplicationLanguage::SimplifiedChinese, +    ApplicationLanguage::TraditionalChinese, +    ApplicationLanguage::Korean, +}}; + +constexpr ApplicationLanguagePriorityList priority_list_german = {{ +    ApplicationLanguage::German, +    ApplicationLanguage::BritishEnglish, +    ApplicationLanguage::AmericanEnglish, +    ApplicationLanguage::French, +    ApplicationLanguage::Spanish, +    ApplicationLanguage::Italian, +    ApplicationLanguage::Dutch, +    ApplicationLanguage::Portuguese, +    ApplicationLanguage::Russian, +    ApplicationLanguage::LatinAmericanSpanish, +    ApplicationLanguage::CanadianFrench, +    ApplicationLanguage::Japanese, +    ApplicationLanguage::SimplifiedChinese, +    ApplicationLanguage::TraditionalChinese, +    ApplicationLanguage::Korean, +}}; + +constexpr ApplicationLanguagePriorityList priority_list_latin_american_spanish = {{ +    ApplicationLanguage::LatinAmericanSpanish, +    ApplicationLanguage::Spanish, +    ApplicationLanguage::AmericanEnglish, +    ApplicationLanguage::BritishEnglish, +    ApplicationLanguage::Portuguese, +    ApplicationLanguage::CanadianFrench, +    ApplicationLanguage::French, +    ApplicationLanguage::Italian, +    ApplicationLanguage::German, +    ApplicationLanguage::Dutch, +    ApplicationLanguage::Russian, +    ApplicationLanguage::Japanese, +    ApplicationLanguage::SimplifiedChinese, +    ApplicationLanguage::TraditionalChinese, +    ApplicationLanguage::Korean, +}}; + +constexpr ApplicationLanguagePriorityList priority_list_spanish = {{ +    ApplicationLanguage::Spanish, +    ApplicationLanguage::LatinAmericanSpanish, +    ApplicationLanguage::BritishEnglish, +    ApplicationLanguage::AmericanEnglish, +    ApplicationLanguage::French, +    ApplicationLanguage::German, +    ApplicationLanguage::Italian, +    ApplicationLanguage::Dutch, +    ApplicationLanguage::Portuguese, +    ApplicationLanguage::Russian, +    ApplicationLanguage::CanadianFrench, +    ApplicationLanguage::Japanese, +    ApplicationLanguage::SimplifiedChinese, +    ApplicationLanguage::TraditionalChinese, +    ApplicationLanguage::Korean, +}}; + +constexpr ApplicationLanguagePriorityList priority_list_italian = {{ +    ApplicationLanguage::Italian, +    ApplicationLanguage::BritishEnglish, +    ApplicationLanguage::AmericanEnglish, +    ApplicationLanguage::French, +    ApplicationLanguage::German, +    ApplicationLanguage::Spanish, +    ApplicationLanguage::Dutch, +    ApplicationLanguage::Portuguese, +    ApplicationLanguage::Russian, +    ApplicationLanguage::LatinAmericanSpanish, +    ApplicationLanguage::CanadianFrench, +    ApplicationLanguage::Japanese, +    ApplicationLanguage::SimplifiedChinese, +    ApplicationLanguage::TraditionalChinese, +    ApplicationLanguage::Korean, +}}; + +constexpr ApplicationLanguagePriorityList priority_list_dutch = {{ +    ApplicationLanguage::Dutch, +    ApplicationLanguage::BritishEnglish, +    ApplicationLanguage::AmericanEnglish, +    ApplicationLanguage::French, +    ApplicationLanguage::German, +    ApplicationLanguage::Spanish, +    ApplicationLanguage::Italian, +    ApplicationLanguage::Portuguese, +    ApplicationLanguage::Russian, +    ApplicationLanguage::LatinAmericanSpanish, +    ApplicationLanguage::CanadianFrench, +    ApplicationLanguage::Japanese, +    ApplicationLanguage::SimplifiedChinese, +    ApplicationLanguage::TraditionalChinese, +    ApplicationLanguage::Korean, +}}; + +constexpr ApplicationLanguagePriorityList priority_list_canadian_french = {{ +    ApplicationLanguage::CanadianFrench, +    ApplicationLanguage::French, +    ApplicationLanguage::AmericanEnglish, +    ApplicationLanguage::BritishEnglish, +    ApplicationLanguage::LatinAmericanSpanish, +    ApplicationLanguage::Spanish, +    ApplicationLanguage::German, +    ApplicationLanguage::Italian, +    ApplicationLanguage::Dutch, +    ApplicationLanguage::Portuguese, +    ApplicationLanguage::Russian, +    ApplicationLanguage::Japanese, +    ApplicationLanguage::SimplifiedChinese, +    ApplicationLanguage::TraditionalChinese, +    ApplicationLanguage::Korean, +}}; + +constexpr ApplicationLanguagePriorityList priority_list_portuguese = {{ +    ApplicationLanguage::Portuguese, +    ApplicationLanguage::BritishEnglish, +    ApplicationLanguage::AmericanEnglish, +    ApplicationLanguage::French, +    ApplicationLanguage::German, +    ApplicationLanguage::Spanish, +    ApplicationLanguage::Italian, +    ApplicationLanguage::Dutch, +    ApplicationLanguage::Russian, +    ApplicationLanguage::LatinAmericanSpanish, +    ApplicationLanguage::CanadianFrench, +    ApplicationLanguage::Japanese, +    ApplicationLanguage::SimplifiedChinese, +    ApplicationLanguage::TraditionalChinese, +    ApplicationLanguage::Korean, +}}; + +constexpr ApplicationLanguagePriorityList priority_list_russian = {{ +    ApplicationLanguage::Russian, +    ApplicationLanguage::BritishEnglish, +    ApplicationLanguage::AmericanEnglish, +    ApplicationLanguage::French, +    ApplicationLanguage::German, +    ApplicationLanguage::Spanish, +    ApplicationLanguage::Italian, +    ApplicationLanguage::Dutch, +    ApplicationLanguage::Portuguese, +    ApplicationLanguage::LatinAmericanSpanish, +    ApplicationLanguage::CanadianFrench, +    ApplicationLanguage::Japanese, +    ApplicationLanguage::SimplifiedChinese, +    ApplicationLanguage::TraditionalChinese, +    ApplicationLanguage::Korean, +}}; + +constexpr ApplicationLanguagePriorityList priority_list_korean = {{ +    ApplicationLanguage::Korean, +    ApplicationLanguage::AmericanEnglish, +    ApplicationLanguage::BritishEnglish, +    ApplicationLanguage::LatinAmericanSpanish, +    ApplicationLanguage::CanadianFrench, +    ApplicationLanguage::French, +    ApplicationLanguage::German, +    ApplicationLanguage::Spanish, +    ApplicationLanguage::Italian, +    ApplicationLanguage::Dutch, +    ApplicationLanguage::Portuguese, +    ApplicationLanguage::Russian, +    ApplicationLanguage::Japanese, +    ApplicationLanguage::SimplifiedChinese, +    ApplicationLanguage::TraditionalChinese, +}}; + +constexpr ApplicationLanguagePriorityList priority_list_traditional_chinese = {{ +    ApplicationLanguage::TraditionalChinese, +    ApplicationLanguage::SimplifiedChinese, +    ApplicationLanguage::AmericanEnglish, +    ApplicationLanguage::BritishEnglish, +    ApplicationLanguage::Japanese, +    ApplicationLanguage::LatinAmericanSpanish, +    ApplicationLanguage::CanadianFrench, +    ApplicationLanguage::French, +    ApplicationLanguage::German, +    ApplicationLanguage::Spanish, +    ApplicationLanguage::Italian, +    ApplicationLanguage::Dutch, +    ApplicationLanguage::Portuguese, +    ApplicationLanguage::Russian, +    ApplicationLanguage::Korean, +}}; + +constexpr ApplicationLanguagePriorityList priority_list_simplified_chinese = {{ +    ApplicationLanguage::SimplifiedChinese, +    ApplicationLanguage::TraditionalChinese, +    ApplicationLanguage::AmericanEnglish, +    ApplicationLanguage::BritishEnglish, +    ApplicationLanguage::Japanese, +    ApplicationLanguage::LatinAmericanSpanish, +    ApplicationLanguage::CanadianFrench, +    ApplicationLanguage::French, +    ApplicationLanguage::German, +    ApplicationLanguage::Spanish, +    ApplicationLanguage::Italian, +    ApplicationLanguage::Dutch, +    ApplicationLanguage::Portuguese, +    ApplicationLanguage::Russian, +    ApplicationLanguage::Korean, +}}; + +const ApplicationLanguagePriorityList* GetApplicationLanguagePriorityList( +    const ApplicationLanguage lang) { +    switch (lang) { +    case ApplicationLanguage::AmericanEnglish: +        return &priority_list_american_english; +    case ApplicationLanguage::BritishEnglish: +        return &priority_list_british_english; +    case ApplicationLanguage::Japanese: +        return &priority_list_japanese; +    case ApplicationLanguage::French: +        return &priority_list_french; +    case ApplicationLanguage::German: +        return &priority_list_german; +    case ApplicationLanguage::LatinAmericanSpanish: +        return &priority_list_latin_american_spanish; +    case ApplicationLanguage::Spanish: +        return &priority_list_spanish; +    case ApplicationLanguage::Italian: +        return &priority_list_italian; +    case ApplicationLanguage::Dutch: +        return &priority_list_dutch; +    case ApplicationLanguage::CanadianFrench: +        return &priority_list_canadian_french; +    case ApplicationLanguage::Portuguese: +        return &priority_list_portuguese; +    case ApplicationLanguage::Russian: +        return &priority_list_russian; +    case ApplicationLanguage::Korean: +        return &priority_list_korean; +    case ApplicationLanguage::TraditionalChinese: +        return &priority_list_traditional_chinese; +    case ApplicationLanguage::SimplifiedChinese: +        return &priority_list_simplified_chinese; +    default: +        return nullptr; +    } +} + +std::optional<ApplicationLanguage> ConvertToApplicationLanguage( +    const Set::LanguageCode language_code) { +    switch (language_code) { +    case Set::LanguageCode::EN_US: +        return ApplicationLanguage::AmericanEnglish; +    case Set::LanguageCode::EN_GB: +        return ApplicationLanguage::BritishEnglish; +    case Set::LanguageCode::JA: +        return ApplicationLanguage::Japanese; +    case Set::LanguageCode::FR: +        return ApplicationLanguage::French; +    case Set::LanguageCode::DE: +        return ApplicationLanguage::German; +    case Set::LanguageCode::ES_419: +        return ApplicationLanguage::LatinAmericanSpanish; +    case Set::LanguageCode::ES: +        return ApplicationLanguage::Spanish; +    case Set::LanguageCode::IT: +        return ApplicationLanguage::Italian; +    case Set::LanguageCode::NL: +        return ApplicationLanguage::Dutch; +    case Set::LanguageCode::FR_CA: +        return ApplicationLanguage::CanadianFrench; +    case Set::LanguageCode::PT: +        return ApplicationLanguage::Portuguese; +    case Set::LanguageCode::RU: +        return ApplicationLanguage::Russian; +    case Set::LanguageCode::KO: +        return ApplicationLanguage::Korean; +    case Set::LanguageCode::ZH_HANT: +        return ApplicationLanguage::TraditionalChinese; +    case Set::LanguageCode::ZH_HANS: +        return ApplicationLanguage::SimplifiedChinese; +    default: +        return std::nullopt; +    } +} + +std::optional<Set::LanguageCode> ConvertToLanguageCode(const ApplicationLanguage lang) { +    switch (lang) { +    case ApplicationLanguage::AmericanEnglish: +        return Set::LanguageCode::EN_US; +    case ApplicationLanguage::BritishEnglish: +        return Set::LanguageCode::EN_GB; +    case ApplicationLanguage::Japanese: +        return Set::LanguageCode::JA; +    case ApplicationLanguage::French: +        return Set::LanguageCode::FR; +    case ApplicationLanguage::German: +        return Set::LanguageCode::DE; +    case ApplicationLanguage::LatinAmericanSpanish: +        return Set::LanguageCode::ES_419; +    case ApplicationLanguage::Spanish: +        return Set::LanguageCode::ES; +    case ApplicationLanguage::Italian: +        return Set::LanguageCode::IT; +    case ApplicationLanguage::Dutch: +        return Set::LanguageCode::NL; +    case ApplicationLanguage::CanadianFrench: +        return Set::LanguageCode::FR_CA; +    case ApplicationLanguage::Portuguese: +        return Set::LanguageCode::PT; +    case ApplicationLanguage::Russian: +        return Set::LanguageCode::RU; +    case ApplicationLanguage::Korean: +        return Set::LanguageCode::KO; +    case ApplicationLanguage::TraditionalChinese: +        return Set::LanguageCode::ZH_HANT; +    case ApplicationLanguage::SimplifiedChinese: +        return Set::LanguageCode::ZH_HANS; +    default: +        return std::nullopt; +    } +} +} // namespace Service::NS
\ No newline at end of file diff --git a/src/core/hle/service/ns/language.h b/src/core/hle/service/ns/language.h new file mode 100644 index 000000000..e9829f9d2 --- /dev/null +++ b/src/core/hle/service/ns/language.h @@ -0,0 +1,45 @@ +// Copyright 2019 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include <optional> +#include <string> +#include "common/common_types.h" + +namespace Service::Set { +enum class LanguageCode : u64; +} + +namespace Service::NS { +/// This is nn::ns::detail::ApplicationLanguage +enum class ApplicationLanguage : u8 { +    AmericanEnglish = 0, +    BritishEnglish, +    Japanese, +    French, +    German, +    LatinAmericanSpanish, +    Spanish, +    Italian, +    Dutch, +    CanadianFrench, +    Portuguese, +    Russian, +    Korean, +    TraditionalChinese, +    SimplifiedChinese, +    Count +}; +using ApplicationLanguagePriorityList = +    const std::array<ApplicationLanguage, static_cast<std::size_t>(ApplicationLanguage::Count)>; + +constexpr u32 GetSupportedLanguageFlag(const ApplicationLanguage lang) { +    return 1U << static_cast<u32>(lang); +} + +const ApplicationLanguagePriorityList* GetApplicationLanguagePriorityList(ApplicationLanguage lang); +std::optional<ApplicationLanguage> ConvertToApplicationLanguage(Set::LanguageCode language_code); +std::optional<Set::LanguageCode> ConvertToLanguageCode(ApplicationLanguage lang); +} // namespace Service::NS
\ No newline at end of file diff --git a/src/core/hle/service/ns/ns.cpp b/src/core/hle/service/ns/ns.cpp index 0eb04037a..ce88a2941 100644 --- a/src/core/hle/service/ns/ns.cpp +++ b/src/core/hle/service/ns/ns.cpp @@ -7,445 +7,507 @@  #include "core/file_sys/patch_manager.h"  #include "core/hle/ipc_helpers.h"  #include "core/hle/kernel/hle_ipc.h" +#include "core/hle/service/ns/errors.h" +#include "core/hle/service/ns/language.h"  #include "core/hle/service/ns/ns.h"  #include "core/hle/service/ns/pl_u.h" +#include "core/hle/service/set/set.h" +#include "core/settings.h"  namespace Service::NS { -class IAccountProxyInterface final : public ServiceFramework<IAccountProxyInterface> { -public: -    explicit IAccountProxyInterface() : ServiceFramework{"IAccountProxyInterface"} { -        // clang-format off -        static const FunctionInfo functions[] = { -            {0, nullptr, "CreateUserAccount"}, -        }; -        // clang-format on +IAccountProxyInterface::IAccountProxyInterface() : ServiceFramework{"IAccountProxyInterface"} { +    // clang-format off +    static const FunctionInfo functions[] = { +        {0, nullptr, "CreateUserAccount"}, +    }; +    // clang-format on -        RegisterHandlers(functions); -    } -}; +    RegisterHandlers(functions); +} -class IApplicationManagerInterface final : public ServiceFramework<IApplicationManagerInterface> { -public: -    explicit IApplicationManagerInterface() : ServiceFramework{"IApplicationManagerInterface"} { -        // clang-format off -        static const FunctionInfo functions[] = { -            {0, nullptr, "ListApplicationRecord"}, -            {1, nullptr, "GenerateApplicationRecordCount"}, -            {2, nullptr, "GetApplicationRecordUpdateSystemEvent"}, -            {3, nullptr, "GetApplicationViewDeprecated"}, -            {4, nullptr, "DeleteApplicationEntity"}, -            {5, nullptr, "DeleteApplicationCompletely"}, -            {6, nullptr, "IsAnyApplicationEntityRedundant"}, -            {7, nullptr, "DeleteRedundantApplicationEntity"}, -            {8, nullptr, "IsApplicationEntityMovable"}, -            {9, nullptr, "MoveApplicationEntity"}, -            {11, nullptr, "CalculateApplicationOccupiedSize"}, -            {16, nullptr, "PushApplicationRecord"}, -            {17, nullptr, "ListApplicationRecordContentMeta"}, -            {19, nullptr, "LaunchApplicationOld"}, -            {21, nullptr, "GetApplicationContentPath"}, -            {22, nullptr, "TerminateApplication"}, -            {23, nullptr, "ResolveApplicationContentPath"}, -            {26, nullptr, "BeginInstallApplication"}, -            {27, nullptr, "DeleteApplicationRecord"}, -            {30, nullptr, "RequestApplicationUpdateInfo"}, -            {32, nullptr, "CancelApplicationDownload"}, -            {33, nullptr, "ResumeApplicationDownload"}, -            {35, nullptr, "UpdateVersionList"}, -            {36, nullptr, "PushLaunchVersion"}, -            {37, nullptr, "ListRequiredVersion"}, -            {38, nullptr, "CheckApplicationLaunchVersion"}, -            {39, nullptr, "CheckApplicationLaunchRights"}, -            {40, nullptr, "GetApplicationLogoData"}, -            {41, nullptr, "CalculateApplicationDownloadRequiredSize"}, -            {42, nullptr, "CleanupSdCard"}, -            {43, nullptr, "CheckSdCardMountStatus"}, -            {44, nullptr, "GetSdCardMountStatusChangedEvent"}, -            {45, nullptr, "GetGameCardAttachmentEvent"}, -            {46, nullptr, "GetGameCardAttachmentInfo"}, -            {47, nullptr, "GetTotalSpaceSize"}, -            {48, nullptr, "GetFreeSpaceSize"}, -            {49, nullptr, "GetSdCardRemovedEvent"}, -            {52, nullptr, "GetGameCardUpdateDetectionEvent"}, -            {53, nullptr, "DisableApplicationAutoDelete"}, -            {54, nullptr, "EnableApplicationAutoDelete"}, -            {55, nullptr, "GetApplicationDesiredLanguage"}, -            {56, nullptr, "SetApplicationTerminateResult"}, -            {57, nullptr, "ClearApplicationTerminateResult"}, -            {58, nullptr, "GetLastSdCardMountUnexpectedResult"}, -            {59, nullptr, "ConvertApplicationLanguageToLanguageCode"}, -            {60, nullptr, "ConvertLanguageCodeToApplicationLanguage"}, -            {61, nullptr, "GetBackgroundDownloadStressTaskInfo"}, -            {62, nullptr, "GetGameCardStopper"}, -            {63, nullptr, "IsSystemProgramInstalled"}, -            {64, nullptr, "StartApplyDeltaTask"}, -            {65, nullptr, "GetRequestServerStopper"}, -            {66, nullptr, "GetBackgroundApplyDeltaStressTaskInfo"}, -            {67, nullptr, "CancelApplicationApplyDelta"}, -            {68, nullptr, "ResumeApplicationApplyDelta"}, -            {69, nullptr, "CalculateApplicationApplyDeltaRequiredSize"}, -            {70, nullptr, "ResumeAll"}, -            {71, nullptr, "GetStorageSize"}, -            {80, nullptr, "RequestDownloadApplication"}, -            {81, nullptr, "RequestDownloadAddOnContent"}, -            {82, nullptr, "DownloadApplication"}, -            {83, nullptr, "CheckApplicationResumeRights"}, -            {84, nullptr, "GetDynamicCommitEvent"}, -            {85, nullptr, "RequestUpdateApplication2"}, -            {86, nullptr, "EnableApplicationCrashReport"}, -            {87, nullptr, "IsApplicationCrashReportEnabled"}, -            {90, nullptr, "BoostSystemMemoryResourceLimit"}, -            {91, nullptr, "DeprecatedLaunchApplication"}, -            {92, nullptr, "GetRunningApplicationProgramId"}, -            {93, nullptr, "GetMainApplicationProgramIndex"}, -            {94, nullptr, "LaunchApplication"}, -            {95, nullptr, "GetApplicationLaunchInfo"}, -            {96, nullptr, "AcquireApplicationLaunchInfo"}, -            {97, nullptr, "GetMainApplicationProgramIndex2"}, -            {98, nullptr, "EnableApplicationAllThreadDumpOnCrash"}, -            {100, nullptr, "ResetToFactorySettings"}, -            {101, nullptr, "ResetToFactorySettingsWithoutUserSaveData"}, -            {102, nullptr, "ResetToFactorySettingsForRefurbishment"}, -            {200, nullptr, "CalculateUserSaveDataStatistics"}, -            {201, nullptr, "DeleteUserSaveDataAll"}, -            {210, nullptr, "DeleteUserSystemSaveData"}, -            {211, nullptr, "DeleteSaveData"}, -            {220, nullptr, "UnregisterNetworkServiceAccount"}, -            {221, nullptr, "UnregisterNetworkServiceAccountWithUserSaveDataDeletion"}, -            {300, nullptr, "GetApplicationShellEvent"}, -            {301, nullptr, "PopApplicationShellEventInfo"}, -            {302, nullptr, "LaunchLibraryApplet"}, -            {303, nullptr, "TerminateLibraryApplet"}, -            {304, nullptr, "LaunchSystemApplet"}, -            {305, nullptr, "TerminateSystemApplet"}, -            {306, nullptr, "LaunchOverlayApplet"}, -            {307, nullptr, "TerminateOverlayApplet"}, -            {400, &IApplicationManagerInterface::GetApplicationControlData, "GetApplicationControlData"}, -            {401, nullptr, "InvalidateAllApplicationControlCache"}, -            {402, nullptr, "RequestDownloadApplicationControlData"}, -            {403, nullptr, "GetMaxApplicationControlCacheCount"}, -            {404, nullptr, "InvalidateApplicationControlCache"}, -            {405, nullptr, "ListApplicationControlCacheEntryInfo"}, -            {406, nullptr, "GetApplicationControlProperty"}, -            {502, nullptr, "RequestCheckGameCardRegistration"}, -            {503, nullptr, "RequestGameCardRegistrationGoldPoint"}, -            {504, nullptr, "RequestRegisterGameCard"}, -            {505, nullptr, "GetGameCardMountFailureEvent"}, -            {506, nullptr, "IsGameCardInserted"}, -            {507, nullptr, "EnsureGameCardAccess"}, -            {508, nullptr, "GetLastGameCardMountFailureResult"}, -            {509, nullptr, "ListApplicationIdOnGameCard"}, -            {600, nullptr, "CountApplicationContentMeta"}, -            {601, nullptr, "ListApplicationContentMetaStatus"}, -            {602, nullptr, "ListAvailableAddOnContent"}, -            {603, nullptr, "GetOwnedApplicationContentMetaStatus"}, -            {604, nullptr, "RegisterContentsExternalKey"}, -            {605, nullptr, "ListApplicationContentMetaStatusWithRightsCheck"}, -            {606, nullptr, "GetContentMetaStorage"}, -            {607, nullptr, "ListAvailableAddOnContent"}, -            {700, nullptr, "PushDownloadTaskList"}, -            {701, nullptr, "ClearTaskStatusList"}, -            {702, nullptr, "RequestDownloadTaskList"}, -            {703, nullptr, "RequestEnsureDownloadTask"}, -            {704, nullptr, "ListDownloadTaskStatus"}, -            {705, nullptr, "RequestDownloadTaskListData"}, -            {800, nullptr, "RequestVersionList"}, -            {801, nullptr, "ListVersionList"}, -            {802, nullptr, "RequestVersionListData"}, -            {900, nullptr, "GetApplicationRecord"}, -            {901, nullptr, "GetApplicationRecordProperty"}, -            {902, nullptr, "EnableApplicationAutoUpdate"}, -            {903, nullptr, "DisableApplicationAutoUpdate"}, -            {904, nullptr, "TouchApplication"}, -            {905, nullptr, "RequestApplicationUpdate"}, -            {906, nullptr, "IsApplicationUpdateRequested"}, -            {907, nullptr, "WithdrawApplicationUpdateRequest"}, -            {908, nullptr, "ListApplicationRecordInstalledContentMeta"}, -            {909, nullptr, "WithdrawCleanupAddOnContentsWithNoRightsRecommendation"}, -            {910, nullptr, "HasApplicationRecord"}, -            {911, nullptr, "SetPreInstalledApplication"}, -            {912, nullptr, "ClearPreInstalledApplicationFlag"}, -            {1000, nullptr, "RequestVerifyApplicationDeprecated"}, -            {1001, nullptr, "CorruptApplicationForDebug"}, -            {1002, nullptr, "RequestVerifyAddOnContentsRights"}, -            {1003, nullptr, "RequestVerifyApplication"}, -            {1004, nullptr, "CorruptContentForDebug"}, -            {1200, nullptr, "NeedsUpdateVulnerability"}, -            {1300, nullptr, "IsAnyApplicationEntityInstalled"}, -            {1301, nullptr, "DeleteApplicationContentEntities"}, -            {1302, nullptr, "CleanupUnrecordedApplicationEntity"}, -            {1303, nullptr, "CleanupAddOnContentsWithNoRights"}, -            {1304, nullptr, "DeleteApplicationContentEntity"}, -            {1305, nullptr, "TryDeleteRunningApplicationEntity"}, -            {1306, nullptr, "TryDeleteRunningApplicationCompletely"}, -            {1307, nullptr, "TryDeleteRunningApplicationContentEntities"}, -            {1308, nullptr, "DeleteApplicationCompletelyForDebug"}, -            {1309, nullptr, "CleanupUnavailableAddOnContents"}, -            {1400, nullptr, "PrepareShutdown"}, -            {1500, nullptr, "FormatSdCard"}, -            {1501, nullptr, "NeedsSystemUpdateToFormatSdCard"}, -            {1502, nullptr, "GetLastSdCardFormatUnexpectedResult"}, -            {1504, nullptr, "InsertSdCard"}, -            {1505, nullptr, "RemoveSdCard"}, -            {1600, nullptr, "GetSystemSeedForPseudoDeviceId"}, -            {1601, nullptr, "ResetSystemSeedForPseudoDeviceId"}, -            {1700, nullptr, "ListApplicationDownloadingContentMeta"}, -            {1701, nullptr, "GetApplicationView"}, -            {1702, nullptr, "GetApplicationDownloadTaskStatus"}, -            {1703, nullptr, "GetApplicationViewDownloadErrorContext"}, -            {1800, nullptr, "IsNotificationSetupCompleted"}, -            {1801, nullptr, "GetLastNotificationInfoCount"}, -            {1802, nullptr, "ListLastNotificationInfo"}, -            {1803, nullptr, "ListNotificationTask"}, -            {1900, nullptr, "IsActiveAccount"}, -            {1901, nullptr, "RequestDownloadApplicationPrepurchasedRights"}, -            {1902, nullptr, "GetApplicationTicketInfo"}, -            {2000, nullptr, "GetSystemDeliveryInfo"}, -            {2001, nullptr, "SelectLatestSystemDeliveryInfo"}, -            {2002, nullptr, "VerifyDeliveryProtocolVersion"}, -            {2003, nullptr, "GetApplicationDeliveryInfo"}, -            {2004, nullptr, "HasAllContentsToDeliver"}, -            {2005, nullptr, "CompareApplicationDeliveryInfo"}, -            {2006, nullptr, "CanDeliverApplication"}, -            {2007, nullptr, "ListContentMetaKeyToDeliverApplication"}, -            {2008, nullptr, "NeedsSystemUpdateToDeliverApplication"}, -            {2009, nullptr, "EstimateRequiredSize"}, -            {2010, nullptr, "RequestReceiveApplication"}, -            {2011, nullptr, "CommitReceiveApplication"}, -            {2012, nullptr, "GetReceiveApplicationProgress"}, -            {2013, nullptr, "RequestSendApplication"}, -            {2014, nullptr, "GetSendApplicationProgress"}, -            {2015, nullptr, "CompareSystemDeliveryInfo"}, -            {2016, nullptr, "ListNotCommittedContentMeta"}, -            {2017, nullptr, "CreateDownloadTask"}, -            {2018, nullptr, "GetApplicationDeliveryInfoHash"}, -            {2050, nullptr, "GetApplicationRightsOnClient"}, -            {2100, nullptr, "GetApplicationTerminateResult"}, -            {2101, nullptr, "GetRawApplicationTerminateResult"}, -            {2150, nullptr, "CreateRightsEnvironment"}, -            {2151, nullptr, "DestroyRightsEnvironment"}, -            {2152, nullptr, "ActivateRightsEnvironment"}, -            {2153, nullptr, "DeactivateRightsEnvironment"}, -            {2154, nullptr, "ForceActivateRightsContextForExit"}, -            {2160, nullptr, "AddTargetApplicationToRightsEnvironment"}, -            {2161, nullptr, "SetUsersToRightsEnvironment"}, -            {2170, nullptr, "GetRightsEnvironmentStatus"}, -            {2171, nullptr, "GetRightsEnvironmentStatusChangedEvent"}, -            {2180, nullptr, "RequestExtendRightsInRightsEnvironment"}, -            {2181, nullptr, "GetLastResultOfExtendRightsInRightsEnvironment"}, -            {2182, nullptr, "SetActiveRightsContextUsingStateToRightsEnvironment"}, -            {2190, nullptr, "GetRightsEnvironmentHandleForApplication"}, -            {2199, nullptr, "GetRightsEnvironmentCountForDebug"}, -            {2200, nullptr, "GetGameCardApplicationCopyIdentifier"}, -            {2201, nullptr, "GetInstalledApplicationCopyIdentifier"}, -            {2250, nullptr, "RequestReportActiveELicence"}, -            {2300, nullptr, "ListEventLog"}, -        }; -        // clang-format on +IAccountProxyInterface::~IAccountProxyInterface() = default; + +IApplicationManagerInterface::IApplicationManagerInterface() +    : ServiceFramework{"IApplicationManagerInterface"} { +    // clang-format off +    static const FunctionInfo functions[] = { +        {0, nullptr, "ListApplicationRecord"}, +        {1, nullptr, "GenerateApplicationRecordCount"}, +        {2, nullptr, "GetApplicationRecordUpdateSystemEvent"}, +        {3, nullptr, "GetApplicationViewDeprecated"}, +        {4, nullptr, "DeleteApplicationEntity"}, +        {5, nullptr, "DeleteApplicationCompletely"}, +        {6, nullptr, "IsAnyApplicationEntityRedundant"}, +        {7, nullptr, "DeleteRedundantApplicationEntity"}, +        {8, nullptr, "IsApplicationEntityMovable"}, +        {9, nullptr, "MoveApplicationEntity"}, +        {11, nullptr, "CalculateApplicationOccupiedSize"}, +        {16, nullptr, "PushApplicationRecord"}, +        {17, nullptr, "ListApplicationRecordContentMeta"}, +        {19, nullptr, "LaunchApplicationOld"}, +        {21, nullptr, "GetApplicationContentPath"}, +        {22, nullptr, "TerminateApplication"}, +        {23, nullptr, "ResolveApplicationContentPath"}, +        {26, nullptr, "BeginInstallApplication"}, +        {27, nullptr, "DeleteApplicationRecord"}, +        {30, nullptr, "RequestApplicationUpdateInfo"}, +        {32, nullptr, "CancelApplicationDownload"}, +        {33, nullptr, "ResumeApplicationDownload"}, +        {35, nullptr, "UpdateVersionList"}, +        {36, nullptr, "PushLaunchVersion"}, +        {37, nullptr, "ListRequiredVersion"}, +        {38, nullptr, "CheckApplicationLaunchVersion"}, +        {39, nullptr, "CheckApplicationLaunchRights"}, +        {40, nullptr, "GetApplicationLogoData"}, +        {41, nullptr, "CalculateApplicationDownloadRequiredSize"}, +        {42, nullptr, "CleanupSdCard"}, +        {43, nullptr, "CheckSdCardMountStatus"}, +        {44, nullptr, "GetSdCardMountStatusChangedEvent"}, +        {45, nullptr, "GetGameCardAttachmentEvent"}, +        {46, nullptr, "GetGameCardAttachmentInfo"}, +        {47, nullptr, "GetTotalSpaceSize"}, +        {48, nullptr, "GetFreeSpaceSize"}, +        {49, nullptr, "GetSdCardRemovedEvent"}, +        {52, nullptr, "GetGameCardUpdateDetectionEvent"}, +        {53, nullptr, "DisableApplicationAutoDelete"}, +        {54, nullptr, "EnableApplicationAutoDelete"}, +        {55, &IApplicationManagerInterface::GetApplicationDesiredLanguage, "GetApplicationDesiredLanguage"}, +        {56, nullptr, "SetApplicationTerminateResult"}, +        {57, nullptr, "ClearApplicationTerminateResult"}, +        {58, nullptr, "GetLastSdCardMountUnexpectedResult"}, +        {59, &IApplicationManagerInterface::ConvertApplicationLanguageToLanguageCode, "ConvertApplicationLanguageToLanguageCode"}, +        {60, nullptr, "ConvertLanguageCodeToApplicationLanguage"}, +        {61, nullptr, "GetBackgroundDownloadStressTaskInfo"}, +        {62, nullptr, "GetGameCardStopper"}, +        {63, nullptr, "IsSystemProgramInstalled"}, +        {64, nullptr, "StartApplyDeltaTask"}, +        {65, nullptr, "GetRequestServerStopper"}, +        {66, nullptr, "GetBackgroundApplyDeltaStressTaskInfo"}, +        {67, nullptr, "CancelApplicationApplyDelta"}, +        {68, nullptr, "ResumeApplicationApplyDelta"}, +        {69, nullptr, "CalculateApplicationApplyDeltaRequiredSize"}, +        {70, nullptr, "ResumeAll"}, +        {71, nullptr, "GetStorageSize"}, +        {80, nullptr, "RequestDownloadApplication"}, +        {81, nullptr, "RequestDownloadAddOnContent"}, +        {82, nullptr, "DownloadApplication"}, +        {83, nullptr, "CheckApplicationResumeRights"}, +        {84, nullptr, "GetDynamicCommitEvent"}, +        {85, nullptr, "RequestUpdateApplication2"}, +        {86, nullptr, "EnableApplicationCrashReport"}, +        {87, nullptr, "IsApplicationCrashReportEnabled"}, +        {90, nullptr, "BoostSystemMemoryResourceLimit"}, +        {91, nullptr, "DeprecatedLaunchApplication"}, +        {92, nullptr, "GetRunningApplicationProgramId"}, +        {93, nullptr, "GetMainApplicationProgramIndex"}, +        {94, nullptr, "LaunchApplication"}, +        {95, nullptr, "GetApplicationLaunchInfo"}, +        {96, nullptr, "AcquireApplicationLaunchInfo"}, +        {97, nullptr, "GetMainApplicationProgramIndex2"}, +        {98, nullptr, "EnableApplicationAllThreadDumpOnCrash"}, +        {100, nullptr, "ResetToFactorySettings"}, +        {101, nullptr, "ResetToFactorySettingsWithoutUserSaveData"}, +        {102, nullptr, "ResetToFactorySettingsForRefurbishment"}, +        {200, nullptr, "CalculateUserSaveDataStatistics"}, +        {201, nullptr, "DeleteUserSaveDataAll"}, +        {210, nullptr, "DeleteUserSystemSaveData"}, +        {211, nullptr, "DeleteSaveData"}, +        {220, nullptr, "UnregisterNetworkServiceAccount"}, +        {221, nullptr, "UnregisterNetworkServiceAccountWithUserSaveDataDeletion"}, +        {300, nullptr, "GetApplicationShellEvent"}, +        {301, nullptr, "PopApplicationShellEventInfo"}, +        {302, nullptr, "LaunchLibraryApplet"}, +        {303, nullptr, "TerminateLibraryApplet"}, +        {304, nullptr, "LaunchSystemApplet"}, +        {305, nullptr, "TerminateSystemApplet"}, +        {306, nullptr, "LaunchOverlayApplet"}, +        {307, nullptr, "TerminateOverlayApplet"}, +        {400, &IApplicationManagerInterface::GetApplicationControlData, "GetApplicationControlData"}, +        {401, nullptr, "InvalidateAllApplicationControlCache"}, +        {402, nullptr, "RequestDownloadApplicationControlData"}, +        {403, nullptr, "GetMaxApplicationControlCacheCount"}, +        {404, nullptr, "InvalidateApplicationControlCache"}, +        {405, nullptr, "ListApplicationControlCacheEntryInfo"}, +        {406, nullptr, "GetApplicationControlProperty"}, +        {502, nullptr, "RequestCheckGameCardRegistration"}, +        {503, nullptr, "RequestGameCardRegistrationGoldPoint"}, +        {504, nullptr, "RequestRegisterGameCard"}, +        {505, nullptr, "GetGameCardMountFailureEvent"}, +        {506, nullptr, "IsGameCardInserted"}, +        {507, nullptr, "EnsureGameCardAccess"}, +        {508, nullptr, "GetLastGameCardMountFailureResult"}, +        {509, nullptr, "ListApplicationIdOnGameCard"}, +        {600, nullptr, "CountApplicationContentMeta"}, +        {601, nullptr, "ListApplicationContentMetaStatus"}, +        {602, nullptr, "ListAvailableAddOnContent"}, +        {603, nullptr, "GetOwnedApplicationContentMetaStatus"}, +        {604, nullptr, "RegisterContentsExternalKey"}, +        {605, nullptr, "ListApplicationContentMetaStatusWithRightsCheck"}, +        {606, nullptr, "GetContentMetaStorage"}, +        {607, nullptr, "ListAvailableAddOnContent"}, +        {700, nullptr, "PushDownloadTaskList"}, +        {701, nullptr, "ClearTaskStatusList"}, +        {702, nullptr, "RequestDownloadTaskList"}, +        {703, nullptr, "RequestEnsureDownloadTask"}, +        {704, nullptr, "ListDownloadTaskStatus"}, +        {705, nullptr, "RequestDownloadTaskListData"}, +        {800, nullptr, "RequestVersionList"}, +        {801, nullptr, "ListVersionList"}, +        {802, nullptr, "RequestVersionListData"}, +        {900, nullptr, "GetApplicationRecord"}, +        {901, nullptr, "GetApplicationRecordProperty"}, +        {902, nullptr, "EnableApplicationAutoUpdate"}, +        {903, nullptr, "DisableApplicationAutoUpdate"}, +        {904, nullptr, "TouchApplication"}, +        {905, nullptr, "RequestApplicationUpdate"}, +        {906, nullptr, "IsApplicationUpdateRequested"}, +        {907, nullptr, "WithdrawApplicationUpdateRequest"}, +        {908, nullptr, "ListApplicationRecordInstalledContentMeta"}, +        {909, nullptr, "WithdrawCleanupAddOnContentsWithNoRightsRecommendation"}, +        {910, nullptr, "HasApplicationRecord"}, +        {911, nullptr, "SetPreInstalledApplication"}, +        {912, nullptr, "ClearPreInstalledApplicationFlag"}, +        {1000, nullptr, "RequestVerifyApplicationDeprecated"}, +        {1001, nullptr, "CorruptApplicationForDebug"}, +        {1002, nullptr, "RequestVerifyAddOnContentsRights"}, +        {1003, nullptr, "RequestVerifyApplication"}, +        {1004, nullptr, "CorruptContentForDebug"}, +        {1200, nullptr, "NeedsUpdateVulnerability"}, +        {1300, nullptr, "IsAnyApplicationEntityInstalled"}, +        {1301, nullptr, "DeleteApplicationContentEntities"}, +        {1302, nullptr, "CleanupUnrecordedApplicationEntity"}, +        {1303, nullptr, "CleanupAddOnContentsWithNoRights"}, +        {1304, nullptr, "DeleteApplicationContentEntity"}, +        {1305, nullptr, "TryDeleteRunningApplicationEntity"}, +        {1306, nullptr, "TryDeleteRunningApplicationCompletely"}, +        {1307, nullptr, "TryDeleteRunningApplicationContentEntities"}, +        {1308, nullptr, "DeleteApplicationCompletelyForDebug"}, +        {1309, nullptr, "CleanupUnavailableAddOnContents"}, +        {1400, nullptr, "PrepareShutdown"}, +        {1500, nullptr, "FormatSdCard"}, +        {1501, nullptr, "NeedsSystemUpdateToFormatSdCard"}, +        {1502, nullptr, "GetLastSdCardFormatUnexpectedResult"}, +        {1504, nullptr, "InsertSdCard"}, +        {1505, nullptr, "RemoveSdCard"}, +        {1600, nullptr, "GetSystemSeedForPseudoDeviceId"}, +        {1601, nullptr, "ResetSystemSeedForPseudoDeviceId"}, +        {1700, nullptr, "ListApplicationDownloadingContentMeta"}, +        {1701, nullptr, "GetApplicationView"}, +        {1702, nullptr, "GetApplicationDownloadTaskStatus"}, +        {1703, nullptr, "GetApplicationViewDownloadErrorContext"}, +        {1800, nullptr, "IsNotificationSetupCompleted"}, +        {1801, nullptr, "GetLastNotificationInfoCount"}, +        {1802, nullptr, "ListLastNotificationInfo"}, +        {1803, nullptr, "ListNotificationTask"}, +        {1900, nullptr, "IsActiveAccount"}, +        {1901, nullptr, "RequestDownloadApplicationPrepurchasedRights"}, +        {1902, nullptr, "GetApplicationTicketInfo"}, +        {2000, nullptr, "GetSystemDeliveryInfo"}, +        {2001, nullptr, "SelectLatestSystemDeliveryInfo"}, +        {2002, nullptr, "VerifyDeliveryProtocolVersion"}, +        {2003, nullptr, "GetApplicationDeliveryInfo"}, +        {2004, nullptr, "HasAllContentsToDeliver"}, +        {2005, nullptr, "CompareApplicationDeliveryInfo"}, +        {2006, nullptr, "CanDeliverApplication"}, +        {2007, nullptr, "ListContentMetaKeyToDeliverApplication"}, +        {2008, nullptr, "NeedsSystemUpdateToDeliverApplication"}, +        {2009, nullptr, "EstimateRequiredSize"}, +        {2010, nullptr, "RequestReceiveApplication"}, +        {2011, nullptr, "CommitReceiveApplication"}, +        {2012, nullptr, "GetReceiveApplicationProgress"}, +        {2013, nullptr, "RequestSendApplication"}, +        {2014, nullptr, "GetSendApplicationProgress"}, +        {2015, nullptr, "CompareSystemDeliveryInfo"}, +        {2016, nullptr, "ListNotCommittedContentMeta"}, +        {2017, nullptr, "CreateDownloadTask"}, +        {2018, nullptr, "GetApplicationDeliveryInfoHash"}, +        {2050, nullptr, "GetApplicationRightsOnClient"}, +        {2100, nullptr, "GetApplicationTerminateResult"}, +        {2101, nullptr, "GetRawApplicationTerminateResult"}, +        {2150, nullptr, "CreateRightsEnvironment"}, +        {2151, nullptr, "DestroyRightsEnvironment"}, +        {2152, nullptr, "ActivateRightsEnvironment"}, +        {2153, nullptr, "DeactivateRightsEnvironment"}, +        {2154, nullptr, "ForceActivateRightsContextForExit"}, +        {2160, nullptr, "AddTargetApplicationToRightsEnvironment"}, +        {2161, nullptr, "SetUsersToRightsEnvironment"}, +        {2170, nullptr, "GetRightsEnvironmentStatus"}, +        {2171, nullptr, "GetRightsEnvironmentStatusChangedEvent"}, +        {2180, nullptr, "RequestExtendRightsInRightsEnvironment"}, +        {2181, nullptr, "GetLastResultOfExtendRightsInRightsEnvironment"}, +        {2182, nullptr, "SetActiveRightsContextUsingStateToRightsEnvironment"}, +        {2190, nullptr, "GetRightsEnvironmentHandleForApplication"}, +        {2199, nullptr, "GetRightsEnvironmentCountForDebug"}, +        {2200, nullptr, "GetGameCardApplicationCopyIdentifier"}, +        {2201, nullptr, "GetInstalledApplicationCopyIdentifier"}, +        {2250, nullptr, "RequestReportActiveELicence"}, +        {2300, nullptr, "ListEventLog"}, +    }; +    // clang-format on + +    RegisterHandlers(functions); +} -        RegisterHandlers(functions); -    } +IApplicationManagerInterface::~IApplicationManagerInterface() = default; + +void IApplicationManagerInterface::GetApplicationControlData(Kernel::HLERequestContext& ctx) { +    IPC::RequestParser rp{ctx}; +    const auto flag = rp.PopRaw<u64>(); +    LOG_DEBUG(Service_NS, "called with flag={:016X}", flag); -    void GetApplicationControlData(Kernel::HLERequestContext& ctx) { -        IPC::RequestParser rp{ctx}; -        const auto flag = rp.PopRaw<u64>(); -        LOG_DEBUG(Service_NS, "called with flag={:016X}", flag); - -        const auto title_id = rp.PopRaw<u64>(); - -        const auto size = ctx.GetWriteBufferSize(); - -        const FileSys::PatchManager pm{title_id}; -        const auto control = pm.GetControlMetadata(); - -        std::vector<u8> out; - -        if (control.first != nullptr) { -            if (size < 0x4000) { -                LOG_ERROR(Service_NS, -                          "output buffer is too small! (actual={:016X}, expected_min=0x4000)", -                          size); -                IPC::ResponseBuilder rb{ctx, 2}; -                // TODO(DarkLordZach): Find a better error code for this. -                rb.Push(ResultCode(-1)); -                return; -            } - -            out.resize(0x4000); -            const auto bytes = control.first->GetRawBytes(); -            std::memcpy(out.data(), bytes.data(), bytes.size()); -        } else { -            LOG_WARNING(Service_NS, "missing NACP data for title_id={:016X}, defaulting to zeros.", -                        title_id); -            out.resize(std::min<u64>(0x4000, size)); +    const auto title_id = rp.PopRaw<u64>(); + +    const auto size = ctx.GetWriteBufferSize(); + +    const FileSys::PatchManager pm{title_id}; +    const auto control = pm.GetControlMetadata(); + +    std::vector<u8> out; + +    if (control.first != nullptr) { +        if (size < 0x4000) { +            LOG_ERROR(Service_NS, +                      "output buffer is too small! (actual={:016X}, expected_min=0x4000)", size); +            IPC::ResponseBuilder rb{ctx, 2}; +            // TODO(DarkLordZach): Find a better error code for this. +            rb.Push(ResultCode(-1)); +            return;          } -        if (control.second != nullptr) { -            if (size < 0x4000 + control.second->GetSize()) { -                LOG_ERROR(Service_NS, -                          "output buffer is too small! (actual={:016X}, expected_min={:016X})", -                          size, 0x4000 + control.second->GetSize()); -                IPC::ResponseBuilder rb{ctx, 2}; -                // TODO(DarkLordZach): Find a better error code for this. -                rb.Push(ResultCode(-1)); -                return; -            } - -            out.resize(0x4000 + control.second->GetSize()); -            control.second->Read(out.data() + 0x4000, control.second->GetSize()); -        } else { -            LOG_WARNING(Service_NS, "missing icon data for title_id={:016X}, defaulting to zeros.", -                        title_id); +        out.resize(0x4000); +        const auto bytes = control.first->GetRawBytes(); +        std::memcpy(out.data(), bytes.data(), bytes.size()); +    } else { +        LOG_WARNING(Service_NS, "missing NACP data for title_id={:016X}, defaulting to zeros.", +                    title_id); +        out.resize(std::min<u64>(0x4000, size)); +    } + +    if (control.second != nullptr) { +        if (size < 0x4000 + control.second->GetSize()) { +            LOG_ERROR(Service_NS, +                      "output buffer is too small! (actual={:016X}, expected_min={:016X})", size, +                      0x4000 + control.second->GetSize()); +            IPC::ResponseBuilder rb{ctx, 2}; +            // TODO(DarkLordZach): Find a better error code for this. +            rb.Push(ResultCode(-1)); +            return;          } -        ctx.WriteBuffer(out); +        out.resize(0x4000 + control.second->GetSize()); +        control.second->Read(out.data() + 0x4000, control.second->GetSize()); +    } else { +        LOG_WARNING(Service_NS, "missing icon data for title_id={:016X}, defaulting to zeros.", +                    title_id); +    } + +    ctx.WriteBuffer(out); + +    IPC::ResponseBuilder rb{ctx, 3}; +    rb.Push(RESULT_SUCCESS); +    rb.Push<u32>(static_cast<u32>(out.size())); +} + +void IApplicationManagerInterface::GetApplicationDesiredLanguage(Kernel::HLERequestContext& ctx) { +    IPC::RequestParser rp{ctx}; +    const auto supported_languages = rp.Pop<u32>(); +    const auto res = GetApplicationDesiredLanguage(supported_languages); +    if (res.Succeeded()) {          IPC::ResponseBuilder rb{ctx, 3};          rb.Push(RESULT_SUCCESS); -        rb.Push<u32>(static_cast<u32>(out.size())); +        rb.Push<u32>(*res); +    } else { +        IPC::ResponseBuilder rb{ctx, 2}; +        rb.Push(res.Code());      } -}; +} -class IApplicationVersionInterface final : public ServiceFramework<IApplicationVersionInterface> { -public: -    explicit IApplicationVersionInterface() : ServiceFramework{"IApplicationVersionInterface"} { -        // clang-format off -        static const FunctionInfo functions[] = { -            {0, nullptr, "GetLaunchRequiredVersion"}, -            {1, nullptr, "UpgradeLaunchRequiredVersion"}, -            {35, nullptr, "UpdateVersionList"}, -            {36, nullptr, "PushLaunchVersion"}, -            {37, nullptr, "ListRequiredVersion"}, -            {800, nullptr, "RequestVersionList"}, -            {801, nullptr, "ListVersionList"}, -            {802, nullptr, "RequestVersionListData"}, -            {1000, nullptr, "PerformAutoUpdate"}, -        }; -        // clang-format on +ResultVal<u8> IApplicationManagerInterface::GetApplicationDesiredLanguage( +    const u32 supported_languages) { +    LOG_DEBUG(Service_NS, "called with supported_languages={:08X}", supported_languages); -        RegisterHandlers(functions); -    } -}; +    // Get language code from settings +    const auto language_code = Set::GetLanguageCodeFromIndex(Settings::values.language_index); -class IContentManagerInterface final : public ServiceFramework<IContentManagerInterface> { -public: -    explicit IContentManagerInterface() : ServiceFramework{"IContentManagerInterface"} { -        // clang-format off -        static const FunctionInfo functions[] = { -            {11, nullptr, "CalculateApplicationOccupiedSize"}, -            {43, nullptr, "CheckSdCardMountStatus"}, -            {47, nullptr, "GetTotalSpaceSize"}, -            {48, nullptr, "GetFreeSpaceSize"}, -            {600, nullptr, "CountApplicationContentMeta"}, -            {601, nullptr, "ListApplicationContentMetaStatus"}, -            {605, nullptr, "ListApplicationContentMetaStatusWithRightsCheck"}, -            {607, nullptr, "IsAnyApplicationRunning"}, -        }; -        // clang-format on +    // Convert to application language, get priority list +    const auto application_language = ConvertToApplicationLanguage(language_code); +    if (application_language == std::nullopt) { +        return ERR_APPLICATION_LANGUAGE_NOT_FOUND; +    } +    const auto priority_list = GetApplicationLanguagePriorityList(*application_language); +    if (!priority_list) { +        return ERR_APPLICATION_LANGUAGE_NOT_FOUND; +    } -        RegisterHandlers(functions); +    // Try to find a valid language. +    for (const auto lang : *priority_list) { +        const auto supported_flag = GetSupportedLanguageFlag(lang); +        if (supported_languages == 0 || (supported_languages & supported_flag) == supported_flag) { +            return MakeResult(static_cast<u8>(lang)); +        }      } -}; -class IDocumentInterface final : public ServiceFramework<IDocumentInterface> { -public: -    explicit IDocumentInterface() : ServiceFramework{"IDocumentInterface"} { -        // clang-format off -        static const FunctionInfo functions[] = { -            {21, nullptr, "GetApplicationContentPath"}, -            {23, nullptr, "ResolveApplicationContentPath"}, -            {93, nullptr, "GetRunningApplicationProgramId"}, -        }; -        // clang-format on +    return ERR_APPLICATION_LANGUAGE_NOT_FOUND; +} -        RegisterHandlers(functions); -    } -}; +void IApplicationManagerInterface::ConvertApplicationLanguageToLanguageCode( +    Kernel::HLERequestContext& ctx) { +    IPC::RequestParser rp{ctx}; +    const auto application_language = rp.Pop<u8>(); -class IDownloadTaskInterface final : public ServiceFramework<IDownloadTaskInterface> { -public: -    explicit IDownloadTaskInterface() : ServiceFramework{"IDownloadTaskInterface"} { -        // clang-format off -        static const FunctionInfo functions[] = { -            {701, nullptr, "ClearTaskStatusList"}, -            {702, nullptr, "RequestDownloadTaskList"}, -            {703, nullptr, "RequestEnsureDownloadTask"}, -            {704, nullptr, "ListDownloadTaskStatus"}, -            {705, nullptr, "RequestDownloadTaskListData"}, -            {706, nullptr, "TryCommitCurrentApplicationDownloadTask"}, -            {707, nullptr, "EnableAutoCommit"}, -            {708, nullptr, "DisableAutoCommit"}, -            {709, nullptr, "TriggerDynamicCommitEvent"}, -        }; -        // clang-format on +    const auto res = ConvertApplicationLanguageToLanguageCode(application_language); +    if (res.Succeeded()) { +        IPC::ResponseBuilder rb{ctx, 4}; +        rb.Push(RESULT_SUCCESS); +        rb.Push(*res); +    } else { +        IPC::ResponseBuilder rb{ctx, 2}; +        rb.Push(res.Code()); +    } +} -        RegisterHandlers(functions); +ResultVal<u64> IApplicationManagerInterface::ConvertApplicationLanguageToLanguageCode( +    u8 application_language) { +    const auto language_code = +        ConvertToLanguageCode(static_cast<ApplicationLanguage>(application_language)); +    if (language_code == std::nullopt) { +        return ERR_APPLICATION_LANGUAGE_NOT_FOUND;      } -}; -class IECommerceInterface final : public ServiceFramework<IECommerceInterface> { -public: -    explicit IECommerceInterface() : ServiceFramework{"IECommerceInterface"} { -        // clang-format off -        static const FunctionInfo functions[] = { -            {0, nullptr, "RequestLinkDevice"}, -            {1, nullptr, "RequestCleanupAllPreInstalledApplications"}, -            {2, nullptr, "RequestCleanupPreInstalledApplication"}, -            {3, nullptr, "RequestSyncRights"}, -            {4, nullptr, "RequestUnlinkDevice"}, -            {5, nullptr, "RequestRevokeAllELicense"}, -        }; -        // clang-format on +    return MakeResult(static_cast<u64>(*language_code)); +} -        RegisterHandlers(functions); -    } -}; +IApplicationVersionInterface::IApplicationVersionInterface() +    : ServiceFramework{"IApplicationVersionInterface"} { +    // clang-format off +    static const FunctionInfo functions[] = { +        {0, nullptr, "GetLaunchRequiredVersion"}, +        {1, nullptr, "UpgradeLaunchRequiredVersion"}, +        {35, nullptr, "UpdateVersionList"}, +        {36, nullptr, "PushLaunchVersion"}, +        {37, nullptr, "ListRequiredVersion"}, +        {800, nullptr, "RequestVersionList"}, +        {801, nullptr, "ListVersionList"}, +        {802, nullptr, "RequestVersionListData"}, +        {1000, nullptr, "PerformAutoUpdate"}, +    }; +    // clang-format on + +    RegisterHandlers(functions); +} -class IFactoryResetInterface final : public ServiceFramework<IFactoryResetInterface> { -public: -    explicit IFactoryResetInterface() : ServiceFramework{"IFactoryResetInterface"} { -        // clang-format off +IApplicationVersionInterface::~IApplicationVersionInterface() = default; + +IContentManagerInterface::IContentManagerInterface() +    : ServiceFramework{"IContentManagerInterface"} { +    // clang-format off +    static const FunctionInfo functions[] = { +        {11, nullptr, "CalculateApplicationOccupiedSize"}, +        {43, nullptr, "CheckSdCardMountStatus"}, +        {47, nullptr, "GetTotalSpaceSize"}, +        {48, nullptr, "GetFreeSpaceSize"}, +        {600, nullptr, "CountApplicationContentMeta"}, +        {601, nullptr, "ListApplicationContentMetaStatus"}, +        {605, nullptr, "ListApplicationContentMetaStatusWithRightsCheck"}, +        {607, nullptr, "IsAnyApplicationRunning"}, +    }; +    // clang-format on + +    RegisterHandlers(functions); +} + +IContentManagerInterface::~IContentManagerInterface() = default; + +IDocumentInterface::IDocumentInterface() : ServiceFramework{"IDocumentInterface"} { +    // clang-format off +    static const FunctionInfo functions[] = { +        {21, nullptr, "GetApplicationContentPath"}, +        {23, nullptr, "ResolveApplicationContentPath"}, +        {93, nullptr, "GetRunningApplicationProgramId"}, +    }; +    // clang-format on + +    RegisterHandlers(functions); +} + +IDocumentInterface::~IDocumentInterface() = default; + +IDownloadTaskInterface::IDownloadTaskInterface() : ServiceFramework{"IDownloadTaskInterface"} { +    // clang-format off +    static const FunctionInfo functions[] = { +        {701, nullptr, "ClearTaskStatusList"}, +        {702, nullptr, "RequestDownloadTaskList"}, +        {703, nullptr, "RequestEnsureDownloadTask"}, +        {704, nullptr, "ListDownloadTaskStatus"}, +        {705, nullptr, "RequestDownloadTaskListData"}, +        {706, nullptr, "TryCommitCurrentApplicationDownloadTask"}, +        {707, nullptr, "EnableAutoCommit"}, +        {708, nullptr, "DisableAutoCommit"}, +        {709, nullptr, "TriggerDynamicCommitEvent"}, +    }; +    // clang-format on + +    RegisterHandlers(functions); +} + +IDownloadTaskInterface::~IDownloadTaskInterface() = default; + +IECommerceInterface::IECommerceInterface() : ServiceFramework{"IECommerceInterface"} { +    // clang-format off +    static const FunctionInfo functions[] = { +        {0, nullptr, "RequestLinkDevice"}, +        {1, nullptr, "RequestCleanupAllPreInstalledApplications"}, +        {2, nullptr, "RequestCleanupPreInstalledApplication"}, +        {3, nullptr, "RequestSyncRights"}, +        {4, nullptr, "RequestUnlinkDevice"}, +        {5, nullptr, "RequestRevokeAllELicense"}, +    }; +    // clang-format on + +    RegisterHandlers(functions); +} + +IECommerceInterface::~IECommerceInterface() = default; + +IFactoryResetInterface::IFactoryResetInterface::IFactoryResetInterface() +    : ServiceFramework{"IFactoryResetInterface"} { +    // clang-format off          static const FunctionInfo functions[] = {              {100, nullptr, "ResetToFactorySettings"},              {101, nullptr, "ResetToFactorySettingsWithoutUserSaveData"},              {102, nullptr, "ResetToFactorySettingsForRefurbishment"},          }; -        // clang-format on +    // clang-format on -        RegisterHandlers(functions); -    } -}; - -class NS final : public ServiceFramework<NS> { -public: -    explicit NS(const char* name) : ServiceFramework{name} { -        // clang-format off -        static const FunctionInfo functions[] = { -            {7992, &NS::PushInterface<IECommerceInterface>, "GetECommerceInterface"}, -            {7993, &NS::PushInterface<IApplicationVersionInterface>, "GetApplicationVersionInterface"}, -            {7994, &NS::PushInterface<IFactoryResetInterface>, "GetFactoryResetInterface"}, -            {7995, &NS::PushInterface<IAccountProxyInterface>, "GetAccountProxyInterface"}, -            {7996, &NS::PushInterface<IApplicationManagerInterface>, "GetApplicationManagerInterface"}, -            {7997, &NS::PushInterface<IDownloadTaskInterface>, "GetDownloadTaskInterface"}, -            {7998, &NS::PushInterface<IContentManagerInterface>, "GetContentManagementInterface"}, -            {7999, &NS::PushInterface<IDocumentInterface>, "GetDocumentInterface"}, -        }; -        // clang-format on +    RegisterHandlers(functions); +} -        RegisterHandlers(functions); -    } +IFactoryResetInterface::~IFactoryResetInterface() = default; + +NS::NS(const char* name) : ServiceFramework{name} { +    // clang-format off +    static const FunctionInfo functions[] = { +        {7992, &NS::PushInterface<IECommerceInterface>, "GetECommerceInterface"}, +        {7993, &NS::PushInterface<IApplicationVersionInterface>, "GetApplicationVersionInterface"}, +        {7994, &NS::PushInterface<IFactoryResetInterface>, "GetFactoryResetInterface"}, +        {7995, &NS::PushInterface<IAccountProxyInterface>, "GetAccountProxyInterface"}, +        {7996, &NS::PushInterface<IApplicationManagerInterface>, "GetApplicationManagerInterface"}, +        {7997, &NS::PushInterface<IDownloadTaskInterface>, "GetDownloadTaskInterface"}, +        {7998, &NS::PushInterface<IContentManagerInterface>, "GetContentManagementInterface"}, +        {7999, &NS::PushInterface<IDocumentInterface>, "GetDocumentInterface"}, +    }; +    // clang-format on + +    RegisterHandlers(functions); +} -private: -    template <typename T> -    void PushInterface(Kernel::HLERequestContext& ctx) { -        LOG_DEBUG(Service_NS, "called"); +NS::~NS() = default; -        IPC::ResponseBuilder rb{ctx, 2, 0, 1}; -        rb.Push(RESULT_SUCCESS); -        rb.PushIpcInterface<T>(); -    } -}; +std::shared_ptr<IApplicationManagerInterface> NS::GetApplicationManagerInterface() const { +    return GetInterface<IApplicationManagerInterface>(); +}  class NS_DEV final : public ServiceFramework<NS_DEV> {  public: diff --git a/src/core/hle/service/ns/ns.h b/src/core/hle/service/ns/ns.h index b81ca8f1e..0f4bab4cb 100644 --- a/src/core/hle/service/ns/ns.h +++ b/src/core/hle/service/ns/ns.h @@ -8,6 +8,88 @@  namespace Service::NS { +class IAccountProxyInterface final : public ServiceFramework<IAccountProxyInterface> { +public: +    explicit IAccountProxyInterface(); +    ~IAccountProxyInterface(); +}; + +class IApplicationManagerInterface final : public ServiceFramework<IApplicationManagerInterface> { +public: +    explicit IApplicationManagerInterface(); +    ~IApplicationManagerInterface(); + +    ResultVal<u8> GetApplicationDesiredLanguage(u32 supported_languages); +    ResultVal<u64> ConvertApplicationLanguageToLanguageCode(u8 application_language); + +private: +    void GetApplicationControlData(Kernel::HLERequestContext& ctx); +    void GetApplicationDesiredLanguage(Kernel::HLERequestContext& ctx); +    void ConvertApplicationLanguageToLanguageCode(Kernel::HLERequestContext& ctx); +}; + +class IApplicationVersionInterface final : public ServiceFramework<IApplicationVersionInterface> { +public: +    explicit IApplicationVersionInterface(); +    ~IApplicationVersionInterface(); +}; + +class IContentManagerInterface final : public ServiceFramework<IContentManagerInterface> { +public: +    explicit IContentManagerInterface(); +    ~IContentManagerInterface(); +}; + +class IDocumentInterface final : public ServiceFramework<IDocumentInterface> { +public: +    explicit IDocumentInterface(); +    ~IDocumentInterface(); +}; + +class IDownloadTaskInterface final : public ServiceFramework<IDownloadTaskInterface> { +public: +    explicit IDownloadTaskInterface(); +    ~IDownloadTaskInterface(); +}; + +class IECommerceInterface final : public ServiceFramework<IECommerceInterface> { +public: +    explicit IECommerceInterface(); +    ~IECommerceInterface(); +}; + +class IFactoryResetInterface final : public ServiceFramework<IFactoryResetInterface> { +public: +    explicit IFactoryResetInterface(); +    ~IFactoryResetInterface(); +}; + +class NS final : public ServiceFramework<NS> { +public: +    explicit NS(const char* name); +    ~NS(); + +    std::shared_ptr<IApplicationManagerInterface> GetApplicationManagerInterface() const; + +private: +    template <typename T> +    void PushInterface(Kernel::HLERequestContext& ctx) { +        LOG_DEBUG(Service_NS, "called"); + +        IPC::ResponseBuilder rb{ctx, 2, 0, 1}; +        rb.Push(RESULT_SUCCESS); +        rb.PushIpcInterface<T>(); +    } + +    template <typename T> +    std::shared_ptr<T> GetInterface() const { +        static_assert(std::is_base_of_v<Kernel::SessionRequestHandler, T>, +                      "Not a base of ServiceFrameworkBase"); + +        return std::make_shared<T>(); +    } +}; +  /// Registers all NS services with the specified service manager.  void InstallInterfaces(SM::ServiceManager& service_manager); diff --git a/src/core/hle/service/ns/ns_language.h b/src/core/hle/service/ns/ns_language.h new file mode 100644 index 000000000..59ac85a19 --- /dev/null +++ b/src/core/hle/service/ns/ns_language.h @@ -0,0 +1,42 @@ +// Copyright 2019 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once +#include <optional> +#include <string> +#include "common/common_types.h" +#include "core/hle/service/set/set.h" + +namespace Service::NS { +/// This is nn::ns::detail::ApplicationLanguage +enum class ApplicationLanguage : u8 { +    AmericanEnglish = 0, +    BritishEnglish, +    Japanese, +    French, +    German, +    LatinAmericanSpanish, +    Spanish, +    Italian, +    Dutch, +    CanadianFrench, +    Portuguese, +    Russian, +    Korean, +    TraditionalChinese, +    SimplifiedChinese, +    Count +}; +using ApplicationLanguagePriorityList = +    const std::array<ApplicationLanguage, static_cast<std::size_t>(ApplicationLanguage::Count)>; + +constexpr u32 GetSupportedLanguageFlag(const ApplicationLanguage lang) { +    return 1U << static_cast<u32>(lang); +} + +const ApplicationLanguagePriorityList* GetApplicationLanguagePriorityList(ApplicationLanguage lang); +std::optional<ApplicationLanguage> ConvertToApplicationLanguage( +    Service::Set::LanguageCode language_code); +std::optional<Service::Set::LanguageCode> ConvertToLanguageCode(ApplicationLanguage lang); +} // namespace Service::NS
\ No newline at end of file diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp index 45812d238..0e28755bd 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.cpp @@ -185,7 +185,8 @@ u32 nvhost_ctrl_gpu::GetGpuTime(const std::vector<u8>& input, std::vector<u8>& o      IoctlGetGpuTime params{};      std::memcpy(¶ms, input.data(), input.size()); -    params.gpu_time = Core::Timing::cyclesToNs(Core::System::GetInstance().CoreTiming().GetTicks()); +    const auto ns = Core::Timing::CyclesToNs(Core::System::GetInstance().CoreTiming().GetTicks()); +    params.gpu_time = static_cast<u64_le>(ns.count());      std::memcpy(output.data(), ¶ms, output.size());      return 0;  } diff --git a/src/core/hle/service/time/time.cpp b/src/core/hle/service/time/time.cpp index aa115935d..346bad80d 100644 --- a/src/core/hle/service/time/time.cpp +++ b/src/core/hle/service/time/time.cpp @@ -108,8 +108,9 @@ private:          LOG_DEBUG(Service_Time, "called");          const auto& core_timing = Core::System::GetInstance().CoreTiming(); -        const SteadyClockTimePoint steady_clock_time_point{ -            Core::Timing::cyclesToMs(core_timing.GetTicks()) / 1000}; +        const auto ms = Core::Timing::CyclesToMs(core_timing.GetTicks()); +        const SteadyClockTimePoint steady_clock_time_point{static_cast<u64_le>(ms.count() / 1000), +                                                           {}};          IPC::ResponseBuilder rb{ctx, (sizeof(SteadyClockTimePoint) / 4) + 2};          rb.Push(RESULT_SUCCESS);          rb.PushRaw(steady_clock_time_point); @@ -284,8 +285,8 @@ void Module::Interface::GetClockSnapshot(Kernel::HLERequestContext& ctx) {      }      const auto& core_timing = Core::System::GetInstance().CoreTiming(); -    const SteadyClockTimePoint steady_clock_time_point{ -        Core::Timing::cyclesToMs(core_timing.GetTicks()) / 1000, {}}; +    const auto ms = Core::Timing::CyclesToMs(core_timing.GetTicks()); +    const SteadyClockTimePoint steady_clock_time_point{static_cast<u64_le>(ms.count() / 1000), {}};      CalendarTime calendar_time{};      calendar_time.year = tm->tm_year + 1900; diff --git a/src/core/loader/loader.h b/src/core/loader/loader.h index f7846db52..869406b75 100644 --- a/src/core/loader/loader.h +++ b/src/core/loader/loader.h @@ -154,17 +154,6 @@ public:      virtual LoadResult Load(Kernel::Process& process) = 0;      /** -     * Loads the system mode that this application needs. -     * This function defaults to 2 (96MB allocated to the application) if it can't read the -     * information. -     * @returns A pair with the optional system mode, and and the status. -     */ -    virtual std::pair<std::optional<u32>, ResultStatus> LoadKernelSystemMode() { -        // 96MB allocated to the application. -        return std::make_pair(2, ResultStatus::Success); -    } - -    /**       * Get the code (typically .code section) of the application       * @param buffer Reference to buffer to store data       * @return ResultStatus result of function diff --git a/src/core/telemetry_session.cpp b/src/core/telemetry_session.cpp index 4b17bada5..90d06830f 100644 --- a/src/core/telemetry_session.cpp +++ b/src/core/telemetry_session.cpp @@ -12,7 +12,6 @@  #include "common/file_util.h"  #include "common/logging/log.h" -#include "core/core.h"  #include "core/file_sys/control_metadata.h"  #include "core/file_sys/patch_manager.h"  #include "core/loader/loader.h" @@ -101,7 +100,30 @@ bool VerifyLogin(const std::string& username, const std::string& token) {  #endif  } -TelemetrySession::TelemetrySession() { +TelemetrySession::TelemetrySession() = default; + +TelemetrySession::~TelemetrySession() { +    // Log one-time session end information +    const s64 shutdown_time{std::chrono::duration_cast<std::chrono::milliseconds>( +                                std::chrono::system_clock::now().time_since_epoch()) +                                .count()}; +    AddField(Telemetry::FieldType::Session, "Shutdown_Time", shutdown_time); + +#ifdef ENABLE_WEB_SERVICE +    auto backend = std::make_unique<WebService::TelemetryJson>( +        Settings::values.web_api_url, Settings::values.yuzu_username, Settings::values.yuzu_token); +#else +    auto backend = std::make_unique<Telemetry::NullVisitor>(); +#endif + +    // Complete the session, submitting to the web service backend if necessary +    field_collection.Accept(*backend); +    if (Settings::values.enable_telemetry) { +        backend->Complete(); +    } +} + +void TelemetrySession::AddInitialInfo(Loader::AppLoader& app_loader) {      // Log one-time top-level information      AddField(Telemetry::FieldType::None, "TelemetryId", GetTelemetryId()); @@ -112,26 +134,28 @@ TelemetrySession::TelemetrySession() {      AddField(Telemetry::FieldType::Session, "Init_Time", init_time);      u64 program_id{}; -    const Loader::ResultStatus res{System::GetInstance().GetAppLoader().ReadProgramId(program_id)}; +    const Loader::ResultStatus res{app_loader.ReadProgramId(program_id)};      if (res == Loader::ResultStatus::Success) {          const std::string formatted_program_id{fmt::format("{:016X}", program_id)};          AddField(Telemetry::FieldType::Session, "ProgramId", formatted_program_id);          std::string name; -        System::GetInstance().GetAppLoader().ReadTitle(name); +        app_loader.ReadTitle(name);          if (name.empty()) {              auto [nacp, icon_file] = FileSys::PatchManager(program_id).GetControlMetadata(); -            if (nacp != nullptr) +            if (nacp != nullptr) {                  name = nacp->GetApplicationName(); +            }          } -        if (!name.empty()) +        if (!name.empty()) {              AddField(Telemetry::FieldType::Session, "ProgramName", name); +        }      }      AddField(Telemetry::FieldType::Session, "ProgramFormat", -             static_cast<u8>(System::GetInstance().GetAppLoader().GetFileType())); +             static_cast<u8>(app_loader.GetFileType()));      // Log application information      Telemetry::AppendBuildInfo(field_collection); @@ -162,27 +186,6 @@ TelemetrySession::TelemetrySession() {               Settings::values.use_docked_mode);  } -TelemetrySession::~TelemetrySession() { -    // Log one-time session end information -    const s64 shutdown_time{std::chrono::duration_cast<std::chrono::milliseconds>( -                                std::chrono::system_clock::now().time_since_epoch()) -                                .count()}; -    AddField(Telemetry::FieldType::Session, "Shutdown_Time", shutdown_time); - -#ifdef ENABLE_WEB_SERVICE -    auto backend = std::make_unique<WebService::TelemetryJson>( -        Settings::values.web_api_url, Settings::values.yuzu_username, Settings::values.yuzu_token); -#else -    auto backend = std::make_unique<Telemetry::NullVisitor>(); -#endif - -    // Complete the session, submitting to web service if necessary -    field_collection.Accept(*backend); -    if (Settings::values.enable_telemetry) -        backend->Complete(); -    backend = nullptr; -} -  bool TelemetrySession::SubmitTestcase() {  #ifdef ENABLE_WEB_SERVICE      auto backend = std::make_unique<WebService::TelemetryJson>( diff --git a/src/core/telemetry_session.h b/src/core/telemetry_session.h index cae5a45a0..17ac22377 100644 --- a/src/core/telemetry_session.h +++ b/src/core/telemetry_session.h @@ -4,10 +4,13 @@  #pragma once -#include <memory>  #include <string>  #include "common/telemetry.h" +namespace Loader { +class AppLoader; +} +  namespace Core {  /** @@ -15,11 +18,33 @@ namespace Core {   * session, logging any one-time fields. Interfaces with the telemetry backend used for submitting   * data to the web service. Submits session data on close.   */ -class TelemetrySession : NonCopyable { +class TelemetrySession {  public: -    TelemetrySession(); +    explicit TelemetrySession();      ~TelemetrySession(); +    TelemetrySession(const TelemetrySession&) = delete; +    TelemetrySession& operator=(const TelemetrySession&) = delete; + +    TelemetrySession(TelemetrySession&&) = delete; +    TelemetrySession& operator=(TelemetrySession&&) = delete; + +    /** +     * Adds the initial telemetry info necessary when starting up a title. +     * +     * This includes information such as: +     *   - Telemetry ID +     *   - Initialization time +     *   - Title ID +     *   - Title name +     *   - Title file format +     *   - Miscellaneous settings values. +     * +     * @param app_loader The application loader to use to retrieve +     *                   title-specific information. +     */ +    void AddInitialInfo(Loader::AppLoader& app_loader); +      /**       * Wrapper around the Telemetry::FieldCollection::AddField method.       * @param type Type of the field to add. diff --git a/src/input_common/sdl/sdl.h b/src/input_common/sdl/sdl.h index d7f24c68a..5306daa70 100644 --- a/src/input_common/sdl/sdl.h +++ b/src/input_common/sdl/sdl.h @@ -6,15 +6,8 @@  #include <memory>  #include <vector> -#include "core/frontend/input.h"  #include "input_common/main.h" -union SDL_Event; - -namespace Common { -class ParamPackage; -} // namespace Common -  namespace InputCommon::Polling {  class DevicePoller;  enum class DeviceType; diff --git a/src/input_common/sdl/sdl_impl.cpp b/src/input_common/sdl/sdl_impl.cpp index 0b69bfede..d2e9d278f 100644 --- a/src/input_common/sdl/sdl_impl.cpp +++ b/src/input_common/sdl/sdl_impl.cpp @@ -6,7 +6,6 @@  #include <atomic>  #include <cmath>  #include <functional> -#include <iterator>  #include <mutex>  #include <string>  #include <thread> @@ -15,7 +14,6 @@  #include <utility>  #include <vector>  #include <SDL.h> -#include "common/assert.h"  #include "common/logging/log.h"  #include "common/math_util.h"  #include "common/param_package.h" @@ -23,12 +21,10 @@  #include "core/frontend/input.h"  #include "input_common/sdl/sdl_impl.h" -namespace InputCommon { - -namespace SDL { +namespace InputCommon::SDL {  static std::string GetGUID(SDL_Joystick* joystick) { -    SDL_JoystickGUID guid = SDL_JoystickGetGUID(joystick); +    const SDL_JoystickGUID guid = SDL_JoystickGetGUID(joystick);      char guid_str[33];      SDL_JoystickGetGUIDString(guid, guid_str, sizeof(guid_str));      return guid_str; @@ -37,26 +33,27 @@ static std::string GetGUID(SDL_Joystick* joystick) {  /// Creates a ParamPackage from an SDL_Event that can directly be used to create a ButtonDevice  static Common::ParamPackage SDLEventToButtonParamPackage(SDLState& state, const SDL_Event& event); -static int SDLEventWatcher(void* userdata, SDL_Event* event) { -    SDLState* sdl_state = reinterpret_cast<SDLState*>(userdata); +static int SDLEventWatcher(void* user_data, SDL_Event* event) { +    auto* const sdl_state = static_cast<SDLState*>(user_data); +      // Don't handle the event if we are configuring      if (sdl_state->polling) {          sdl_state->event_queue.Push(*event);      } else {          sdl_state->HandleGameControllerEvent(*event);      } +      return 0;  }  class SDLJoystick {  public: -    SDLJoystick(std::string guid_, int port_, SDL_Joystick* joystick, -                decltype(&SDL_JoystickClose) deleter = &SDL_JoystickClose) -        : guid{std::move(guid_)}, port{port_}, sdl_joystick{joystick, deleter} {} +    SDLJoystick(std::string guid_, int port_, SDL_Joystick* joystick) +        : guid{std::move(guid_)}, port{port_}, sdl_joystick{joystick, &SDL_JoystickClose} {}      void SetButton(int button, bool value) {          std::lock_guard lock{mutex}; -        state.buttons[button] = value; +        state.buttons.insert_or_assign(button, value);      }      bool GetButton(int button) const { @@ -66,7 +63,7 @@ public:      void SetAxis(int axis, Sint16 value) {          std::lock_guard lock{mutex}; -        state.axes[axis] = value; +        state.axes.insert_or_assign(axis, value);      }      float GetAxis(int axis) const { @@ -93,7 +90,7 @@ public:      void SetHat(int hat, Uint8 direction) {          std::lock_guard lock{mutex}; -        state.hats[hat] = direction; +        state.hats.insert_or_assign(hat, direction);      }      bool GetHatDirection(int hat, Uint8 direction) const { @@ -118,10 +115,8 @@ public:          return sdl_joystick.get();      } -    void SetSDLJoystick(SDL_Joystick* joystick, -                        decltype(&SDL_JoystickClose) deleter = &SDL_JoystickClose) { -        sdl_joystick = -            std::unique_ptr<SDL_Joystick, decltype(&SDL_JoystickClose)>(joystick, deleter); +    void SetSDLJoystick(SDL_Joystick* joystick) { +        sdl_joystick.reset(joystick);      }  private: @@ -136,59 +131,57 @@ private:      mutable std::mutex mutex;  }; -/** - * Get the nth joystick with the corresponding GUID - */  std::shared_ptr<SDLJoystick> SDLState::GetSDLJoystickByGUID(const std::string& guid, int port) {      std::lock_guard lock{joystick_map_mutex};      const auto it = joystick_map.find(guid);      if (it != joystick_map.end()) {          while (it->second.size() <= static_cast<std::size_t>(port)) { -            auto joystick = std::make_shared<SDLJoystick>(guid, static_cast<int>(it->second.size()), -                                                          nullptr, [](SDL_Joystick*) {}); +            auto joystick = +                std::make_shared<SDLJoystick>(guid, static_cast<int>(it->second.size()), nullptr);              it->second.emplace_back(std::move(joystick));          }          return it->second[port];      } -    auto joystick = std::make_shared<SDLJoystick>(guid, 0, nullptr, [](SDL_Joystick*) {}); +    auto joystick = std::make_shared<SDLJoystick>(guid, 0, nullptr);      return joystick_map[guid].emplace_back(std::move(joystick));  } -/** - * Check how many identical joysticks (by guid) were connected before the one with sdl_id and so tie - * it to a SDLJoystick with the same guid and that port - */  std::shared_ptr<SDLJoystick> SDLState::GetSDLJoystickBySDLID(SDL_JoystickID sdl_id) {      auto sdl_joystick = SDL_JoystickFromInstanceID(sdl_id);      const std::string guid = GetGUID(sdl_joystick);      std::lock_guard lock{joystick_map_mutex}; -    auto map_it = joystick_map.find(guid); +    const auto map_it = joystick_map.find(guid);      if (map_it != joystick_map.end()) { -        auto vec_it = std::find_if(map_it->second.begin(), map_it->second.end(), -                                   [&sdl_joystick](const std::shared_ptr<SDLJoystick>& joystick) { -                                       return sdl_joystick == joystick->GetSDLJoystick(); -                                   }); +        const auto vec_it = +            std::find_if(map_it->second.begin(), map_it->second.end(), +                         [&sdl_joystick](const std::shared_ptr<SDLJoystick>& joystick) { +                             return sdl_joystick == joystick->GetSDLJoystick(); +                         });          if (vec_it != map_it->second.end()) {              // This is the common case: There is already an existing SDL_Joystick maped to a              // SDLJoystick. return the SDLJoystick              return *vec_it;          } +          // Search for a SDLJoystick without a mapped SDL_Joystick... -        auto nullptr_it = std::find_if(map_it->second.begin(), map_it->second.end(), -                                       [](const std::shared_ptr<SDLJoystick>& joystick) { -                                           return !joystick->GetSDLJoystick(); -                                       }); +        const auto nullptr_it = std::find_if(map_it->second.begin(), map_it->second.end(), +                                             [](const std::shared_ptr<SDLJoystick>& joystick) { +                                                 return !joystick->GetSDLJoystick(); +                                             });          if (nullptr_it != map_it->second.end()) {              // ... and map it              (*nullptr_it)->SetSDLJoystick(sdl_joystick);              return *nullptr_it;          } +          // There is no SDLJoystick without a mapped SDL_Joystick          // Create a new SDLJoystick -        auto joystick = std::make_shared<SDLJoystick>(guid, map_it->second.size(), sdl_joystick); +        const int port = static_cast<int>(map_it->second.size()); +        auto joystick = std::make_shared<SDLJoystick>(guid, port, sdl_joystick);          return map_it->second.emplace_back(std::move(joystick));      } +      auto joystick = std::make_shared<SDLJoystick>(guid, 0, sdl_joystick);      return joystick_map[guid].emplace_back(std::move(joystick));  } @@ -215,17 +208,19 @@ void SDLState::InitJoystick(int joystick_index) {          (*it)->SetSDLJoystick(sdl_joystick);          return;      } -    auto joystick = std::make_shared<SDLJoystick>(guid, joystick_guid_list.size(), sdl_joystick); +    const int port = static_cast<int>(joystick_guid_list.size()); +    auto joystick = std::make_shared<SDLJoystick>(guid, port, sdl_joystick);      joystick_guid_list.emplace_back(std::move(joystick));  }  void SDLState::CloseJoystick(SDL_Joystick* sdl_joystick) { -    std::string guid = GetGUID(sdl_joystick); +    const std::string guid = GetGUID(sdl_joystick); +      std::shared_ptr<SDLJoystick> joystick;      {          std::lock_guard lock{joystick_map_mutex};          // This call to guid is safe since the joystick is guaranteed to be in the map -        auto& joystick_guid_list = joystick_map[guid]; +        const auto& joystick_guid_list = joystick_map[guid];          const auto joystick_it =              std::find_if(joystick_guid_list.begin(), joystick_guid_list.end(),                           [&sdl_joystick](const std::shared_ptr<SDLJoystick>& joystick) { @@ -233,9 +228,10 @@ void SDLState::CloseJoystick(SDL_Joystick* sdl_joystick) {                           });          joystick = *joystick_it;      } -    // Destruct SDL_Joystick outside the lock guard because SDL can internally call event calback -    // which locks the mutex again -    joystick->SetSDLJoystick(nullptr, [](SDL_Joystick*) {}); + +    // Destruct SDL_Joystick outside the lock guard because SDL can internally call the +    // event callback which locks the mutex again. +    joystick->SetSDLJoystick(nullptr);  }  void SDLState::HandleGameControllerEvent(const SDL_Event& event) { @@ -317,9 +313,10 @@ public:            trigger_if_greater(trigger_if_greater_) {}      bool GetStatus() const override { -        float axis_value = joystick->GetAxis(axis); -        if (trigger_if_greater) +        const float axis_value = joystick->GetAxis(axis); +        if (trigger_if_greater) {              return axis_value > threshold; +        }          return axis_value < threshold;      } @@ -444,7 +441,7 @@ public:          const int port = params.Get("port", 0);          const int axis_x = params.Get("axis_x", 0);          const int axis_y = params.Get("axis_y", 1); -        float deadzone = std::clamp(params.Get("deadzone", 0.0f), 0.0f, .99f); +        const float deadzone = std::clamp(params.Get("deadzone", 0.0f), 0.0f, .99f);          auto joystick = state.GetSDLJoystickByGUID(guid, port); @@ -470,7 +467,7 @@ SDLState::SDLState() {          return;      }      if (SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1") == SDL_FALSE) { -        LOG_ERROR(Input, "Failed to set Hint for background events", SDL_GetError()); +        LOG_ERROR(Input, "Failed to set hint for background events with: {}", SDL_GetError());      }      SDL_AddEventWatch(&SDLEventWatcher, this); @@ -507,12 +504,12 @@ SDLState::~SDLState() {      }  } -Common::ParamPackage SDLEventToButtonParamPackage(SDLState& state, const SDL_Event& event) { +static Common::ParamPackage SDLEventToButtonParamPackage(SDLState& state, const SDL_Event& event) {      Common::ParamPackage params({{"engine", "sdl"}});      switch (event.type) {      case SDL_JOYAXISMOTION: { -        auto joystick = state.GetSDLJoystickBySDLID(event.jaxis.which); +        const auto joystick = state.GetSDLJoystickBySDLID(event.jaxis.which);          params.Set("port", joystick->GetPort());          params.Set("guid", joystick->GetGUID());          params.Set("axis", event.jaxis.axis); @@ -526,14 +523,14 @@ Common::ParamPackage SDLEventToButtonParamPackage(SDLState& state, const SDL_Eve          break;      }      case SDL_JOYBUTTONUP: { -        auto joystick = state.GetSDLJoystickBySDLID(event.jbutton.which); +        const auto joystick = state.GetSDLJoystickBySDLID(event.jbutton.which);          params.Set("port", joystick->GetPort());          params.Set("guid", joystick->GetGUID());          params.Set("button", event.jbutton.button);          break;      }      case SDL_JOYHATMOTION: { -        auto joystick = state.GetSDLJoystickBySDLID(event.jhat.which); +        const auto joystick = state.GetSDLJoystickBySDLID(event.jhat.which);          params.Set("port", joystick->GetPort());          params.Set("guid", joystick->GetGUID());          params.Set("hat", event.jhat.hat); @@ -607,8 +604,8 @@ public:          SDLPoller::Start();          // Reset stored axes -        analog_xaxis = -1; -        analog_yaxis = -1; +        analog_x_axis = -1; +        analog_y_axis = -1;          analog_axes_joystick = -1;      } @@ -620,25 +617,25 @@ public:              }              // An analog device needs two axes, so we need to store the axis for later and wait for              // a second SDL event. The axes also must be from the same joystick. -            int axis = event.jaxis.axis; -            if (analog_xaxis == -1) { -                analog_xaxis = axis; +            const int axis = event.jaxis.axis; +            if (analog_x_axis == -1) { +                analog_x_axis = axis;                  analog_axes_joystick = event.jaxis.which; -            } else if (analog_yaxis == -1 && analog_xaxis != axis && +            } else if (analog_y_axis == -1 && analog_x_axis != axis &&                         analog_axes_joystick == event.jaxis.which) { -                analog_yaxis = axis; +                analog_y_axis = axis;              }          }          Common::ParamPackage params; -        if (analog_xaxis != -1 && analog_yaxis != -1) { -            auto joystick = state.GetSDLJoystickBySDLID(event.jaxis.which); +        if (analog_x_axis != -1 && analog_y_axis != -1) { +            const auto joystick = state.GetSDLJoystickBySDLID(event.jaxis.which);              params.Set("engine", "sdl");              params.Set("port", joystick->GetPort());              params.Set("guid", joystick->GetGUID()); -            params.Set("axis_x", analog_xaxis); -            params.Set("axis_y", analog_yaxis); -            analog_xaxis = -1; -            analog_yaxis = -1; +            params.Set("axis_x", analog_x_axis); +            params.Set("axis_y", analog_y_axis); +            analog_x_axis = -1; +            analog_y_axis = -1;              analog_axes_joystick = -1;              return params;          } @@ -646,8 +643,8 @@ public:      }  private: -    int analog_xaxis = -1; -    int analog_yaxis = -1; +    int analog_x_axis = -1; +    int analog_y_axis = -1;      SDL_JoystickID analog_axes_joystick = -1;  };  } // namespace Polling @@ -667,5 +664,4 @@ SDLState::Pollers SDLState::GetPollers(InputCommon::Polling::DeviceType type) {      return pollers;  } -} // namespace SDL -} // namespace InputCommon +} // namespace InputCommon::SDL diff --git a/src/input_common/sdl/sdl_impl.h b/src/input_common/sdl/sdl_impl.h index 2579741d6..606a32c5b 100644 --- a/src/input_common/sdl/sdl_impl.h +++ b/src/input_common/sdl/sdl_impl.h @@ -6,7 +6,10 @@  #include <atomic>  #include <memory> +#include <mutex>  #include <thread> +#include <unordered_map> +#include "common/common_types.h"  #include "common/threadsafe_queue.h"  #include "input_common/sdl/sdl.h" @@ -16,9 +19,9 @@ using SDL_JoystickID = s32;  namespace InputCommon::SDL { -class SDLJoystick; -class SDLButtonFactory;  class SDLAnalogFactory; +class SDLButtonFactory; +class SDLJoystick;  class SDLState : public State {  public: @@ -31,7 +34,13 @@ public:      /// Handle SDL_Events for joysticks from SDL_PollEvent      void HandleGameControllerEvent(const SDL_Event& event); +    /// Get the nth joystick with the corresponding GUID      std::shared_ptr<SDLJoystick> GetSDLJoystickBySDLID(SDL_JoystickID sdl_id); + +    /** +     * Check how many identical joysticks (by guid) were connected before the one with sdl_id and so +     * tie it to a SDLJoystick with the same guid and that port +     */      std::shared_ptr<SDLJoystick> GetSDLJoystickByGUID(const std::string& guid, int port);      /// Get all DevicePoller that use the SDL backend for a specific device type diff --git a/src/video_core/gpu_thread.cpp b/src/video_core/gpu_thread.cpp index 1e2ff46b0..3f0939ec9 100644 --- a/src/video_core/gpu_thread.cpp +++ b/src/video_core/gpu_thread.cpp @@ -75,7 +75,7 @@ void ThreadManager::StartThread(VideoCore::RendererBase& renderer, Tegra::DmaPus  void ThreadManager::SubmitList(Tegra::CommandList&& entries) {      const u64 fence{PushCommand(SubmitListCommand(std::move(entries)))}; -    const s64 synchronization_ticks{Core::Timing::usToCycles(9000)}; +    const s64 synchronization_ticks{Core::Timing::usToCycles(std::chrono::microseconds{9000})};      system.CoreTiming().ScheduleEvent(synchronization_ticks, synchronization_event, fence);  } diff --git a/src/video_core/renderer_opengl/gl_device.cpp b/src/video_core/renderer_opengl/gl_device.cpp index 1d1581f49..65a88b06c 100644 --- a/src/video_core/renderer_opengl/gl_device.cpp +++ b/src/video_core/renderer_opengl/gl_device.cpp @@ -2,11 +2,14 @@  // Licensed under GPLv2 or any later version  // Refer to the license.txt file included. +#include <array>  #include <cstddef>  #include <glad/glad.h>  #include "common/logging/log.h" +#include "common/scope_exit.h"  #include "video_core/renderer_opengl/gl_device.h" +#include "video_core/renderer_opengl/gl_resource_manager.h"  namespace OpenGL { @@ -24,6 +27,7 @@ Device::Device() {      max_vertex_attributes = GetInteger<u32>(GL_MAX_VERTEX_ATTRIBS);      max_varyings = GetInteger<u32>(GL_MAX_VARYING_VECTORS);      has_variable_aoffi = TestVariableAoffi(); +    has_component_indexing_bug = TestComponentIndexingBug();  }  Device::Device(std::nullptr_t) { @@ -31,6 +35,7 @@ Device::Device(std::nullptr_t) {      max_vertex_attributes = 16;      max_varyings = 15;      has_variable_aoffi = true; +    has_component_indexing_bug = false;  }  bool Device::TestVariableAoffi() { @@ -52,4 +57,53 @@ void main() {      return supported;  } +bool Device::TestComponentIndexingBug() { +    constexpr char log_message[] = "Renderer_ComponentIndexingBug: {}"; +    const GLchar* COMPONENT_TEST = R"(#version 430 core +layout (std430, binding = 0) buffer OutputBuffer { +    uint output_value; +}; +layout (std140, binding = 0) uniform InputBuffer { +    uvec4 input_value[4096]; +}; +layout (location = 0) uniform uint idx; +void main() { +    output_value = input_value[idx >> 2][idx & 3]; +})"; +    const GLuint shader{glCreateShaderProgramv(GL_VERTEX_SHADER, 1, &COMPONENT_TEST)}; +    SCOPE_EXIT({ glDeleteProgram(shader); }); +    glUseProgram(shader); + +    OGLVertexArray vao; +    vao.Create(); +    glBindVertexArray(vao.handle); + +    constexpr std::array<GLuint, 8> values{0, 0, 0, 0, 0x1236327, 0x985482, 0x872753, 0x2378432}; +    OGLBuffer ubo; +    ubo.Create(); +    glNamedBufferData(ubo.handle, sizeof(values), values.data(), GL_STATIC_DRAW); +    glBindBufferBase(GL_UNIFORM_BUFFER, 0, ubo.handle); + +    OGLBuffer ssbo; +    ssbo.Create(); +    glNamedBufferStorage(ssbo.handle, sizeof(GLuint), nullptr, GL_CLIENT_STORAGE_BIT); + +    for (GLuint index = 4; index < 8; ++index) { +        glInvalidateBufferData(ssbo.handle); +        glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, ssbo.handle); + +        glProgramUniform1ui(shader, 0, index); +        glDrawArrays(GL_POINTS, 0, 1); + +        GLuint result; +        glGetNamedBufferSubData(ssbo.handle, 0, sizeof(result), &result); +        if (result != values.at(index)) { +            LOG_INFO(Render_OpenGL, log_message, true); +            return true; +        } +    } +    LOG_INFO(Render_OpenGL, log_message, false); +    return false; +} +  } // namespace OpenGL diff --git a/src/video_core/renderer_opengl/gl_device.h b/src/video_core/renderer_opengl/gl_device.h index de8490682..8c8c93760 100644 --- a/src/video_core/renderer_opengl/gl_device.h +++ b/src/video_core/renderer_opengl/gl_device.h @@ -30,13 +30,19 @@ public:          return has_variable_aoffi;      } +    bool HasComponentIndexingBug() const { +        return has_component_indexing_bug; +    } +  private:      static bool TestVariableAoffi(); +    static bool TestComponentIndexingBug();      std::size_t uniform_buffer_alignment{};      u32 max_vertex_attributes{};      u32 max_varyings{};      bool has_variable_aoffi{}; +    bool has_component_indexing_bug{};  };  } // namespace OpenGL diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index e9f8d40db..3b61bf77f 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp @@ -577,9 +577,26 @@ private:              if (std::holds_alternative<OperationNode>(*offset)) {                  // Indirect access                  const std::string final_offset = code.GenerateTemporary(); -                code.AddLine("uint {} = (ftou({}) / 4);", final_offset, Visit(offset)); -                return fmt::format("{}[{} / 4][{} % 4]", GetConstBuffer(cbuf->GetIndex()), -                                   final_offset, final_offset); +                code.AddLine("uint {} = ftou({}) >> 2;", final_offset, Visit(offset)); + +                if (!device.HasComponentIndexingBug()) { +                    return fmt::format("{}[{} >> 2][{} & 3]", GetConstBuffer(cbuf->GetIndex()), +                                       final_offset, final_offset); +                } + +                // AMD's proprietary GLSL compiler emits ill code for variable component access. +                // To bypass this driver bug generate 4 ifs, one per each component. +                const std::string pack = code.GenerateTemporary(); +                code.AddLine("vec4 {} = {}[{} >> 2];", pack, GetConstBuffer(cbuf->GetIndex()), +                             final_offset); + +                const std::string result = code.GenerateTemporary(); +                code.AddLine("float {};", result); +                for (u32 swizzle = 0; swizzle < 4; ++swizzle) { +                    code.AddLine("if (({} & 3) == {}) {} = {}{};", final_offset, swizzle, result, +                                 pack, GetSwizzle(swizzle)); +                } +                return result;              }              UNREACHABLE_MSG("Unmanaged offset node type"); diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index d2258a487..cd32623b4 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -847,11 +847,6 @@ bool GMainWindow::LoadROM(const QString& filename) {              QMessageBox::critical(this, tr("Error while loading ROM!"),                                    tr("The ROM format is not supported."));              break; -        case Core::System::ResultStatus::ErrorSystemMode: -            LOG_CRITICAL(Frontend, "Failed to load ROM!"); -            QMessageBox::critical(this, tr("Error while loading ROM!"), -                                  tr("Could not determine the system mode.")); -            break;          case Core::System::ResultStatus::ErrorVideoCore:              QMessageBox::critical(                  this, tr("An error occurred initializing the video core."), diff --git a/src/yuzu_cmd/yuzu.cpp b/src/yuzu_cmd/yuzu.cpp index 5d9442646..129d8ca73 100644 --- a/src/yuzu_cmd/yuzu.cpp +++ b/src/yuzu_cmd/yuzu.cpp @@ -192,7 +192,7 @@ int main(int argc, char** argv) {      switch (load_result) {      case Core::System::ResultStatus::ErrorGetLoader: -        LOG_CRITICAL(Frontend, "Failed to obtain loader for %s!", filepath.c_str()); +        LOG_CRITICAL(Frontend, "Failed to obtain loader for {}!", filepath);          return -1;      case Core::System::ResultStatus::ErrorLoader:          LOG_CRITICAL(Frontend, "Failed to load ROM!"); @@ -200,9 +200,6 @@ int main(int argc, char** argv) {      case Core::System::ResultStatus::ErrorNotInitialized:          LOG_CRITICAL(Frontend, "CPUCore not initialized");          return -1; -    case Core::System::ResultStatus::ErrorSystemMode: -        LOG_CRITICAL(Frontend, "Failed to determine system mode!"); -        return -1;      case Core::System::ResultStatus::ErrorVideoCore:          LOG_CRITICAL(Frontend, "Failed to initialize VideoCore!");          return -1;  | 
