diff options
Diffstat (limited to 'src/core/hle/service')
31 files changed, 1413 insertions, 514 deletions
diff --git a/src/core/hle/service/acc/acc.cpp b/src/core/hle/service/acc/acc.cpp index 86bf53d08..025714e5a 100644 --- a/src/core/hle/service/acc/acc.cpp +++ b/src/core/hle/service/acc/acc.cpp @@ -10,30 +10,22 @@ #include "common/logging/log.h" #include "common/string_util.h" #include "common/swap.h" +#include "core/constants.h" #include "core/core_timing.h" +#include "core/file_sys/control_metadata.h" +#include "core/file_sys/patch_manager.h" #include "core/hle/ipc_helpers.h" +#include "core/hle/kernel/process.h" #include "core/hle/service/acc/acc.h" #include "core/hle/service/acc/acc_aa.h" #include "core/hle/service/acc/acc_su.h" #include "core/hle/service/acc/acc_u0.h" #include "core/hle/service/acc/acc_u1.h" #include "core/hle/service/acc/profile_manager.h" +#include "core/loader/loader.h" namespace Service::Account { -// Smallest JPEG https://github.com/mathiasbynens/small/blob/master/jpeg.jpg -// used as a backup should the one on disk not exist -constexpr u32 backup_jpeg_size = 107; -constexpr std::array<u8, backup_jpeg_size> backup_jpeg{{ - 0xff, 0xd8, 0xff, 0xdb, 0x00, 0x43, 0x00, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x02, 0x02, - 0x02, 0x03, 0x03, 0x03, 0x03, 0x04, 0x06, 0x04, 0x04, 0x04, 0x04, 0x04, 0x08, 0x06, 0x06, 0x05, - 0x06, 0x09, 0x08, 0x0a, 0x0a, 0x09, 0x08, 0x09, 0x09, 0x0a, 0x0c, 0x0f, 0x0c, 0x0a, 0x0b, 0x0e, - 0x0b, 0x09, 0x09, 0x0d, 0x11, 0x0d, 0x0e, 0x0f, 0x10, 0x10, 0x11, 0x10, 0x0a, 0x0c, 0x12, 0x13, - 0x12, 0x10, 0x13, 0x0f, 0x10, 0x10, 0x10, 0xff, 0xc9, 0x00, 0x0b, 0x08, 0x00, 0x01, 0x00, 0x01, - 0x01, 0x01, 0x11, 0x00, 0xff, 0xcc, 0x00, 0x06, 0x00, 0x10, 0x10, 0x05, 0xff, 0xda, 0x00, 0x08, - 0x01, 0x01, 0x00, 0x00, 0x3f, 0x00, 0xd2, 0xcf, 0x20, 0xff, 0xd9, -}}; - static std::string GetImagePath(Common::UUID uuid) { return FileUtil::GetUserPath(FileUtil::UserPath::NANDDir) + "/system/save/8000000000000010/su/avators/" + uuid.FormatSwitch() + ".jpg"; @@ -101,8 +93,8 @@ private: if (!image.IsOpen()) { LOG_WARNING(Service_ACC, "Failed to load user provided image! Falling back to built-in backup..."); - ctx.WriteBuffer(backup_jpeg); - rb.Push<u32>(backup_jpeg_size); + ctx.WriteBuffer(Core::Constants::ACCOUNT_BACKUP_JPEG); + rb.Push<u32>(Core::Constants::ACCOUNT_BACKUP_JPEG.size()); return; } @@ -124,7 +116,7 @@ private: if (!image.IsOpen()) { LOG_WARNING(Service_ACC, "Failed to load user provided image! Falling back to built-in backup..."); - rb.Push<u32>(backup_jpeg_size); + rb.Push<u32>(Core::Constants::ACCOUNT_BACKUP_JPEG.size()); } else { rb.Push<u32>(SanitizeJPEGSize(image.GetSize())); } @@ -225,7 +217,7 @@ void Module::Interface::IsUserRegistrationRequestPermitted(Kernel::HLERequestCon rb.Push(profile_manager->CanSystemRegisterUser()); } -void Module::Interface::InitializeApplicationInfo(Kernel::HLERequestContext& ctx) { +void Module::Interface::InitializeApplicationInfoOld(Kernel::HLERequestContext& ctx) { LOG_WARNING(Service_ACC, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); @@ -238,6 +230,31 @@ void Module::Interface::GetBaasAccountManagerForApplication(Kernel::HLERequestCo rb.PushIpcInterface<IManagerForApplication>(); } +void Module::Interface::IsUserAccountSwitchLocked(Kernel::HLERequestContext& ctx) { + LOG_DEBUG(Service_ACC, "called"); + FileSys::NACP nacp; + const auto res = system.GetAppLoader().ReadControlData(nacp); + + bool is_locked = false; + + if (res != Loader::ResultStatus::Success) { + FileSys::PatchManager pm{system.CurrentProcess()->GetTitleID()}; + auto nacp_unique = pm.GetControlMetadata().first; + + if (nacp_unique != nullptr) { + is_locked = nacp_unique->GetUserAccountSwitchLock(); + } else { + LOG_ERROR(Service_ACC, "nacp_unique is null!"); + } + } else { + is_locked = nacp.GetUserAccountSwitchLock(); + } + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(RESULT_SUCCESS); + rb.Push(is_locked); +} + void Module::Interface::TrySelectUserWithoutInteraction(Kernel::HLERequestContext& ctx) { LOG_DEBUG(Service_ACC, "called"); // A u8 is passed into this function which we can safely ignore. It's to determine if we have @@ -263,19 +280,25 @@ void Module::Interface::TrySelectUserWithoutInteraction(Kernel::HLERequestContex } Module::Interface::Interface(std::shared_ptr<Module> module, - std::shared_ptr<ProfileManager> profile_manager, const char* name) + std::shared_ptr<ProfileManager> profile_manager, Core::System& system, + const char* name) : ServiceFramework(name), module(std::move(module)), - profile_manager(std::move(profile_manager)) {} + profile_manager(std::move(profile_manager)), system(system) {} Module::Interface::~Interface() = default; -void InstallInterfaces(SM::ServiceManager& service_manager) { +void InstallInterfaces(Core::System& system) { auto module = std::make_shared<Module>(); auto profile_manager = std::make_shared<ProfileManager>(); - std::make_shared<ACC_AA>(module, profile_manager)->InstallAsService(service_manager); - std::make_shared<ACC_SU>(module, profile_manager)->InstallAsService(service_manager); - std::make_shared<ACC_U0>(module, profile_manager)->InstallAsService(service_manager); - std::make_shared<ACC_U1>(module, profile_manager)->InstallAsService(service_manager); + + std::make_shared<ACC_AA>(module, profile_manager, system) + ->InstallAsService(system.ServiceManager()); + std::make_shared<ACC_SU>(module, profile_manager, system) + ->InstallAsService(system.ServiceManager()); + std::make_shared<ACC_U0>(module, profile_manager, system) + ->InstallAsService(system.ServiceManager()); + std::make_shared<ACC_U1>(module, profile_manager, system) + ->InstallAsService(system.ServiceManager()); } } // namespace Service::Account diff --git a/src/core/hle/service/acc/acc.h b/src/core/hle/service/acc/acc.h index 89b2104fa..350f123a0 100644 --- a/src/core/hle/service/acc/acc.h +++ b/src/core/hle/service/acc/acc.h @@ -15,7 +15,8 @@ public: class Interface : public ServiceFramework<Interface> { public: explicit Interface(std::shared_ptr<Module> module, - std::shared_ptr<ProfileManager> profile_manager, const char* name); + std::shared_ptr<ProfileManager> profile_manager, Core::System& system, + const char* name); ~Interface() override; void GetUserCount(Kernel::HLERequestContext& ctx); @@ -24,18 +25,20 @@ public: void ListOpenUsers(Kernel::HLERequestContext& ctx); void GetLastOpenedUser(Kernel::HLERequestContext& ctx); void GetProfile(Kernel::HLERequestContext& ctx); - void InitializeApplicationInfo(Kernel::HLERequestContext& ctx); + void InitializeApplicationInfoOld(Kernel::HLERequestContext& ctx); void GetBaasAccountManagerForApplication(Kernel::HLERequestContext& ctx); void IsUserRegistrationRequestPermitted(Kernel::HLERequestContext& ctx); void TrySelectUserWithoutInteraction(Kernel::HLERequestContext& ctx); + void IsUserAccountSwitchLocked(Kernel::HLERequestContext& ctx); protected: std::shared_ptr<Module> module; std::shared_ptr<ProfileManager> profile_manager; + Core::System& system; }; }; /// Registers all ACC services with the specified service manager. -void InstallInterfaces(SM::ServiceManager& service_manager); +void InstallInterfaces(Core::System& system); } // namespace Service::Account diff --git a/src/core/hle/service/acc/acc_aa.cpp b/src/core/hle/service/acc/acc_aa.cpp index e84d9f7cf..3bac6bcd1 100644 --- a/src/core/hle/service/acc/acc_aa.cpp +++ b/src/core/hle/service/acc/acc_aa.cpp @@ -6,8 +6,9 @@ namespace Service::Account { -ACC_AA::ACC_AA(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> profile_manager) - : Module::Interface(std::move(module), std::move(profile_manager), "acc:aa") { +ACC_AA::ACC_AA(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> profile_manager, + Core::System& system) + : Module::Interface(std::move(module), std::move(profile_manager), system, "acc:aa") { static const FunctionInfo functions[] = { {0, nullptr, "EnsureCacheAsync"}, {1, nullptr, "LoadCache"}, diff --git a/src/core/hle/service/acc/acc_aa.h b/src/core/hle/service/acc/acc_aa.h index 9edb0421b..932c04890 100644 --- a/src/core/hle/service/acc/acc_aa.h +++ b/src/core/hle/service/acc/acc_aa.h @@ -10,8 +10,8 @@ namespace Service::Account { class ACC_AA final : public Module::Interface { public: - explicit ACC_AA(std::shared_ptr<Module> module, - std::shared_ptr<ProfileManager> profile_manager); + explicit ACC_AA(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> profile_manager, + Core::System& system); ~ACC_AA() override; }; diff --git a/src/core/hle/service/acc/acc_su.cpp b/src/core/hle/service/acc/acc_su.cpp index d66233cad..1b7ec3ed0 100644 --- a/src/core/hle/service/acc/acc_su.cpp +++ b/src/core/hle/service/acc/acc_su.cpp @@ -6,8 +6,9 @@ namespace Service::Account { -ACC_SU::ACC_SU(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> profile_manager) - : Module::Interface(std::move(module), std::move(profile_manager), "acc:su") { +ACC_SU::ACC_SU(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> profile_manager, + Core::System& system) + : Module::Interface(std::move(module), std::move(profile_manager), system, "acc:su") { // clang-format off static const FunctionInfo functions[] = { {0, &ACC_SU::GetUserCount, "GetUserCount"}, diff --git a/src/core/hle/service/acc/acc_su.h b/src/core/hle/service/acc/acc_su.h index fcced063a..0a700d9bf 100644 --- a/src/core/hle/service/acc/acc_su.h +++ b/src/core/hle/service/acc/acc_su.h @@ -10,8 +10,8 @@ namespace Service::Account { class ACC_SU final : public Module::Interface { public: - explicit ACC_SU(std::shared_ptr<Module> module, - std::shared_ptr<ProfileManager> profile_manager); + explicit ACC_SU(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> profile_manager, + Core::System& system); ~ACC_SU() override; }; diff --git a/src/core/hle/service/acc/acc_u0.cpp b/src/core/hle/service/acc/acc_u0.cpp index 182f7c7e5..2f239e8c0 100644 --- a/src/core/hle/service/acc/acc_u0.cpp +++ b/src/core/hle/service/acc/acc_u0.cpp @@ -6,8 +6,9 @@ namespace Service::Account { -ACC_U0::ACC_U0(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> profile_manager) - : Module::Interface(std::move(module), std::move(profile_manager), "acc:u0") { +ACC_U0::ACC_U0(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> profile_manager, + Core::System& system) + : Module::Interface(std::move(module), std::move(profile_manager), system, "acc:u0") { // clang-format off static const FunctionInfo functions[] = { {0, &ACC_U0::GetUserCount, "GetUserCount"}, @@ -21,7 +22,7 @@ ACC_U0::ACC_U0(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> p {51, &ACC_U0::TrySelectUserWithoutInteraction, "TrySelectUserWithoutInteraction"}, {60, nullptr, "ListOpenContextStoredUsers"}, {99, nullptr, "DebugActivateOpenContextRetention"}, - {100, &ACC_U0::InitializeApplicationInfo, "InitializeApplicationInfo"}, + {100, &ACC_U0::InitializeApplicationInfoOld, "InitializeApplicationInfoOld"}, {101, &ACC_U0::GetBaasAccountManagerForApplication, "GetBaasAccountManagerForApplication"}, {102, nullptr, "AuthenticateApplicationAsync"}, {103, nullptr, "CheckNetworkServiceAvailabilityAsync"}, @@ -32,7 +33,7 @@ ACC_U0::ACC_U0(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> p {131, nullptr, "ListOpenContextStoredUsers"}, {140, nullptr, "InitializeApplicationInfo"}, {141, nullptr, "ListQualifiedUsers"}, - {150, nullptr, "IsUserAccountSwitchLocked"}, + {150, &ACC_U0::IsUserAccountSwitchLocked, "IsUserAccountSwitchLocked"}, }; // clang-format on diff --git a/src/core/hle/service/acc/acc_u0.h b/src/core/hle/service/acc/acc_u0.h index a1290e0bd..3bd9c3164 100644 --- a/src/core/hle/service/acc/acc_u0.h +++ b/src/core/hle/service/acc/acc_u0.h @@ -10,8 +10,8 @@ namespace Service::Account { class ACC_U0 final : public Module::Interface { public: - explicit ACC_U0(std::shared_ptr<Module> module, - std::shared_ptr<ProfileManager> profile_manager); + explicit ACC_U0(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> profile_manager, + Core::System& system); ~ACC_U0() override; }; diff --git a/src/core/hle/service/acc/acc_u1.cpp b/src/core/hle/service/acc/acc_u1.cpp index 2dd17d935..6520b3968 100644 --- a/src/core/hle/service/acc/acc_u1.cpp +++ b/src/core/hle/service/acc/acc_u1.cpp @@ -6,8 +6,9 @@ namespace Service::Account { -ACC_U1::ACC_U1(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> profile_manager) - : Module::Interface(std::move(module), std::move(profile_manager), "acc:u1") { +ACC_U1::ACC_U1(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> profile_manager, + Core::System& system) + : Module::Interface(std::move(module), std::move(profile_manager), system, "acc:u1") { // clang-format off static const FunctionInfo functions[] = { {0, &ACC_U1::GetUserCount, "GetUserCount"}, diff --git a/src/core/hle/service/acc/acc_u1.h b/src/core/hle/service/acc/acc_u1.h index 9e79daee3..829f8a744 100644 --- a/src/core/hle/service/acc/acc_u1.h +++ b/src/core/hle/service/acc/acc_u1.h @@ -10,8 +10,8 @@ namespace Service::Account { class ACC_U1 final : public Module::Interface { public: - explicit ACC_U1(std::shared_ptr<Module> module, - std::shared_ptr<ProfileManager> profile_manager); + explicit ACC_U1(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> profile_manager, + Core::System& system); ~ACC_U1() override; }; diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index 1a32a109f..4a7bf4acb 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" @@ -267,7 +271,7 @@ ISelfController::ISelfController(std::shared_ptr<NVFlinger::NVFlinger> nvflinger {71, nullptr, "GetCurrentIlluminanceEx"}, {80, nullptr, "SetWirelessPriorityMode"}, {90, nullptr, "GetAccumulatedSuspendedTickValue"}, - {91, nullptr, "GetAccumulatedSuspendedTickChangedEvent"}, + {91, &ISelfController::GetAccumulatedSuspendedTickChangedEvent, "GetAccumulatedSuspendedTickChangedEvent"}, {100, nullptr, "SetAlbumImageTakenNotificationEnabled"}, {1000, nullptr, "GetDebugStorageChannel"}, }; @@ -278,6 +282,11 @@ ISelfController::ISelfController(std::shared_ptr<NVFlinger::NVFlinger> nvflinger auto& kernel = Core::System::GetInstance().Kernel(); launchable_event = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Manual, "ISelfController:LaunchableEvent"); + + // TODO(ogniK): Figure out where, when and why this event gets signalled + accumulated_suspended_tick_changed_event = Kernel::WritableEvent::CreateEventPair( + kernel, Kernel::ResetType::Manual, "ISelfController:AccumulatedSuspendedTickChangedEvent"); + accumulated_suspended_tick_changed_event.writable->Signal(); // Is signalled on creation } ISelfController::~ISelfController() = default; @@ -440,6 +449,17 @@ void ISelfController::GetIdleTimeDetectionExtension(Kernel::HLERequestContext& c rb.Push<u32>(idle_time_detection_extension); } +void ISelfController::GetAccumulatedSuspendedTickChangedEvent(Kernel::HLERequestContext& ctx) { + // The implementation of this function is fine as is, the reason we're labelling it as stubbed + // is because we're currently unsure when and where accumulated_suspended_tick_changed_event is + // actually signalled for the time being. + LOG_WARNING(Service_AM, "(STUBBED) called"); + + IPC::ResponseBuilder rb{ctx, 2, 1}; + rb.Push(RESULT_SUCCESS); + rb.PushCopyObjects(accumulated_suspended_tick_changed_event.readable); +} + AppletMessageQueue::AppletMessageQueue() { auto& kernel = Core::System::GetInstance().Kernel(); on_new_message = Kernel::WritableEvent::CreateEventPair(kernel, Kernel::ResetType::Manual, @@ -1100,10 +1120,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/am.h b/src/core/hle/service/am/am.h index 991b7d47c..1fa069e56 100644 --- a/src/core/hle/service/am/am.h +++ b/src/core/hle/service/am/am.h @@ -133,9 +133,12 @@ private: void SetHandlesRequestToDisplay(Kernel::HLERequestContext& ctx); void SetIdleTimeDetectionExtension(Kernel::HLERequestContext& ctx); void GetIdleTimeDetectionExtension(Kernel::HLERequestContext& ctx); + void GetAccumulatedSuspendedTickChangedEvent(Kernel::HLERequestContext& ctx); std::shared_ptr<NVFlinger::NVFlinger> nvflinger; Kernel::EventPair launchable_event; + Kernel::EventPair accumulated_suspended_tick_changed_event; + u32 idle_time_detection_extension = 0; u64 num_fatal_sections_entered = 0; }; diff --git a/src/core/hle/service/am/applets/applets.cpp b/src/core/hle/service/am/applets/applets.cpp index e812c66e9..e3e4ead03 100644 --- a/src/core/hle/service/am/applets/applets.cpp +++ b/src/core/hle/service/am/applets/applets.cpp @@ -35,12 +35,28 @@ AppletDataBroker::AppletDataBroker() { AppletDataBroker::~AppletDataBroker() = default; +AppletDataBroker::RawChannelData AppletDataBroker::PeekDataToAppletForDebug() const { + std::vector<std::vector<u8>> out_normal; + + for (const auto& storage : in_channel) { + out_normal.push_back(storage->GetData()); + } + + std::vector<std::vector<u8>> out_interactive; + + for (const auto& storage : in_interactive_channel) { + out_interactive.push_back(storage->GetData()); + } + + return {std::move(out_normal), std::move(out_interactive)}; +} + std::unique_ptr<IStorage> AppletDataBroker::PopNormalDataToGame() { if (out_channel.empty()) return nullptr; auto out = std::move(out_channel.front()); - out_channel.pop(); + out_channel.pop_front(); return out; } @@ -49,7 +65,7 @@ std::unique_ptr<IStorage> AppletDataBroker::PopNormalDataToApplet() { return nullptr; auto out = std::move(in_channel.front()); - in_channel.pop(); + in_channel.pop_front(); return out; } @@ -58,7 +74,7 @@ std::unique_ptr<IStorage> AppletDataBroker::PopInteractiveDataToGame() { return nullptr; auto out = std::move(out_interactive_channel.front()); - out_interactive_channel.pop(); + out_interactive_channel.pop_front(); return out; } @@ -67,25 +83,25 @@ std::unique_ptr<IStorage> AppletDataBroker::PopInteractiveDataToApplet() { return nullptr; auto out = std::move(in_interactive_channel.front()); - in_interactive_channel.pop(); + in_interactive_channel.pop_front(); return out; } void AppletDataBroker::PushNormalDataFromGame(IStorage storage) { - in_channel.push(std::make_unique<IStorage>(storage)); + in_channel.push_back(std::make_unique<IStorage>(storage)); } void AppletDataBroker::PushNormalDataFromApplet(IStorage storage) { - out_channel.push(std::make_unique<IStorage>(storage)); + out_channel.push_back(std::make_unique<IStorage>(storage)); pop_out_data_event.writable->Signal(); } void AppletDataBroker::PushInteractiveDataFromGame(IStorage storage) { - in_interactive_channel.push(std::make_unique<IStorage>(storage)); + in_interactive_channel.push_back(std::make_unique<IStorage>(storage)); } void AppletDataBroker::PushInteractiveDataFromApplet(IStorage storage) { - out_interactive_channel.push(std::make_unique<IStorage>(storage)); + out_interactive_channel.push_back(std::make_unique<IStorage>(storage)); pop_interactive_out_data_event.writable->Signal(); } @@ -121,6 +137,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; @@ -189,7 +220,7 @@ std::shared_ptr<Applet> AppletManager::GetApplet(AppletId id) const { UNIMPLEMENTED_MSG( "No backend implementation exists for applet_id={:02X}! Falling back to stub applet.", static_cast<u8>(id)); - return std::make_shared<StubApplet>(); + return std::make_shared<StubApplet>(id); } } diff --git a/src/core/hle/service/am/applets/applets.h b/src/core/hle/service/am/applets/applets.h index 7f932672c..05ae739ca 100644 --- a/src/core/hle/service/am/applets/applets.h +++ b/src/core/hle/service/am/applets/applets.h @@ -54,6 +54,14 @@ public: AppletDataBroker(); ~AppletDataBroker(); + struct RawChannelData { + std::vector<std::vector<u8>> normal; + std::vector<std::vector<u8>> interactive; + }; + + // Retrieves but does not pop the data sent to applet. + RawChannelData PeekDataToAppletForDebug() const; + std::unique_ptr<IStorage> PopNormalDataToGame(); std::unique_ptr<IStorage> PopNormalDataToApplet(); @@ -76,16 +84,16 @@ private: // Queues are named from applet's perspective // PopNormalDataToApplet and PushNormalDataFromGame - std::queue<std::unique_ptr<IStorage>> in_channel; + std::deque<std::unique_ptr<IStorage>> in_channel; // PopNormalDataToGame and PushNormalDataFromApplet - std::queue<std::unique_ptr<IStorage>> out_channel; + std::deque<std::unique_ptr<IStorage>> out_channel; // PopInteractiveDataToApplet and PushInteractiveDataFromGame - std::queue<std::unique_ptr<IStorage>> in_interactive_channel; + std::deque<std::unique_ptr<IStorage>> in_interactive_channel; // PopInteractiveDataToGame and PushInteractiveDataFromApplet - std::queue<std::unique_ptr<IStorage>> out_interactive_channel; + std::deque<std::unique_ptr<IStorage>> out_interactive_channel; Kernel::EventPair state_changed_event; @@ -137,11 +145,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/am/applets/error.cpp b/src/core/hle/service/am/applets/error.cpp index 04774bedc..af3a900f8 100644 --- a/src/core/hle/service/am/applets/error.cpp +++ b/src/core/hle/service/am/applets/error.cpp @@ -9,8 +9,10 @@ #include "common/string_util.h" #include "core/core.h" #include "core/frontend/applets/error.h" +#include "core/hle/kernel/process.h" #include "core/hle/service/am/am.h" #include "core/hle/service/am/applets/error.h" +#include "core/reporter.h" namespace Service::AM::Applets { @@ -143,9 +145,12 @@ void Error::Execute() { } const auto callback = [this] { DisplayCompleted(); }; + const auto title_id = Core::CurrentProcess()->GetTitleID(); + const auto& reporter{Core::System::GetInstance().GetReporter()}; switch (mode) { case ErrorAppletMode::ShowError: + reporter.SaveErrorReport(title_id, error_code); frontend.ShowError(error_code, callback); break; case ErrorAppletMode::ShowSystemError: @@ -156,14 +161,18 @@ void Error::Execute() { const auto& detail_text = system ? args->system_error.detail_text : args->application_error.detail_text; - frontend.ShowCustomErrorText( - error_code, - Common::StringFromFixedZeroTerminatedBuffer(main_text.data(), main_text.size()), - Common::StringFromFixedZeroTerminatedBuffer(detail_text.data(), detail_text.size()), - callback); + const auto main_text_string = + Common::StringFromFixedZeroTerminatedBuffer(main_text.data(), main_text.size()); + const auto detail_text_string = + Common::StringFromFixedZeroTerminatedBuffer(detail_text.data(), detail_text.size()); + + reporter.SaveErrorReport(title_id, error_code, main_text_string, detail_text_string); + frontend.ShowCustomErrorText(error_code, main_text_string, detail_text_string, callback); break; } case ErrorAppletMode::ShowErrorRecord: + reporter.SaveErrorReport(title_id, error_code, + fmt::format("{:016X}", args->error_record.posix_time)); frontend.ShowErrorWithTimestamp( error_code, std::chrono::seconds{args->error_record.posix_time}, callback); break; diff --git a/src/core/hle/service/am/applets/general_backend.cpp b/src/core/hle/service/am/applets/general_backend.cpp index c591b9ac2..54c155dd8 100644 --- a/src/core/hle/service/am/applets/general_backend.cpp +++ b/src/core/hle/service/am/applets/general_backend.cpp @@ -2,7 +2,7 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. -#include <string> +#include <string_view> #include "common/assert.h" #include "common/hex_util.h" @@ -13,24 +13,25 @@ #include "core/hle/result.h" #include "core/hle/service/am/am.h" #include "core/hle/service/am/applets/general_backend.h" +#include "core/reporter.h" namespace Service::AM::Applets { -static void LogCurrentStorage(AppletDataBroker& broker, std::string prefix) { +static void LogCurrentStorage(AppletDataBroker& broker, std::string_view prefix) { std::unique_ptr<IStorage> storage = broker.PopNormalDataToApplet(); for (; storage != nullptr; storage = broker.PopNormalDataToApplet()) { const auto data = storage->GetData(); LOG_INFO(Service_AM, - "called (STUBBED), during {} recieved normal data with size={:08X}, data={}", - prefix, data.size(), Common::HexVectorToString(data)); + "called (STUBBED), during {} received normal data with size={:08X}, data={}", + prefix, data.size(), Common::HexToString(data)); } storage = broker.PopInteractiveDataToApplet(); for (; storage != nullptr; storage = broker.PopInteractiveDataToApplet()) { const auto data = storage->GetData(); LOG_INFO(Service_AM, - "called (STUBBED), during {} recieved interactive data with size={:08X}, data={}", - prefix, data.size(), Common::HexVectorToString(data)); + "called (STUBBED), during {} received interactive data with size={:08X}, data={}", + prefix, data.size(), Common::HexToString(data)); } } @@ -83,13 +84,20 @@ void PhotoViewer::ViewFinished() { broker.SignalStateChanged(); } -StubApplet::StubApplet() = default; +StubApplet::StubApplet(AppletId id) : id(id) {} StubApplet::~StubApplet() = default; void StubApplet::Initialize() { LOG_WARNING(Service_AM, "called (STUBBED)"); Applet::Initialize(); + + const auto data = broker.PeekDataToAppletForDebug(); + Core::System::GetInstance().GetReporter().SaveUnimplementedAppletReport( + static_cast<u32>(id), common_args.arguments_version, common_args.library_version, + common_args.theme_color, common_args.play_startup_sound, common_args.system_tick, + data.normal, data.interactive); + LogCurrentStorage(broker, "Initialize"); } diff --git a/src/core/hle/service/am/applets/general_backend.h b/src/core/hle/service/am/applets/general_backend.h index 2dd255d7c..fb68a2543 100644 --- a/src/core/hle/service/am/applets/general_backend.h +++ b/src/core/hle/service/am/applets/general_backend.h @@ -34,7 +34,7 @@ private: class StubApplet final : public Applet { public: - StubApplet(); + explicit StubApplet(AppletId id); ~StubApplet() override; void Initialize() override; @@ -43,6 +43,9 @@ public: ResultCode GetStatus() const override; void ExecuteInteractive() override; void Execute() override; + +private: + AppletId id; }; } // namespace Service::AM::Applets diff --git a/src/core/hle/service/audio/audout_u.cpp b/src/core/hle/service/audio/audout_u.cpp index 6ba41b20a..7db6eb08d 100644 --- a/src/core/hle/service/audio/audout_u.cpp +++ b/src/core/hle/service/audio/audout_u.cpp @@ -58,8 +58,8 @@ public: {9, &IAudioOut::GetAudioOutBufferCount, "GetAudioOutBufferCount"}, {10, nullptr, "GetAudioOutPlayedSampleCount"}, {11, nullptr, "FlushAudioOutBuffers"}, - {12, nullptr, "SetAudioOutVolume"}, - {13, nullptr, "GetAudioOutVolume"}, + {12, &IAudioOut::SetAudioOutVolume, "SetAudioOutVolume"}, + {13, &IAudioOut::GetAudioOutVolume, "GetAudioOutVolume"}, }; // clang-format on RegisterHandlers(functions); @@ -183,6 +183,25 @@ private: rb.Push(static_cast<u32>(stream->GetQueueSize())); } + void SetAudioOutVolume(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const float volume = rp.Pop<float>(); + LOG_DEBUG(Service_Audio, "called, volume={}", volume); + + stream->SetVolume(volume); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + } + + void GetAudioOutVolume(Kernel::HLERequestContext& ctx) { + LOG_DEBUG(Service_Audio, "called"); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(RESULT_SUCCESS); + rb.Push(stream->GetVolume()); + } + AudioCore::AudioOut& audio_core; AudioCore::StreamPtr stream; std::string device_name; diff --git a/src/core/hle/service/fatal/fatal.cpp b/src/core/hle/service/fatal/fatal.cpp index 2c229bcad..fe49c2161 100644 --- a/src/core/hle/service/fatal/fatal.cpp +++ b/src/core/hle/service/fatal/fatal.cpp @@ -16,6 +16,7 @@ #include "core/hle/service/fatal/fatal.h" #include "core/hle/service/fatal/fatal_p.h" #include "core/hle/service/fatal/fatal_u.h" +#include "core/reporter.h" namespace Service::Fatal { @@ -100,27 +101,10 @@ static void GenerateErrorReport(ResultCode error_code, const FatalInfo& info) { LOG_ERROR(Service_Fatal, "{}", crash_report); - const std::string crashreport_dir = - FileUtil::GetUserPath(FileUtil::UserPath::LogDir) + "crash_logs"; - - if (!FileUtil::CreateFullPath(crashreport_dir)) { - LOG_ERROR( - Service_Fatal, - "Unable to create crash report directory. Possible log directory permissions issue."); - return; - } - - const std::time_t t = std::time(nullptr); - const std::string crashreport_filename = - fmt::format("{}/{:016x}-{:%F-%H%M%S}.log", crashreport_dir, title_id, *std::localtime(&t)); - - auto file = FileUtil::IOFile(crashreport_filename, "wb"); - if (file.IsOpen()) { - file.WriteString(crash_report); - LOG_ERROR(Service_Fatal, "Saving error report to {}", crashreport_filename); - } else { - LOG_ERROR(Service_Fatal, "Failed to save error report to {}", crashreport_filename); - } + Core::System::GetInstance().GetReporter().SaveCrashReport( + title_id, error_code, info.set_flags, info.program_entry_point, info.sp, info.pc, + info.pstate, info.afsr0, info.afsr1, info.esr, info.far, info.registers, info.backtrace, + info.backtrace_size, info.ArchAsString(), info.unk10); } static void ThrowFatalError(ResultCode error_code, FatalType fatal_type, const FatalInfo& info) { diff --git a/src/core/hle/service/ldr/ldr.cpp b/src/core/hle/service/ldr/ldr.cpp index 5af925515..b839303ac 100644 --- a/src/core/hle/service/ldr/ldr.cpp +++ b/src/core/hle/service/ldr/ldr.cpp @@ -310,7 +310,7 @@ public: if (!IsValidNROHash(hash)) { LOG_ERROR(Service_LDR, "NRO hash is not present in any currently loaded NRRs (hash={})!", - Common::HexArrayToString(hash)); + Common::HexToString(hash)); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ERROR_MISSING_NRR_HASH); return; diff --git a/src/core/hle/service/ncm/ncm.cpp b/src/core/hle/service/ncm/ncm.cpp index 5d31f638f..b405a4b66 100644 --- a/src/core/hle/service/ncm/ncm.cpp +++ b/src/core/hle/service/ncm/ncm.cpp @@ -4,15 +4,89 @@ #include <memory> +#include "core/file_sys/romfs_factory.h" +#include "core/hle/ipc_helpers.h" #include "core/hle/service/ncm/ncm.h" #include "core/hle/service/service.h" #include "core/hle/service/sm/sm.h" namespace Service::NCM { -class LocationResolver final : public ServiceFramework<LocationResolver> { +class ILocationResolver final : public ServiceFramework<ILocationResolver> { public: - explicit LocationResolver() : ServiceFramework{"lr"} { + explicit ILocationResolver(FileSys::StorageId id) + : ServiceFramework{"ILocationResolver"}, storage(id) { + // clang-format off + static const FunctionInfo functions[] = { + {0, nullptr, "ResolveProgramPath"}, + {1, nullptr, "RedirectProgramPath"}, + {2, nullptr, "ResolveApplicationControlPath"}, + {3, nullptr, "ResolveApplicationHtmlDocumentPath"}, + {4, nullptr, "ResolveDataPath"}, + {5, nullptr, "RedirectApplicationControlPath"}, + {6, nullptr, "RedirectApplicationHtmlDocumentPath"}, + {7, nullptr, "ResolveApplicationLegalInformationPath"}, + {8, nullptr, "RedirectApplicationLegalInformationPath"}, + {9, nullptr, "Refresh"}, + {10, nullptr, "RedirectProgramPath2"}, + {11, nullptr, "Refresh2"}, + {12, nullptr, "DeleteProgramPath"}, + {13, nullptr, "DeleteApplicationControlPath"}, + {14, nullptr, "DeleteApplicationHtmlDocumentPath"}, + {15, nullptr, "DeleteApplicationLegalInformationPath"}, + {16, nullptr, ""}, + {17, nullptr, ""}, + {18, nullptr, ""}, + {19, nullptr, ""}, + }; + // clang-format on + + RegisterHandlers(functions); + } + +private: + FileSys::StorageId storage; +}; + +class IRegisteredLocationResolver final : public ServiceFramework<IRegisteredLocationResolver> { +public: + explicit IRegisteredLocationResolver() : ServiceFramework{"IRegisteredLocationResolver"} { + // clang-format off + static const FunctionInfo functions[] = { + {0, nullptr, "ResolveProgramPath"}, + {1, nullptr, "RegisterProgramPath"}, + {2, nullptr, "UnregisterProgramPath"}, + {3, nullptr, "RedirectProgramPath"}, + {4, nullptr, "ResolveHtmlDocumentPath"}, + {5, nullptr, "RegisterHtmlDocumentPath"}, + {6, nullptr, "UnregisterHtmlDocumentPath"}, + {7, nullptr, "RedirectHtmlDocumentPath"}, + {8, nullptr, ""}, + }; + // clang-format on + + RegisterHandlers(functions); + } +}; + +class IAddOnContentLocationResolver final : public ServiceFramework<IAddOnContentLocationResolver> { +public: + explicit IAddOnContentLocationResolver() : ServiceFramework{"IAddOnContentLocationResolver"} { + // clang-format off + static const FunctionInfo functions[] = { + {0, nullptr, "ResolveAddOnContentPath"}, + {1, nullptr, "RegisterAddOnContentStorage"}, + {2, nullptr, "UnregisterAllAddOnContentPath"}, + }; + // clang-format on + + RegisterHandlers(functions); + } +}; + +class LR final : public ServiceFramework<LR> { +public: + explicit LR() : ServiceFramework{"lr"} { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "OpenLocationResolver"}, @@ -52,7 +126,7 @@ public: }; void InstallInterfaces(SM::ServiceManager& sm) { - std::make_shared<LocationResolver>()->InstallAsService(sm); + std::make_shared<LR>()->InstallAsService(sm); std::make_shared<NCM>()->InstallAsService(sm); } 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..0e8256cb4 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() override; +}; + +class IApplicationManagerInterface final : public ServiceFramework<IApplicationManagerInterface> { +public: + explicit IApplicationManagerInterface(); + ~IApplicationManagerInterface() override; + + 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() override; +}; + +class IContentManagerInterface final : public ServiceFramework<IContentManagerInterface> { +public: + explicit IContentManagerInterface(); + ~IContentManagerInterface() override; +}; + +class IDocumentInterface final : public ServiceFramework<IDocumentInterface> { +public: + explicit IDocumentInterface(); + ~IDocumentInterface() override; +}; + +class IDownloadTaskInterface final : public ServiceFramework<IDownloadTaskInterface> { +public: + explicit IDownloadTaskInterface(); + ~IDownloadTaskInterface() override; +}; + +class IECommerceInterface final : public ServiceFramework<IECommerceInterface> { +public: + explicit IECommerceInterface(); + ~IECommerceInterface() override; +}; + +class IFactoryResetInterface final : public ServiceFramework<IFactoryResetInterface> { +public: + explicit IFactoryResetInterface(); + ~IFactoryResetInterface() override; +}; + +class NS final : public ServiceFramework<NS> { +public: + explicit NS(const char* name); + ~NS() override; + + 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/prepo/prepo.cpp b/src/core/hle/service/prepo/prepo.cpp index e4fcee9f8..7e134f5c1 100644 --- a/src/core/hle/service/prepo/prepo.cpp +++ b/src/core/hle/service/prepo/prepo.cpp @@ -2,10 +2,18 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include <json.hpp> +#include "common/file_util.h" +#include "common/hex_util.h" #include "common/logging/log.h" +#include "common/scm_rev.h" #include "core/hle/ipc_helpers.h" +#include "core/hle/kernel/process.h" +#include "core/hle/service/acc/profile_manager.h" #include "core/hle/service/prepo/prepo.h" #include "core/hle/service/service.h" +#include "core/reporter.h" +#include "core/settings.h" namespace Service::PlayReport { @@ -40,8 +48,21 @@ public: private: void SaveReportWithUserOld(Kernel::HLERequestContext& ctx) { - // TODO(ogniK): Do we want to add play report? - LOG_WARNING(Service_PREPO, "(STUBBED) called"); + IPC::RequestParser rp{ctx}; + const auto user_id = rp.PopRaw<u128>(); + const auto process_id = rp.PopRaw<u64>(); + + const auto data1 = ctx.ReadBuffer(0); + const auto data2 = ctx.ReadBuffer(1); + + LOG_DEBUG( + Service_PREPO, + "called, user_id={:016X}{:016X}, unk1={:016X}, data1_size={:016X}, data2_size={:016X}", + user_id[1], user_id[0], process_id, data1.size(), data2.size()); + + const auto& reporter{Core::System::GetInstance().GetReporter()}; + reporter.SavePlayReport(Core::CurrentProcess()->GetTitleID(), process_id, {data1, data2}, + user_id); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index 00806b0ed..b2954eb34 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp @@ -68,6 +68,7 @@ #include "core/hle/service/usb/usb.h" #include "core/hle/service/vi/vi.h" #include "core/hle/service/wlan/wlan.h" +#include "core/reporter.h" namespace Service { @@ -148,6 +149,8 @@ void ServiceFrameworkBase::ReportUnimplementedFunction(Kernel::HLERequestContext } buf.push_back('}'); + Core::System::GetInstance().GetReporter().SaveUnimplementedFunctionReport( + ctx, ctx.GetCommand(), function_name, service_name); UNIMPLEMENTED_MSG("Unknown / unimplemented {}", fmt::to_string(buf)); } @@ -200,7 +203,7 @@ void Init(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system, SM::ServiceManager::InstallInterfaces(sm); - Account::InstallInterfaces(*sm); + Account::InstallInterfaces(system); AM::InstallInterfaces(*sm, nv_flinger); AOC::InstallInterfaces(*sm); APM::InstallInterfaces(*sm); 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; |
