diff options
-rw-r--r-- | README.md | 2 | ||||
-rw-r--r-- | src/core/hle/service/am/am.cpp | 44 | ||||
-rw-r--r-- | src/core/hle/service/am/am.h | 30 | ||||
-rw-r--r-- | src/core/hle/service/am/applet_ae.cpp | 8 | ||||
-rw-r--r-- | src/core/hle/service/audio/audctl.cpp | 46 | ||||
-rw-r--r-- | src/core/hle/service/audio/audctl.h | 22 | ||||
-rw-r--r-- | src/core/hle/service/olsc/olsc.cpp | 158 | ||||
-rw-r--r-- | src/core/hle/service/pctl/pctl_module.cpp | 152 | ||||
-rw-r--r-- | src/core/hle/service/set/set.cpp | 60 | ||||
-rw-r--r-- | src/core/hle/service/set/set.h | 61 | ||||
-rw-r--r-- | src/core/hle/service/set/set_sys.cpp | 375 | ||||
-rw-r--r-- | src/core/hle/service/set/set_sys.h | 322 | ||||
-rw-r--r-- | src/shader_recompiler/environment.h | 2 | ||||
-rw-r--r-- | src/video_core/renderer_opengl/gl_shader_cache.cpp | 10 | ||||
-rw-r--r-- | src/video_core/renderer_vulkan/vk_pipeline_cache.cpp | 12 | ||||
-rw-r--r-- | src/video_core/shader_cache.cpp | 5 | ||||
-rw-r--r-- | src/video_core/shader_cache.h | 2 | ||||
-rw-r--r-- | src/video_core/shader_environment.cpp | 31 | ||||
-rw-r--r-- | src/video_core/shader_environment.h | 6 |
19 files changed, 1171 insertions, 177 deletions
@@ -40,7 +40,7 @@ It is written in C++ with portability in mind, and we actively maintain builds f The emulator is capable of running most commercial games at full speed, provided you meet the [necessary hardware requirements](https://yuzu-emu.org/help/quickstart/#hardware-requirements). -For a full list of games yuzu support, please visit our [Compatibility page](https://yuzu-emu.org/game/) +For a full list of games yuzu supports, please visit our [Compatibility page](https://yuzu-emu.org/game/). Check out our [website](https://yuzu-emu.org/) for the latest news on exciting features, monthly progress reports, and more! diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index 4f400d341..585675718 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -1317,6 +1317,50 @@ void ILibraryAppletCreator::CreateHandleStorage(HLERequestContext& ctx) { rb.PushIpcInterface<IStorage>(system, std::move(memory)); } +ILibraryAppletSelfAccessor::ILibraryAppletSelfAccessor(Core::System& system_) + : ServiceFramework{system_, "ILibraryAppletSelfAccessor"} { + static const FunctionInfo functions[] = { + {0, nullptr, "PopInData"}, + {1, nullptr, "PushOutData"}, + {2, nullptr, "PopInteractiveInData"}, + {3, nullptr, "PushInteractiveOutData"}, + {5, nullptr, "GetPopInDataEvent"}, + {6, nullptr, "GetPopInteractiveInDataEvent"}, + {10, nullptr, "ExitProcessAndReturn"}, + {11, nullptr, "GetLibraryAppletInfo"}, + {12, nullptr, "GetMainAppletIdentityInfo"}, + {13, nullptr, "CanUseApplicationCore"}, + {14, nullptr, "GetCallerAppletIdentityInfo"}, + {15, nullptr, "GetMainAppletApplicationControlProperty"}, + {16, nullptr, "GetMainAppletStorageId"}, + {17, nullptr, "GetCallerAppletIdentityInfoStack"}, + {18, nullptr, "GetNextReturnDestinationAppletIdentityInfo"}, + {19, nullptr, "GetDesirableKeyboardLayout"}, + {20, nullptr, "PopExtraStorage"}, + {25, nullptr, "GetPopExtraStorageEvent"}, + {30, nullptr, "UnpopInData"}, + {31, nullptr, "UnpopExtraStorage"}, + {40, nullptr, "GetIndirectLayerProducerHandle"}, + {50, nullptr, "ReportVisibleError"}, + {51, nullptr, "ReportVisibleErrorWithErrorContext"}, + {60, nullptr, "GetMainAppletApplicationDesiredLanguage"}, + {70, nullptr, "GetCurrentApplicationId"}, + {80, nullptr, "RequestExitToSelf"}, + {90, nullptr, "CreateApplicationAndPushAndRequestToLaunch"}, + {100, nullptr, "CreateGameMovieTrimmer"}, + {101, nullptr, "ReserveResourceForMovieOperation"}, + {102, nullptr, "UnreserveResourceForMovieOperation"}, + {110, nullptr, "GetMainAppletAvailableUsers"}, + {120, nullptr, "GetLaunchStorageInfoForDebug"}, + {130, nullptr, "GetGpuErrorDetectedSystemEvent"}, + {140, nullptr, "SetApplicationMemoryReservation"}, + {150, nullptr, "ShouldSetGpuTimeSliceManually"}, + }; + RegisterHandlers(functions); +} + +ILibraryAppletSelfAccessor::~ILibraryAppletSelfAccessor() = default; + IApplicationFunctions::IApplicationFunctions(Core::System& system_) : ServiceFramework{system_, "IApplicationFunctions"}, service_context{system, "IApplicationFunctions"} { diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h index d4fd163da..d68998f04 100644 --- a/src/core/hle/service/am/am.h +++ b/src/core/hle/service/am/am.h @@ -22,30 +22,6 @@ class Nvnflinger; namespace Service::AM { -// This is nn::settings::Language -enum SystemLanguage { - Japanese = 0, - English = 1, // en-US - French = 2, - German = 3, - Italian = 4, - Spanish = 5, - Chinese = 6, - Korean = 7, - Dutch = 8, - Portuguese = 9, - Russian = 10, - Taiwanese = 11, - BritishEnglish = 12, // en-GB - CanadianFrench = 13, - LatinAmericanSpanish = 14, // es-419 - // 4.0.0+ - SimplifiedChinese = 15, - TraditionalChinese = 16, - // 10.1.0+ - BrazilianPortuguese = 17, -}; - class AppletMessageQueue { public: // This is nn::am::AppletMessage @@ -314,6 +290,12 @@ private: void CreateHandleStorage(HLERequestContext& ctx); }; +class ILibraryAppletSelfAccessor final : public ServiceFramework<ILibraryAppletSelfAccessor> { +public: + explicit ILibraryAppletSelfAccessor(Core::System& system_); + ~ILibraryAppletSelfAccessor() override; +}; + class IApplicationFunctions final : public ServiceFramework<IApplicationFunctions> { public: explicit IApplicationFunctions(Core::System& system_); diff --git a/src/core/hle/service/am/applet_ae.cpp b/src/core/hle/service/am/applet_ae.cpp index 2764f7ceb..ee9d99a54 100644 --- a/src/core/hle/service/am/applet_ae.cpp +++ b/src/core/hle/service/am/applet_ae.cpp @@ -26,8 +26,10 @@ public: {4, &ILibraryAppletProxy::GetDisplayController, "GetDisplayController"}, {10, &ILibraryAppletProxy::GetProcessWindingController, "GetProcessWindingController"}, {11, &ILibraryAppletProxy::GetLibraryAppletCreator, "GetLibraryAppletCreator"}, - {20, &ILibraryAppletProxy::GetApplicationFunctions, "GetApplicationFunctions"}, + {20, &ILibraryAppletProxy::OpenLibraryAppletSelfAccessor, "OpenLibraryAppletSelfAccessor"}, {21, nullptr, "GetAppletCommonFunctions"}, + {22, nullptr, "GetHomeMenuFunctions"}, + {23, nullptr, "GetGlobalStateController"}, {1000, &ILibraryAppletProxy::GetDebugFunctions, "GetDebugFunctions"}, }; // clang-format on @@ -100,12 +102,12 @@ private: rb.PushIpcInterface<ILibraryAppletCreator>(system); } - void GetApplicationFunctions(HLERequestContext& ctx) { + void OpenLibraryAppletSelfAccessor(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(ResultSuccess); - rb.PushIpcInterface<IApplicationFunctions>(system); + rb.PushIpcInterface<ILibraryAppletSelfAccessor>(system); } Nvnflinger::Nvnflinger& nvnflinger; diff --git a/src/core/hle/service/audio/audctl.cpp b/src/core/hle/service/audio/audctl.cpp index 7ad93be6b..66dd64fd1 100644 --- a/src/core/hle/service/audio/audctl.cpp +++ b/src/core/hle/service/audio/audctl.cpp @@ -22,13 +22,13 @@ AudCtl::AudCtl(Core::System& system_) : ServiceFramework{system_, "audctl"} { {9, nullptr, "GetAudioOutputMode"}, {10, nullptr, "SetAudioOutputMode"}, {11, nullptr, "SetForceMutePolicy"}, - {12, nullptr, "GetForceMutePolicy"}, - {13, nullptr, "GetOutputModeSetting"}, + {12, &AudCtl::GetForceMutePolicy, "GetForceMutePolicy"}, + {13, &AudCtl::GetOutputModeSetting, "GetOutputModeSetting"}, {14, nullptr, "SetOutputModeSetting"}, {15, nullptr, "SetOutputTarget"}, {16, nullptr, "SetInputTargetForceEnabled"}, {17, nullptr, "SetHeadphoneOutputLevelMode"}, - {18, nullptr, "GetHeadphoneOutputLevelMode"}, + {18, &AudCtl::GetHeadphoneOutputLevelMode, "GetHeadphoneOutputLevelMode"}, {19, nullptr, "AcquireAudioVolumeUpdateEventForPlayReport"}, {20, nullptr, "AcquireAudioOutputDeviceUpdateEventForPlayReport"}, {21, nullptr, "GetAudioOutputTargetForPlayReport"}, @@ -41,7 +41,7 @@ AudCtl::AudCtl(Core::System& system_) : ServiceFramework{system_, "audctl"} { {28, nullptr, "GetAudioOutputChannelCountForPlayReport"}, {29, nullptr, "BindAudioOutputChannelCountUpdateEventForPlayReport"}, {30, nullptr, "SetSpeakerAutoMuteEnabled"}, - {31, nullptr, "IsSpeakerAutoMuteEnabled"}, + {31, &AudCtl::IsSpeakerAutoMuteEnabled, "IsSpeakerAutoMuteEnabled"}, {32, nullptr, "GetActiveOutputTarget"}, {33, nullptr, "GetTargetDeviceInfo"}, {34, nullptr, "AcquireTargetNotification"}, @@ -96,4 +96,42 @@ void AudCtl::GetTargetVolumeMax(HLERequestContext& ctx) { rb.Push(target_max_volume); } +void AudCtl::GetForceMutePolicy(HLERequestContext& ctx) { + LOG_WARNING(Audio, "(STUBBED) called"); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.PushEnum(ForceMutePolicy::Disable); +} + +void AudCtl::GetOutputModeSetting(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto value = rp.Pop<u32>(); + + LOG_WARNING(Audio, "(STUBBED) called, value={}", value); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.PushEnum(AudioOutputMode::PcmAuto); +} + +void AudCtl::GetHeadphoneOutputLevelMode(HLERequestContext& ctx) { + LOG_WARNING(Audio, "(STUBBED) called"); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.PushEnum(HeadphoneOutputLevelMode::Normal); +} + +void AudCtl::IsSpeakerAutoMuteEnabled(HLERequestContext& ctx) { + const bool is_speaker_auto_mute_enabled = false; + + LOG_WARNING(Audio, "(STUBBED) called, is_speaker_auto_mute_enabled={}", + is_speaker_auto_mute_enabled); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push<u8>(is_speaker_auto_mute_enabled); +} + } // namespace Service::Audio diff --git a/src/core/hle/service/audio/audctl.h b/src/core/hle/service/audio/audctl.h index 8e31ac237..d57abb383 100644 --- a/src/core/hle/service/audio/audctl.h +++ b/src/core/hle/service/audio/audctl.h @@ -17,8 +17,30 @@ public: ~AudCtl() override; private: + enum class AudioOutputMode { + Invalid, + Pcm1ch, + Pcm2ch, + Pcm6ch, + PcmAuto, + }; + + enum class ForceMutePolicy { + Disable, + SpeakerMuteOnHeadphoneUnplugged, + }; + + enum class HeadphoneOutputLevelMode { + Normal, + HighPower, + }; + void GetTargetVolumeMin(HLERequestContext& ctx); void GetTargetVolumeMax(HLERequestContext& ctx); + void GetForceMutePolicy(HLERequestContext& ctx); + void GetOutputModeSetting(HLERequestContext& ctx); + void GetHeadphoneOutputLevelMode(HLERequestContext& ctx); + void IsSpeakerAutoMuteEnabled(HLERequestContext& ctx); }; } // namespace Service::Audio diff --git a/src/core/hle/service/olsc/olsc.cpp b/src/core/hle/service/olsc/olsc.cpp index 14ba67b4c..889f27c31 100644 --- a/src/core/hle/service/olsc/olsc.cpp +++ b/src/core/hle/service/olsc/olsc.cpp @@ -8,15 +8,16 @@ namespace Service::OLSC { -class OLSC final : public ServiceFramework<OLSC> { +class IOlscServiceForApplication final : public ServiceFramework<IOlscServiceForApplication> { public: - explicit OLSC(Core::System& system_) : ServiceFramework{system_, "olsc:u"} { + explicit IOlscServiceForApplication(Core::System& system_) + : ServiceFramework{system_, "olsc:u"} { // clang-format off static const FunctionInfo functions[] = { - {0, &OLSC::Initialize, "Initialize"}, + {0, &IOlscServiceForApplication::Initialize, "Initialize"}, {10, nullptr, "VerifySaveDataBackupLicenseAsync"}, - {13, &OLSC::GetSaveDataBackupSetting, "GetSaveDataBackupSetting"}, - {14, &OLSC::SetSaveDataBackupSettingEnabled, "SetSaveDataBackupSettingEnabled"}, + {13, &IOlscServiceForApplication::GetSaveDataBackupSetting, "GetSaveDataBackupSetting"}, + {14, &IOlscServiceForApplication::SetSaveDataBackupSettingEnabled, "SetSaveDataBackupSettingEnabled"}, {15, nullptr, "SetCustomData"}, {16, nullptr, "DeleteSaveDataBackupSetting"}, {18, nullptr, "GetSaveDataBackupInfoCache"}, @@ -72,10 +73,155 @@ private: bool initialized{}; }; +class INativeHandleHolder final : public ServiceFramework<INativeHandleHolder> { +public: + explicit INativeHandleHolder(Core::System& system_) + : ServiceFramework{system_, "INativeHandleHolder"} { + // clang-format off + static const FunctionInfo functions[] = { + {0, nullptr, "GetNativeHandle"}, + }; + // clang-format on + + RegisterHandlers(functions); + } +}; + +class ITransferTaskListController final : public ServiceFramework<ITransferTaskListController> { +public: + explicit ITransferTaskListController(Core::System& system_) + : ServiceFramework{system_, "ITransferTaskListController"} { + // clang-format off + static const FunctionInfo functions[] = { + {0, nullptr, "Unknown0"}, + {1, nullptr, "Unknown1"}, + {2, nullptr, "Unknown2"}, + {3, nullptr, "Unknown3"}, + {4, nullptr, "Unknown4"}, + {5, &ITransferTaskListController::GetNativeHandleHolder , "GetNativeHandleHolder"}, + {6, nullptr, "Unknown6"}, + {7, nullptr, "Unknown7"}, + {8, nullptr, "GetRemoteStorageController"}, + {9, &ITransferTaskListController::GetNativeHandleHolder, "GetNativeHandleHolder2"}, + {10, nullptr, "Unknown10"}, + {11, nullptr, "Unknown11"}, + {12, nullptr, "Unknown12"}, + {13, nullptr, "Unknown13"}, + {14, nullptr, "Unknown14"}, + {15, nullptr, "Unknown15"}, + {16, nullptr, "Unknown16"}, + {17, nullptr, "Unknown17"}, + {18, nullptr, "Unknown18"}, + {19, nullptr, "Unknown19"}, + {20, nullptr, "Unknown20"}, + {21, nullptr, "Unknown21"}, + {22, nullptr, "Unknown22"}, + {23, nullptr, "Unknown23"}, + {24, nullptr, "Unknown24"}, + {25, nullptr, "Unknown25"}, + }; + // clang-format on + + RegisterHandlers(functions); + } + +private: + void GetNativeHandleHolder(HLERequestContext& ctx) { + LOG_INFO(Service_OLSC, "called"); + + IPC::ResponseBuilder rb{ctx, 2, 0, 1}; + rb.Push(ResultSuccess); + rb.PushIpcInterface<INativeHandleHolder>(system); + } +}; + +class IOlscServiceForSystemService final : public ServiceFramework<IOlscServiceForSystemService> { +public: + explicit IOlscServiceForSystemService(Core::System& system_) + : ServiceFramework{system_, "olsc:s"} { + // clang-format off + static const FunctionInfo functions[] = { + {0, &IOlscServiceForSystemService::OpenTransferTaskListController, "OpenTransferTaskListController"}, + {1, nullptr, "OpenRemoteStorageController"}, + {2, nullptr, "OpenDaemonController"}, + {10, nullptr, "Unknown10"}, + {11, nullptr, "Unknown11"}, + {12, nullptr, "Unknown12"}, + {13, nullptr, "Unknown13"}, + {100, nullptr, "ListLastTransferTaskErrorInfo"}, + {101, nullptr, "GetLastErrorInfoCount"}, + {102, nullptr, "RemoveLastErrorInfoOld"}, + {103, nullptr, "GetLastErrorInfo"}, + {104, nullptr, "GetLastErrorEventHolder"}, + {105, nullptr, "GetLastTransferTaskErrorInfo"}, + {200, nullptr, "GetDataTransferPolicyInfo"}, + {201, nullptr, "RemoveDataTransferPolicyInfo"}, + {202, nullptr, "UpdateDataTransferPolicyOld"}, + {203, nullptr, "UpdateDataTransferPolicy"}, + {204, nullptr, "CleanupDataTransferPolicyInfo"}, + {205, nullptr, "RequestDataTransferPolicy"}, + {300, nullptr, "GetAutoTransferSeriesInfo"}, + {301, nullptr, "UpdateAutoTransferSeriesInfo"}, + {400, nullptr, "CleanupSaveDataArchiveInfoType1"}, + {900, nullptr, "CleanupTransferTask"}, + {902, nullptr, "CleanupSeriesInfoType0"}, + {903, nullptr, "CleanupSaveDataArchiveInfoType0"}, + {904, nullptr, "CleanupApplicationAutoTransferSetting"}, + {905, nullptr, "CleanupErrorHistory"}, + {906, nullptr, "SetLastError"}, + {907, nullptr, "AddSaveDataArchiveInfoType0"}, + {908, nullptr, "RemoveSeriesInfoType0"}, + {909, nullptr, "GetSeriesInfoType0"}, + {910, nullptr, "RemoveLastErrorInfo"}, + {911, nullptr, "CleanupSeriesInfoType1"}, + {912, nullptr, "RemoveSeriesInfoType1"}, + {913, nullptr, "GetSeriesInfoType1"}, + {1000, nullptr, "UpdateIssueOld"}, + {1010, nullptr, "Unknown1010"}, + {1011, nullptr, "ListIssueInfoOld"}, + {1012, nullptr, "GetIssueOld"}, + {1013, nullptr, "GetIssue2Old"}, + {1014, nullptr, "GetIssue3Old"}, + {1020, nullptr, "RepairIssueOld"}, + {1021, nullptr, "RepairIssueWithUserIdOld"}, + {1022, nullptr, "RepairIssue2Old"}, + {1023, nullptr, "RepairIssue3Old"}, + {1024, nullptr, "Unknown1024"}, + {1100, nullptr, "UpdateIssue"}, + {1110, nullptr, "Unknown1110"}, + {1111, nullptr, "ListIssueInfo"}, + {1112, nullptr, "GetIssue"}, + {1113, nullptr, "GetIssue2"}, + {1114, nullptr, "GetIssue3"}, + {1120, nullptr, "RepairIssue"}, + {1121, nullptr, "RepairIssueWithUserId"}, + {1122, nullptr, "RepairIssue2"}, + {1123, nullptr, "RepairIssue3"}, + {1124, nullptr, "Unknown1124"}, + }; + // clang-format on + + RegisterHandlers(functions); + } + +private: + void OpenTransferTaskListController(HLERequestContext& ctx) { + LOG_INFO(Service_OLSC, "called"); + + IPC::ResponseBuilder rb{ctx, 2, 0, 1}; + rb.Push(ResultSuccess); + rb.PushIpcInterface<ITransferTaskListController>(system); + } +}; + void LoopProcess(Core::System& system) { auto server_manager = std::make_unique<ServerManager>(system); - server_manager->RegisterNamedService("olsc:u", std::make_shared<OLSC>(system)); + server_manager->RegisterNamedService("olsc:u", + std::make_shared<IOlscServiceForApplication>(system)); + server_manager->RegisterNamedService("olsc:s", + std::make_shared<IOlscServiceForSystemService>(system)); + ServerManager::RunServer(std::move(server_manager)); } diff --git a/src/core/hle/service/pctl/pctl_module.cpp b/src/core/hle/service/pctl/pctl_module.cpp index f966c5c8b..7c8a539b8 100644 --- a/src/core/hle/service/pctl/pctl_module.cpp +++ b/src/core/hle/service/pctl/pctl_module.cpp @@ -6,6 +6,7 @@ #include "core/file_sys/control_metadata.h" #include "core/file_sys/patch_manager.h" #include "core/hle/service/ipc_helpers.h" +#include "core/hle/service/kernel_helpers.h" #include "core/hle/service/pctl/pctl.h" #include "core/hle/service/pctl/pctl_module.h" #include "core/hle/service/server_manager.h" @@ -24,7 +25,8 @@ constexpr Result ResultNoRestrictionEnabled{ErrorModule::PCTL, 181}; class IParentalControlService final : public ServiceFramework<IParentalControlService> { public: explicit IParentalControlService(Core::System& system_, Capability capability_) - : ServiceFramework{system_, "IParentalControlService"}, capability{capability_} { + : ServiceFramework{system_, "IParentalControlService"}, capability{capability_}, + service_context{system_, "IParentalControlService"} { // clang-format off static const FunctionInfo functions[] = { {1, &IParentalControlService::Initialize, "Initialize"}, @@ -33,7 +35,7 @@ public: {1003, nullptr, "ConfirmResumeApplicationPermission"}, {1004, nullptr, "ConfirmSnsPostPermission"}, {1005, nullptr, "ConfirmSystemSettingsPermission"}, - {1006, nullptr, "IsRestrictionTemporaryUnlocked"}, + {1006, &IParentalControlService::IsRestrictionTemporaryUnlocked, "IsRestrictionTemporaryUnlocked"}, {1007, nullptr, "RevertRestrictionTemporaryUnlocked"}, {1008, nullptr, "EnterRestrictedSystemSettings"}, {1009, nullptr, "LeaveRestrictedSystemSettings"}, @@ -47,14 +49,14 @@ public: {1017, &IParentalControlService::EndFreeCommunication, "EndFreeCommunication"}, {1018, &IParentalControlService::IsFreeCommunicationAvailable, "IsFreeCommunicationAvailable"}, {1031, &IParentalControlService::IsRestrictionEnabled, "IsRestrictionEnabled"}, - {1032, nullptr, "GetSafetyLevel"}, + {1032, &IParentalControlService::GetSafetyLevel, "GetSafetyLevel"}, {1033, nullptr, "SetSafetyLevel"}, {1034, nullptr, "GetSafetyLevelSettings"}, - {1035, nullptr, "GetCurrentSettings"}, + {1035, &IParentalControlService::GetCurrentSettings, "GetCurrentSettings"}, {1036, nullptr, "SetCustomSafetyLevelSettings"}, {1037, nullptr, "GetDefaultRatingOrganization"}, {1038, nullptr, "SetDefaultRatingOrganization"}, - {1039, nullptr, "GetFreeCommunicationApplicationListCount"}, + {1039, &IParentalControlService::GetFreeCommunicationApplicationListCount, "GetFreeCommunicationApplicationListCount"}, {1042, nullptr, "AddToFreeCommunicationApplicationList"}, {1043, nullptr, "DeleteSettings"}, {1044, nullptr, "GetFreeCommunicationApplicationList"}, @@ -76,7 +78,7 @@ public: {1206, nullptr, "GetPinCodeLength"}, {1207, nullptr, "GetPinCodeChangedEvent"}, {1208, nullptr, "GetPinCode"}, - {1403, nullptr, "IsPairingActive"}, + {1403, &IParentalControlService::IsPairingActive, "IsPairingActive"}, {1406, nullptr, "GetSettingsLastUpdated"}, {1411, nullptr, "GetPairingAccountInfo"}, {1421, nullptr, "GetAccountNickname"}, @@ -84,18 +86,18 @@ public: {1425, nullptr, "RequestPostEvents"}, {1426, nullptr, "GetPostEventInterval"}, {1427, nullptr, "SetPostEventInterval"}, - {1432, nullptr, "GetSynchronizationEvent"}, + {1432, &IParentalControlService::GetSynchronizationEvent, "GetSynchronizationEvent"}, {1451, nullptr, "StartPlayTimer"}, {1452, nullptr, "StopPlayTimer"}, {1453, nullptr, "IsPlayTimerEnabled"}, {1454, nullptr, "GetPlayTimerRemainingTime"}, {1455, nullptr, "IsRestrictedByPlayTimer"}, - {1456, nullptr, "GetPlayTimerSettings"}, - {1457, nullptr, "GetPlayTimerEventToRequestSuspension"}, - {1458, nullptr, "IsPlayTimerAlarmDisabled"}, + {1456, &IParentalControlService::GetPlayTimerSettings, "GetPlayTimerSettings"}, + {1457, &IParentalControlService::GetPlayTimerEventToRequestSuspension, "GetPlayTimerEventToRequestSuspension"}, + {1458, &IParentalControlService::IsPlayTimerAlarmDisabled, "IsPlayTimerAlarmDisabled"}, {1471, nullptr, "NotifyWrongPinCodeInputManyTimes"}, {1472, nullptr, "CancelNetworkRequest"}, - {1473, nullptr, "GetUnlinkedEvent"}, + {1473, &IParentalControlService::GetUnlinkedEvent, "GetUnlinkedEvent"}, {1474, nullptr, "ClearUnlinkedEvent"}, {1601, nullptr, "DisableAllFeatures"}, {1602, nullptr, "PostEnableAllFeatures"}, @@ -131,6 +133,12 @@ public: }; // clang-format on RegisterHandlers(functions); + + synchronization_event = + service_context.CreateEvent("IParentalControlService::SynchronizationEvent"); + unlinked_event = service_context.CreateEvent("IParentalControlService::UnlinkedEvent"); + request_suspension_event = + service_context.CreateEvent("IParentalControlService::RequestSuspensionEvent"); } private: @@ -144,7 +152,7 @@ private: if (pin_code[0] == '\0') { return true; } - if (!settings.is_free_communication_default_on) { + if (!restriction_settings.is_free_communication_default_on) { return true; } // TODO(ogniK): Check for blacklisted/exempted applications. Return false can happen here @@ -160,21 +168,21 @@ private: if (pin_code[0] == '\0') { return true; } - if (!settings.is_stero_vision_restricted) { + if (!restriction_settings.is_stero_vision_restricted) { return false; } return true; } void SetStereoVisionRestrictionImpl(bool is_restricted) { - if (settings.disabled) { + if (restriction_settings.disabled) { return; } if (pin_code[0] == '\0') { return; } - settings.is_stero_vision_restricted = is_restricted; + restriction_settings.is_stero_vision_restricted = is_restricted; } void Initialize(HLERequestContext& ctx) { @@ -228,6 +236,17 @@ private: states.free_communication = true; } + void IsRestrictionTemporaryUnlocked(HLERequestContext& ctx) { + const bool is_temporary_unlocked = false; + + LOG_WARNING(Service_PCTL, "(STUBBED) called, is_temporary_unlocked={}", + is_temporary_unlocked); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push<u8>(is_temporary_unlocked); + } + void ConfirmStereoVisionPermission(HLERequestContext& ctx) { LOG_DEBUG(Service_PCTL, "called"); states.stereo_vision = true; @@ -268,6 +287,34 @@ private: rb.Push(pin_code[0] != '\0'); } + void GetSafetyLevel(HLERequestContext& ctx) { + const u32 safety_level = 0; + + LOG_WARNING(Service_PCTL, "(STUBBED) called, safety_level={}", safety_level); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push(safety_level); + } + + void GetCurrentSettings(HLERequestContext& ctx) { + LOG_INFO(Service_PCTL, "called"); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.PushRaw(restriction_settings); + } + + void GetFreeCommunicationApplicationListCount(HLERequestContext& ctx) { + const u32 count = 4; + + LOG_WARNING(Service_PCTL, "(STUBBED) called, count={}", count); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push(count); + } + void ConfirmStereoVisionRestrictionConfigurable(HLERequestContext& ctx) { LOG_DEBUG(Service_PCTL, "called"); @@ -300,6 +347,61 @@ private: } } + void IsPairingActive(HLERequestContext& ctx) { + const bool is_pairing_active = false; + + LOG_WARNING(Service_PCTL, "(STUBBED) called, is_pairing_active={}", is_pairing_active); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push<u8>(is_pairing_active); + } + + void GetSynchronizationEvent(HLERequestContext& ctx) { + LOG_INFO(Service_PCTL, "called"); + + IPC::ResponseBuilder rb{ctx, 2, 1}; + rb.Push(ResultSuccess); + rb.PushCopyObjects(synchronization_event->GetReadableEvent()); + } + + void GetPlayTimerSettings(HLERequestContext& ctx) { + LOG_WARNING(Service_PCTL, "(STUBBED) called"); + + const PlayTimerSettings timer_settings{}; + + IPC::ResponseBuilder rb{ctx, 15}; + rb.Push(ResultSuccess); + rb.PushRaw(timer_settings); + } + + void GetPlayTimerEventToRequestSuspension(HLERequestContext& ctx) { + LOG_INFO(Service_PCTL, "called"); + + IPC::ResponseBuilder rb{ctx, 2, 1}; + rb.Push(ResultSuccess); + rb.PushCopyObjects(request_suspension_event->GetReadableEvent()); + } + + void IsPlayTimerAlarmDisabled(HLERequestContext& ctx) { + const bool is_play_timer_alarm_disabled = false; + + LOG_INFO(Service_PCTL, "called, is_play_timer_alarm_disabled={}", + is_play_timer_alarm_disabled); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push<u8>(is_play_timer_alarm_disabled); + } + + void GetUnlinkedEvent(HLERequestContext& ctx) { + LOG_INFO(Service_PCTL, "called"); + + IPC::ResponseBuilder rb{ctx, 2, 1}; + rb.Push(ResultSuccess); + rb.PushCopyObjects(unlinked_event->GetReadableEvent()); + } + void SetStereoVisionRestriction(HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const auto can_use = rp.Pop<bool>(); @@ -328,7 +430,7 @@ private: } rb.Push(ResultSuccess); - rb.Push(settings.is_stero_vision_restricted); + rb.Push(restriction_settings.is_stero_vision_restricted); } void ResetConfirmedStereoVisionPermission(HLERequestContext& ctx) { @@ -358,16 +460,30 @@ private: bool stereo_vision{}; }; - struct ParentalControlSettings { + // This is nn::pctl::RestrictionSettings + struct RestrictionSettings { bool is_stero_vision_restricted{}; bool is_free_communication_default_on{}; bool disabled{}; }; + static_assert(sizeof(RestrictionSettings) == 0x3, "RestrictionSettings has incorrect size."); + + // This is nn::pctl::PlayTimerSettings + struct PlayTimerSettings { + // TODO: RE the actual contents of this struct + std::array<u8, 0x34> settings; + }; + static_assert(sizeof(PlayTimerSettings) == 0x34, "PlayTimerSettings has incorrect size."); States states{}; - ParentalControlSettings settings{}; + RestrictionSettings restriction_settings{}; std::array<char, 8> pin_code{}; Capability capability{}; + + Kernel::KEvent* synchronization_event; + Kernel::KEvent* unlinked_event; + Kernel::KEvent* request_suspension_event; + KernelHelpers::ServiceContext service_context; }; void Module::Interface::CreateService(HLERequestContext& ctx) { diff --git a/src/core/hle/service/set/set.cpp b/src/core/hle/service/set/set.cpp index 83f888c54..2082b8ef7 100644 --- a/src/core/hle/service/set/set.cpp +++ b/src/core/hle/service/set/set.cpp @@ -11,66 +11,6 @@ namespace Service::Set { namespace { -constexpr std::array<LanguageCode, 18> available_language_codes = {{ - LanguageCode::JA, - LanguageCode::EN_US, - LanguageCode::FR, - LanguageCode::DE, - LanguageCode::IT, - LanguageCode::ES, - LanguageCode::ZH_CN, - LanguageCode::KO, - LanguageCode::NL, - LanguageCode::PT, - LanguageCode::RU, - LanguageCode::ZH_TW, - LanguageCode::EN_GB, - LanguageCode::FR_CA, - LanguageCode::ES_419, - LanguageCode::ZH_HANS, - LanguageCode::ZH_HANT, - LanguageCode::PT_BR, -}}; - -enum class KeyboardLayout : u64 { - Japanese = 0, - EnglishUs = 1, - EnglishUsInternational = 2, - EnglishUk = 3, - French = 4, - FrenchCa = 5, - Spanish = 6, - SpanishLatin = 7, - German = 8, - Italian = 9, - Portuguese = 10, - Russian = 11, - Korean = 12, - ChineseSimplified = 13, - ChineseTraditional = 14, -}; - -constexpr std::array<std::pair<LanguageCode, KeyboardLayout>, 18> language_to_layout{{ - {LanguageCode::JA, KeyboardLayout::Japanese}, - {LanguageCode::EN_US, KeyboardLayout::EnglishUs}, - {LanguageCode::FR, KeyboardLayout::French}, - {LanguageCode::DE, KeyboardLayout::German}, - {LanguageCode::IT, KeyboardLayout::Italian}, - {LanguageCode::ES, KeyboardLayout::Spanish}, - {LanguageCode::ZH_CN, KeyboardLayout::ChineseSimplified}, - {LanguageCode::KO, KeyboardLayout::Korean}, - {LanguageCode::NL, KeyboardLayout::EnglishUsInternational}, - {LanguageCode::PT, KeyboardLayout::Portuguese}, - {LanguageCode::RU, KeyboardLayout::Russian}, - {LanguageCode::ZH_TW, KeyboardLayout::ChineseTraditional}, - {LanguageCode::EN_GB, KeyboardLayout::EnglishUk}, - {LanguageCode::FR_CA, KeyboardLayout::FrenchCa}, - {LanguageCode::ES_419, KeyboardLayout::SpanishLatin}, - {LanguageCode::ZH_HANS, KeyboardLayout::ChineseSimplified}, - {LanguageCode::ZH_HANT, KeyboardLayout::ChineseTraditional}, - {LanguageCode::PT_BR, KeyboardLayout::Portuguese}, -}}; - constexpr std::size_t PRE_4_0_0_MAX_ENTRIES = 0xF; constexpr std::size_t POST_4_0_0_MAX_ENTRIES = 0x40; diff --git a/src/core/hle/service/set/set.h b/src/core/hle/service/set/set.h index 7fd3a7654..b61a3560d 100644 --- a/src/core/hle/service/set/set.h +++ b/src/core/hle/service/set/set.h @@ -32,6 +32,67 @@ enum class LanguageCode : u64 { ZH_HANT = 0x00746E61482D687A, PT_BR = 0x00000052422D7470, }; + +enum class KeyboardLayout : u64 { + Japanese = 0, + EnglishUs = 1, + EnglishUsInternational = 2, + EnglishUk = 3, + French = 4, + FrenchCa = 5, + Spanish = 6, + SpanishLatin = 7, + German = 8, + Italian = 9, + Portuguese = 10, + Russian = 11, + Korean = 12, + ChineseSimplified = 13, + ChineseTraditional = 14, +}; + +constexpr std::array<LanguageCode, 18> available_language_codes = {{ + LanguageCode::JA, + LanguageCode::EN_US, + LanguageCode::FR, + LanguageCode::DE, + LanguageCode::IT, + LanguageCode::ES, + LanguageCode::ZH_CN, + LanguageCode::KO, + LanguageCode::NL, + LanguageCode::PT, + LanguageCode::RU, + LanguageCode::ZH_TW, + LanguageCode::EN_GB, + LanguageCode::FR_CA, + LanguageCode::ES_419, + LanguageCode::ZH_HANS, + LanguageCode::ZH_HANT, + LanguageCode::PT_BR, +}}; + +static constexpr std::array<std::pair<LanguageCode, KeyboardLayout>, 18> language_to_layout{{ + {LanguageCode::JA, KeyboardLayout::Japanese}, + {LanguageCode::EN_US, KeyboardLayout::EnglishUs}, + {LanguageCode::FR, KeyboardLayout::French}, + {LanguageCode::DE, KeyboardLayout::German}, + {LanguageCode::IT, KeyboardLayout::Italian}, + {LanguageCode::ES, KeyboardLayout::Spanish}, + {LanguageCode::ZH_CN, KeyboardLayout::ChineseSimplified}, + {LanguageCode::KO, KeyboardLayout::Korean}, + {LanguageCode::NL, KeyboardLayout::EnglishUsInternational}, + {LanguageCode::PT, KeyboardLayout::Portuguese}, + {LanguageCode::RU, KeyboardLayout::Russian}, + {LanguageCode::ZH_TW, KeyboardLayout::ChineseTraditional}, + {LanguageCode::EN_GB, KeyboardLayout::EnglishUk}, + {LanguageCode::FR_CA, KeyboardLayout::FrenchCa}, + {LanguageCode::ES_419, KeyboardLayout::SpanishLatin}, + {LanguageCode::ZH_HANS, KeyboardLayout::ChineseSimplified}, + {LanguageCode::ZH_HANT, KeyboardLayout::ChineseTraditional}, + {LanguageCode::PT_BR, KeyboardLayout::Portuguese}, +}}; + LanguageCode GetLanguageCodeFromIndex(std::size_t idx); class SET final : public ServiceFramework<SET> { diff --git a/src/core/hle/service/set/set_sys.cpp b/src/core/hle/service/set/set_sys.cpp index 2e38d1cfc..165b97dad 100644 --- a/src/core/hle/service/set/set_sys.cpp +++ b/src/core/hle/service/set/set_sys.cpp @@ -4,10 +4,12 @@ #include "common/assert.h" #include "common/logging/log.h" #include "common/settings.h" +#include "common/string_util.h" #include "core/file_sys/errors.h" #include "core/file_sys/system_archive/system_version.h" #include "core/hle/service/filesystem/filesystem.h" #include "core/hle/service/ipc_helpers.h" +#include "core/hle/service/set/set.h" #include "core/hle/service/set/set_sys.h" namespace Service::Set { @@ -73,6 +75,16 @@ void GetFirmwareVersionImpl(HLERequestContext& ctx, GetFirmwareVersionType type) } } // Anonymous namespace +void SET_SYS::SetLanguageCode(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + language_code_setting = rp.PopEnum<LanguageCode>(); + + LOG_INFO(Service_SET, "called, language_code={}", language_code_setting); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + void SET_SYS::GetFirmwareVersion(HLERequestContext& ctx) { LOG_DEBUG(Service_SET, "called"); GetFirmwareVersionImpl(ctx, GetFirmwareVersionType::Version1); @@ -83,21 +95,113 @@ void SET_SYS::GetFirmwareVersion2(HLERequestContext& ctx) { GetFirmwareVersionImpl(ctx, GetFirmwareVersionType::Version2); } +void SET_SYS::GetAccountSettings(HLERequestContext& ctx) { + LOG_INFO(Service_SET, "called"); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.PushRaw(account_settings); +} + +void SET_SYS::SetAccountSettings(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + account_settings = rp.PopRaw<AccountSettings>(); + + LOG_INFO(Service_SET, "called, account_settings_flags={}", account_settings.flags); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +void SET_SYS::GetEulaVersions(HLERequestContext& ctx) { + LOG_INFO(Service_SET, "called"); + + ctx.WriteBuffer(eula_versions); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push(static_cast<u32>(eula_versions.size())); +} + +void SET_SYS::SetEulaVersions(HLERequestContext& ctx) { + const auto elements = ctx.GetReadBufferNumElements<EulaVersion>(); + const auto buffer_data = ctx.ReadBuffer(); + + LOG_INFO(Service_SET, "called, elements={}", elements); + + eula_versions.resize(elements); + for (std::size_t index = 0; index < elements; index++) { + const std::size_t start_index = index * sizeof(EulaVersion); + memcpy(eula_versions.data() + start_index, buffer_data.data() + start_index, + sizeof(EulaVersion)); + } + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + void SET_SYS::GetColorSetId(HLERequestContext& ctx) { LOG_DEBUG(Service_SET, "called"); IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); rb.PushEnum(color_set); } void SET_SYS::SetColorSetId(HLERequestContext& ctx) { - LOG_DEBUG(Service_SET, "called"); - IPC::RequestParser rp{ctx}; color_set = rp.PopEnum<ColorSet>(); + LOG_DEBUG(Service_SET, "called, color_set={}", color_set); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +void SET_SYS::GetNotificationSettings(HLERequestContext& ctx) { + LOG_INFO(Service_SET, "called"); + + IPC::ResponseBuilder rb{ctx, 8}; + rb.Push(ResultSuccess); + rb.PushRaw(notification_settings); +} + +void SET_SYS::SetNotificationSettings(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + notification_settings = rp.PopRaw<NotificationSettings>(); + + LOG_INFO(Service_SET, "called, flags={}, volume={}, head_time={}:{}, tailt_time={}:{}", + notification_settings.flags.raw, notification_settings.volume, + notification_settings.start_time.hour, notification_settings.start_time.minute, + notification_settings.stop_time.hour, notification_settings.stop_time.minute); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +void SET_SYS::GetAccountNotificationSettings(HLERequestContext& ctx) { + LOG_INFO(Service_SET, "called"); + + ctx.WriteBuffer(account_notifications); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push(static_cast<u32>(account_notifications.size())); +} + +void SET_SYS::SetAccountNotificationSettings(HLERequestContext& ctx) { + const auto elements = ctx.GetReadBufferNumElements<AccountNotificationSettings>(); + const auto buffer_data = ctx.ReadBuffer(); + + LOG_INFO(Service_SET, "called, elements={}", elements); + + account_notifications.resize(elements); + for (std::size_t index = 0; index < elements; index++) { + const std::size_t start_index = index * sizeof(AccountNotificationSettings); + memcpy(account_notifications.data() + start_index, buffer_data.data() + start_index, + sizeof(AccountNotificationSettings)); + } + IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); } @@ -177,17 +281,218 @@ void SET_SYS::GetSettingsItemValue(HLERequestContext& ctx) { rb.Push(response); } +void SET_SYS::GetTvSettings(HLERequestContext& ctx) { + LOG_INFO(Service_SET, "called"); + + IPC::ResponseBuilder rb{ctx, 10}; + rb.Push(ResultSuccess); + rb.PushRaw(tv_settings); +} + +void SET_SYS::SetTvSettings(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + tv_settings = rp.PopRaw<TvSettings>(); + + LOG_INFO(Service_SET, + "called, flags={}, cmu_mode={}, constrast_ratio={}, hdmi_content_type={}, " + "rgb_range={}, tv_gama={}, tv_resolution={}, tv_underscan={}", + tv_settings.flags.raw, tv_settings.cmu_mode, tv_settings.constrast_ratio, + tv_settings.hdmi_content_type, tv_settings.rgb_range, tv_settings.tv_gama, + tv_settings.tv_resolution, tv_settings.tv_underscan); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +void SET_SYS::GetQuestFlag(HLERequestContext& ctx) { + LOG_WARNING(Service_SET, "(STUBBED) called"); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.PushEnum(QuestFlag::Retail); +} + +void SET_SYS::SetRegionCode(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + region_code = rp.PopEnum<RegionCode>(); + + LOG_INFO(Service_SET, "called, region_code={}", region_code); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +void SET_SYS::GetPrimaryAlbumStorage(HLERequestContext& ctx) { + LOG_WARNING(Service_SET, "(STUBBED) called"); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.PushEnum(PrimaryAlbumStorage::SdCard); +} + +void SET_SYS::GetSleepSettings(HLERequestContext& ctx) { + LOG_INFO(Service_SET, "called"); + + IPC::ResponseBuilder rb{ctx, 5}; + rb.Push(ResultSuccess); + rb.PushRaw(sleep_settings); +} + +void SET_SYS::SetSleepSettings(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + sleep_settings = rp.PopRaw<SleepSettings>(); + + LOG_INFO(Service_SET, "called, flags={}, handheld_sleep_plan={}, console_sleep_plan={}", + sleep_settings.flags.raw, sleep_settings.handheld_sleep_plan, + sleep_settings.console_sleep_plan); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +void SET_SYS::GetInitialLaunchSettings(HLERequestContext& ctx) { + LOG_INFO(Service_SET, "called"); + IPC::ResponseBuilder rb{ctx, 10}; + rb.Push(ResultSuccess); + rb.PushRaw(launch_settings); +} + +void SET_SYS::SetInitialLaunchSettings(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + launch_settings = rp.PopRaw<InitialLaunchSettings>(); + + LOG_INFO(Service_SET, "called, flags={}, timestamp={}", launch_settings.flags.raw, + launch_settings.timestamp.time_point); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + void SET_SYS::GetDeviceNickName(HLERequestContext& ctx) { LOG_DEBUG(Service_SET, "called"); + + ctx.WriteBuffer(::Settings::values.device_name.GetValue()); + IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ResultSuccess); - ctx.WriteBuffer(::Settings::values.device_name.GetValue()); +} + +void SET_SYS::SetDeviceNickName(HLERequestContext& ctx) { + const std::string device_name = Common::StringFromBuffer(ctx.ReadBuffer()); + + LOG_INFO(Service_SET, "called, device_name={}", device_name); + + ::Settings::values.device_name = device_name; + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +void SET_SYS::GetProductModel(HLERequestContext& ctx) { + const u32 product_model = 1; + + LOG_WARNING(Service_SET, "(STUBBED) called, product_model={}", product_model); + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push(product_model); +} + +void SET_SYS::GetMiiAuthorId(HLERequestContext& ctx) { + const auto author_id = Common::UUID::MakeDefault(); + + LOG_WARNING(Service_SET, "(STUBBED) called, author_id={}", author_id.FormattedString()); + + IPC::ResponseBuilder rb{ctx, 6}; + rb.Push(ResultSuccess); + rb.PushRaw(author_id); +} + +void SET_SYS::GetAutoUpdateEnableFlag(HLERequestContext& ctx) { + u8 auto_update_flag{}; + + LOG_WARNING(Service_SET, "(STUBBED) called, auto_update_flag={}", auto_update_flag); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push(auto_update_flag); +} + +void SET_SYS::GetBatteryPercentageFlag(HLERequestContext& ctx) { + u8 battery_percentage_flag{1}; + + LOG_WARNING(Service_SET, "(STUBBED) called, battery_percentage_flag={}", + battery_percentage_flag); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push(battery_percentage_flag); +} + +void SET_SYS::GetErrorReportSharePermission(HLERequestContext& ctx) { + LOG_WARNING(Service_SET, "(STUBBED) called"); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.PushEnum(ErrorReportSharePermission::Denied); +} + +void SET_SYS::GetAppletLaunchFlags(HLERequestContext& ctx) { + LOG_INFO(Service_SET, "called, applet_launch_flag={}", applet_launch_flag); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push(applet_launch_flag); +} + +void SET_SYS::SetAppletLaunchFlags(HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + applet_launch_flag = rp.Pop<u32>(); + + LOG_INFO(Service_SET, "called, applet_launch_flag={}", applet_launch_flag); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +void SET_SYS::GetKeyboardLayout(HLERequestContext& ctx) { + const auto language_code = + available_language_codes[static_cast<s32>(::Settings::values.language_index.GetValue())]; + const auto key_code = + std::find_if(language_to_layout.cbegin(), language_to_layout.cend(), + [=](const auto& element) { return element.first == language_code; }); + + KeyboardLayout selected_keyboard_layout = KeyboardLayout::EnglishUs; + if (key_code != language_to_layout.end()) { + selected_keyboard_layout = key_code->second; + } + + LOG_INFO(Service_SET, "called, selected_keyboard_layout={}", selected_keyboard_layout); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push(static_cast<u32>(selected_keyboard_layout)); +} + +void SET_SYS::GetChineseTraditionalInputMethod(HLERequestContext& ctx) { + LOG_WARNING(Service_SET, "(STUBBED) called"); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.PushEnum(ChineseTraditionalInputMethod::Unknown0); +} + +void SET_SYS::GetFieldTestingFlag(HLERequestContext& ctx) { + LOG_WARNING(Service_SET, "(STUBBED) called"); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push<u8>(false); } SET_SYS::SET_SYS(Core::System& system_) : ServiceFramework{system_, "set:sys"} { // clang-format off static const FunctionInfo functions[] = { - {0, nullptr, "SetLanguageCode"}, + {0, &SET_SYS::SetLanguageCode, "SetLanguageCode"}, {1, nullptr, "SetNetworkSettings"}, {2, nullptr, "GetNetworkSettings"}, {3, &SET_SYS::GetFirmwareVersion, "GetFirmwareVersion"}, @@ -203,35 +508,35 @@ SET_SYS::SET_SYS(Core::System& system_) : ServiceFramework{system_, "set:sys"} { {14, nullptr, "SetExternalSteadyClockSourceId"}, {15, nullptr, "GetUserSystemClockContext"}, {16, nullptr, "SetUserSystemClockContext"}, - {17, nullptr, "GetAccountSettings"}, - {18, nullptr, "SetAccountSettings"}, + {17, &SET_SYS::GetAccountSettings, "GetAccountSettings"}, + {18, &SET_SYS::SetAccountSettings, "SetAccountSettings"}, {19, nullptr, "GetAudioVolume"}, {20, nullptr, "SetAudioVolume"}, - {21, nullptr, "GetEulaVersions"}, - {22, nullptr, "SetEulaVersions"}, + {21, &SET_SYS::GetEulaVersions, "GetEulaVersions"}, + {22, &SET_SYS::SetEulaVersions, "SetEulaVersions"}, {23, &SET_SYS::GetColorSetId, "GetColorSetId"}, {24, &SET_SYS::SetColorSetId, "SetColorSetId"}, {25, nullptr, "GetConsoleInformationUploadFlag"}, {26, nullptr, "SetConsoleInformationUploadFlag"}, {27, nullptr, "GetAutomaticApplicationDownloadFlag"}, {28, nullptr, "SetAutomaticApplicationDownloadFlag"}, - {29, nullptr, "GetNotificationSettings"}, - {30, nullptr, "SetNotificationSettings"}, - {31, nullptr, "GetAccountNotificationSettings"}, - {32, nullptr, "SetAccountNotificationSettings"}, + {29, &SET_SYS::GetNotificationSettings, "GetNotificationSettings"}, + {30, &SET_SYS::SetNotificationSettings, "SetNotificationSettings"}, + {31, &SET_SYS::GetAccountNotificationSettings, "GetAccountNotificationSettings"}, + {32, &SET_SYS::SetAccountNotificationSettings, "SetAccountNotificationSettings"}, {35, nullptr, "GetVibrationMasterVolume"}, {36, nullptr, "SetVibrationMasterVolume"}, {37, &SET_SYS::GetSettingsItemValueSize, "GetSettingsItemValueSize"}, {38, &SET_SYS::GetSettingsItemValue, "GetSettingsItemValue"}, - {39, nullptr, "GetTvSettings"}, - {40, nullptr, "SetTvSettings"}, + {39, &SET_SYS::GetTvSettings, "GetTvSettings"}, + {40, &SET_SYS::SetTvSettings, "SetTvSettings"}, {41, nullptr, "GetEdid"}, {42, nullptr, "SetEdid"}, {43, nullptr, "GetAudioOutputMode"}, {44, nullptr, "SetAudioOutputMode"}, {45, nullptr, "IsForceMuteOnHeadphoneRemoved"}, {46, nullptr, "SetForceMuteOnHeadphoneRemoved"}, - {47, nullptr, "GetQuestFlag"}, + {47, &SET_SYS::GetQuestFlag, "GetQuestFlag"}, {48, nullptr, "SetQuestFlag"}, {49, nullptr, "GetDataDeletionSettings"}, {50, nullptr, "SetDataDeletionSettings"}, @@ -241,13 +546,13 @@ SET_SYS::SET_SYS(Core::System& system_) : ServiceFramework{system_, "set:sys"} { {54, nullptr, "SetDeviceTimeZoneLocationName"}, {55, nullptr, "GetWirelessCertificationFileSize"}, {56, nullptr, "GetWirelessCertificationFile"}, - {57, nullptr, "SetRegionCode"}, + {57, &SET_SYS::SetRegionCode, "SetRegionCode"}, {58, nullptr, "GetNetworkSystemClockContext"}, {59, nullptr, "SetNetworkSystemClockContext"}, {60, nullptr, "IsUserSystemClockAutomaticCorrectionEnabled"}, {61, nullptr, "SetUserSystemClockAutomaticCorrectionEnabled"}, {62, nullptr, "GetDebugModeFlag"}, - {63, nullptr, "GetPrimaryAlbumStorage"}, + {63, &SET_SYS::GetPrimaryAlbumStorage, "GetPrimaryAlbumStorage"}, {64, nullptr, "SetPrimaryAlbumStorage"}, {65, nullptr, "GetUsb30EnableFlag"}, {66, nullptr, "SetUsb30EnableFlag"}, @@ -255,15 +560,15 @@ SET_SYS::SET_SYS(Core::System& system_) : ServiceFramework{system_, "set:sys"} { {68, nullptr, "GetSerialNumber"}, {69, nullptr, "GetNfcEnableFlag"}, {70, nullptr, "SetNfcEnableFlag"}, - {71, nullptr, "GetSleepSettings"}, - {72, nullptr, "SetSleepSettings"}, + {71, &SET_SYS::GetSleepSettings, "GetSleepSettings"}, + {72, &SET_SYS::SetSleepSettings, "SetSleepSettings"}, {73, nullptr, "GetWirelessLanEnableFlag"}, {74, nullptr, "SetWirelessLanEnableFlag"}, - {75, nullptr, "GetInitialLaunchSettings"}, - {76, nullptr, "SetInitialLaunchSettings"}, + {75, &SET_SYS::GetInitialLaunchSettings, "GetInitialLaunchSettings"}, + {76, &SET_SYS::SetInitialLaunchSettings, "SetInitialLaunchSettings"}, {77, &SET_SYS::GetDeviceNickName, "GetDeviceNickName"}, - {78, nullptr, "SetDeviceNickName"}, - {79, nullptr, "GetProductModel"}, + {78, &SET_SYS::SetDeviceNickName, "SetDeviceNickName"}, + {79, &SET_SYS::GetProductModel, "GetProductModel"}, {80, nullptr, "GetLdnChannel"}, {81, nullptr, "SetLdnChannel"}, {82, nullptr, "AcquireTelemetryDirtyFlagEventHandle"}, @@ -274,16 +579,16 @@ SET_SYS::SET_SYS(Core::System& system_) : ServiceFramework{system_, "set:sys"} { {87, nullptr, "SetPtmFuelGaugeParameter"}, {88, nullptr, "GetBluetoothEnableFlag"}, {89, nullptr, "SetBluetoothEnableFlag"}, - {90, nullptr, "GetMiiAuthorId"}, + {90, &SET_SYS::GetMiiAuthorId, "GetMiiAuthorId"}, {91, nullptr, "SetShutdownRtcValue"}, {92, nullptr, "GetShutdownRtcValue"}, {93, nullptr, "AcquireFatalDirtyFlagEventHandle"}, {94, nullptr, "GetFatalDirtyFlags"}, - {95, nullptr, "GetAutoUpdateEnableFlag"}, + {95, &SET_SYS::GetAutoUpdateEnableFlag, "GetAutoUpdateEnableFlag"}, {96, nullptr, "SetAutoUpdateEnableFlag"}, {97, nullptr, "GetNxControllerSettings"}, {98, nullptr, "SetNxControllerSettings"}, - {99, nullptr, "GetBatteryPercentageFlag"}, + {99, &SET_SYS::GetBatteryPercentageFlag, "GetBatteryPercentageFlag"}, {100, nullptr, "SetBatteryPercentageFlag"}, {101, nullptr, "GetExternalRtcResetFlag"}, {102, nullptr, "SetExternalRtcResetFlag"}, @@ -308,10 +613,10 @@ SET_SYS::SET_SYS(Core::System& system_) : ServiceFramework{system_, "set:sys"} { {121, nullptr, "SetPushNotificationActivityModeOnSleep"}, {122, nullptr, "GetServiceDiscoveryControlSettings"}, {123, nullptr, "SetServiceDiscoveryControlSettings"}, - {124, nullptr, "GetErrorReportSharePermission"}, + {124, &SET_SYS::GetErrorReportSharePermission, "GetErrorReportSharePermission"}, {125, nullptr, "SetErrorReportSharePermission"}, - {126, nullptr, "GetAppletLaunchFlags"}, - {127, nullptr, "SetAppletLaunchFlags"}, + {126, &SET_SYS::GetAppletLaunchFlags, "GetAppletLaunchFlags"}, + {127, &SET_SYS::SetAppletLaunchFlags, "SetAppletLaunchFlags"}, {128, nullptr, "GetConsoleSixAxisSensorAccelerationBias"}, {129, nullptr, "SetConsoleSixAxisSensorAccelerationBias"}, {130, nullptr, "GetConsoleSixAxisSensorAngularVelocityBias"}, @@ -320,7 +625,7 @@ SET_SYS::SET_SYS(Core::System& system_) : ServiceFramework{system_, "set:sys"} { {133, nullptr, "SetConsoleSixAxisSensorAccelerationGain"}, {134, nullptr, "GetConsoleSixAxisSensorAngularVelocityGain"}, {135, nullptr, "SetConsoleSixAxisSensorAngularVelocityGain"}, - {136, nullptr, "GetKeyboardLayout"}, + {136, &SET_SYS::GetKeyboardLayout, "GetKeyboardLayout"}, {137, nullptr, "SetKeyboardLayout"}, {138, nullptr, "GetWebInspectorFlag"}, {139, nullptr, "GetAllowedSslHosts"}, @@ -354,7 +659,7 @@ SET_SYS::SET_SYS(Core::System& system_) : ServiceFramework{system_, "set:sys"} { {167, nullptr, "SetUsb30DeviceEnableFlag"}, {168, nullptr, "GetThemeId"}, {169, nullptr, "SetThemeId"}, - {170, nullptr, "GetChineseTraditionalInputMethod"}, + {170, &SET_SYS::GetChineseTraditionalInputMethod, "GetChineseTraditionalInputMethod"}, {171, nullptr, "SetChineseTraditionalInputMethod"}, {172, nullptr, "GetPtmCycleCountReliability"}, {173, nullptr, "SetPtmCycleCountReliability"}, @@ -385,12 +690,16 @@ SET_SYS::SET_SYS(Core::System& system_) : ServiceFramework{system_, "set:sys"} { {198, nullptr, "SetButtonConfigRegisteredSettingsEmbedded"}, {199, nullptr, "GetButtonConfigRegisteredSettings"}, {200, nullptr, "SetButtonConfigRegisteredSettings"}, - {201, nullptr, "GetFieldTestingFlag"}, + {201, &SET_SYS::GetFieldTestingFlag, "GetFieldTestingFlag"}, {202, nullptr, "SetFieldTestingFlag"}, {203, nullptr, "GetPanelCrcMode"}, {204, nullptr, "SetPanelCrcMode"}, {205, nullptr, "GetNxControllerSettingsEx"}, {206, nullptr, "SetNxControllerSettingsEx"}, + {207, nullptr, "GetHearingProtectionSafeguardFlag"}, + {208, nullptr, "SetHearingProtectionSafeguardFlag"}, + {209, nullptr, "GetHearingProtectionSafeguardRemainingTime"}, + {210, nullptr, "SetHearingProtectionSafeguardRemainingTime"}, }; // clang-format on diff --git a/src/core/hle/service/set/set_sys.h b/src/core/hle/service/set/set_sys.h index 1efbcc97a..c7dba2a9e 100644 --- a/src/core/hle/service/set/set_sys.h +++ b/src/core/hle/service/set/set_sys.h @@ -3,7 +3,9 @@ #pragma once +#include "common/uuid.h" #include "core/hle/service/service.h" +#include "core/hle/service/time/clock_types.h" namespace Core { class System; @@ -23,15 +25,331 @@ private: BasicBlack = 1, }; - void GetSettingsItemValueSize(HLERequestContext& ctx); - void GetSettingsItemValue(HLERequestContext& ctx); + /// Indicates the current console is a retail or kiosk unit + enum class QuestFlag : u8 { + Retail = 0, + Kiosk = 1, + }; + + /// This is nn::settings::system::TvResolution + enum class TvResolution : u32 { + Auto, + Resolution1080p, + Resolution720p, + Resolution480p, + }; + + /// This is nn::settings::system::HdmiContentType + enum class HdmiContentType : u32 { + None, + Graphics, + Cinema, + Photo, + Game, + }; + + /// This is nn::settings::system::RgbRange + enum class RgbRange : u32 { + Auto, + Full, + Limited, + }; + + /// This is nn::settings::system::CmuMode + enum class CmuMode : u32 { + None, + ColorInvert, + HighContrast, + GrayScale, + }; + + /// This is nn::settings::system::PrimaryAlbumStorage + enum class PrimaryAlbumStorage : u32 { + Nand, + SdCard, + }; + + /// This is nn::settings::system::NotificationVolume + enum class NotificationVolume : u32 { + Mute, + Low, + High, + }; + + /// This is nn::settings::system::ChineseTraditionalInputMethod + enum class ChineseTraditionalInputMethod : u32 { + Unknown0 = 0, + Unknown1 = 1, + Unknown2 = 2, + }; + + /// This is nn::settings::system::ErrorReportSharePermission + enum class ErrorReportSharePermission : u32 { + NotConfirmed, + Granted, + Denied, + }; + + /// This is nn::settings::system::FriendPresenceOverlayPermission + enum class FriendPresenceOverlayPermission : u8 { + NotConfirmed, + NoDisplay, + FavoriteFriends, + Friends, + }; + + /// This is nn::settings::system::HandheldSleepPlan + enum class HandheldSleepPlan : u32 { + Sleep1Min, + Sleep3Min, + Sleep5Min, + Sleep10Min, + Sleep30Min, + Never, + }; + + /// This is nn::settings::system::ConsoleSleepPlan + enum class ConsoleSleepPlan : u32 { + Sleep1Hour, + Sleep2Hour, + Sleep3Hour, + Sleep6Hour, + Sleep12Hour, + Never, + }; + + /// This is nn::settings::system::RegionCode + enum class RegionCode : u32 { + Japan, + Usa, + Europe, + Australia, + HongKongTaiwanKorea, + China, + }; + + /// This is nn::settings::system::EulaVersionClockType + enum class EulaVersionClockType : u32 { + NetworkSystemClock, + SteadyClock, + }; + + /// This is nn::settings::system::SleepFlag + struct SleepFlag { + union { + u32 raw{}; + + BitField<0, 1, u32> SleepsWhilePlayingMedia; + BitField<1, 1, u32> WakesAtPowerStateChange; + }; + }; + static_assert(sizeof(SleepFlag) == 4, "TvFlag is an invalid size"); + + /// This is nn::settings::system::TvFlag + struct TvFlag { + union { + u32 raw{}; + + BitField<0, 1, u32> Allows4k; + BitField<1, 1, u32> Allows3d; + BitField<2, 1, u32> AllowsCec; + BitField<3, 1, u32> PreventsScreenBurnIn; + }; + }; + static_assert(sizeof(TvFlag) == 4, "TvFlag is an invalid size"); + + /// This is nn::settings::system::InitialLaunchFlag + struct InitialLaunchFlag { + union { + u32 raw{}; + + BitField<0, 1, u32> InitialLaunchCompletionFlag; + BitField<8, 1, u32> InitialLaunchUserAdditionFlag; + BitField<16, 1, u32> InitialLaunchTimestampFlag; + }; + }; + static_assert(sizeof(InitialLaunchFlag) == 4, "InitialLaunchFlag is an invalid size"); + + /// This is nn::settings::system::NotificationFlag + struct NotificationFlag { + union { + u32 raw{}; + + BitField<0, 1, u32> RingtoneFlag; + BitField<1, 1, u32> DownloadCompletionFlag; + BitField<8, 1, u32> EnablesNews; + BitField<9, 1, u32> IncomingLampFlag; + }; + }; + static_assert(sizeof(NotificationFlag) == 4, "NotificationFlag is an invalid size"); + + /// This is nn::settings::system::AccountNotificationFlag + struct AccountNotificationFlag { + union { + u32 raw{}; + + BitField<0, 1, u32> FriendOnlineFlag; + BitField<1, 1, u32> FriendRequestFlag; + BitField<8, 1, u32> CoralInvitationFlag; + }; + }; + static_assert(sizeof(AccountNotificationFlag) == 4, + "AccountNotificationFlag is an invalid size"); + + /// This is nn::settings::system::TvSettings + struct TvSettings { + TvFlag flags; + TvResolution tv_resolution; + HdmiContentType hdmi_content_type; + RgbRange rgb_range; + CmuMode cmu_mode; + u32 tv_underscan; + f32 tv_gama; + f32 constrast_ratio; + }; + static_assert(sizeof(TvSettings) == 0x20, "TvSettings is an invalid size"); + + /// This is nn::settings::system::NotificationTime + struct NotificationTime { + u32 hour; + u32 minute; + }; + static_assert(sizeof(NotificationTime) == 0x8, "NotificationTime is an invalid size"); + + /// This is nn::settings::system::NotificationSettings + struct NotificationSettings { + NotificationFlag flags; + NotificationVolume volume; + NotificationTime start_time; + NotificationTime stop_time; + }; + static_assert(sizeof(NotificationSettings) == 0x18, "NotificationSettings is an invalid size"); + + /// This is nn::settings::system::AccountSettings + struct AccountSettings { + u32 flags; + }; + static_assert(sizeof(AccountSettings) == 0x4, "AccountSettings is an invalid size"); + + /// This is nn::settings::system::AccountNotificationSettings + struct AccountNotificationSettings { + Common::UUID uid; + AccountNotificationFlag flags; + FriendPresenceOverlayPermission friend_presence_permission; + FriendPresenceOverlayPermission friend_invitation_permission; + INSERT_PADDING_BYTES(0x2); + }; + static_assert(sizeof(AccountNotificationSettings) == 0x18, + "AccountNotificationSettings is an invalid size"); + + /// This is nn::settings::system::InitialLaunchSettings + struct SleepSettings { + SleepFlag flags; + HandheldSleepPlan handheld_sleep_plan; + ConsoleSleepPlan console_sleep_plan; + }; + static_assert(sizeof(SleepSettings) == 0xc, "SleepSettings is incorrect size"); + + /// This is nn::settings::system::InitialLaunchSettings + struct InitialLaunchSettings { + InitialLaunchFlag flags; + INSERT_PADDING_BYTES(0x4); + Time::Clock::SteadyClockTimePoint timestamp; + }; + static_assert(sizeof(InitialLaunchSettings) == 0x20, "InitialLaunchSettings is incorrect size"); + + /// This is nn::settings::system::InitialLaunchSettings + struct EulaVersion { + u32 version; + RegionCode region_code; + EulaVersionClockType clock_type; + INSERT_PADDING_BYTES(0x4); + s64 posix_time; + Time::Clock::SteadyClockTimePoint timestamp; + }; + static_assert(sizeof(EulaVersion) == 0x30, "EulaVersion is incorrect size"); + + void SetLanguageCode(HLERequestContext& ctx); void GetFirmwareVersion(HLERequestContext& ctx); void GetFirmwareVersion2(HLERequestContext& ctx); + void GetAccountSettings(HLERequestContext& ctx); + void SetAccountSettings(HLERequestContext& ctx); + void GetEulaVersions(HLERequestContext& ctx); + void SetEulaVersions(HLERequestContext& ctx); void GetColorSetId(HLERequestContext& ctx); void SetColorSetId(HLERequestContext& ctx); + void GetNotificationSettings(HLERequestContext& ctx); + void SetNotificationSettings(HLERequestContext& ctx); + void GetAccountNotificationSettings(HLERequestContext& ctx); + void SetAccountNotificationSettings(HLERequestContext& ctx); + void GetSettingsItemValueSize(HLERequestContext& ctx); + void GetSettingsItemValue(HLERequestContext& ctx); + void GetTvSettings(HLERequestContext& ctx); + void SetTvSettings(HLERequestContext& ctx); + void GetQuestFlag(HLERequestContext& ctx); + void SetRegionCode(HLERequestContext& ctx); + void GetPrimaryAlbumStorage(HLERequestContext& ctx); + void GetSleepSettings(HLERequestContext& ctx); + void SetSleepSettings(HLERequestContext& ctx); + void GetInitialLaunchSettings(HLERequestContext& ctx); + void SetInitialLaunchSettings(HLERequestContext& ctx); void GetDeviceNickName(HLERequestContext& ctx); + void SetDeviceNickName(HLERequestContext& ctx); + void GetProductModel(HLERequestContext& ctx); + void GetMiiAuthorId(HLERequestContext& ctx); + void GetAutoUpdateEnableFlag(HLERequestContext& ctx); + void GetBatteryPercentageFlag(HLERequestContext& ctx); + void GetErrorReportSharePermission(HLERequestContext& ctx); + void GetAppletLaunchFlags(HLERequestContext& ctx); + void SetAppletLaunchFlags(HLERequestContext& ctx); + void GetKeyboardLayout(HLERequestContext& ctx); + void GetChineseTraditionalInputMethod(HLERequestContext& ctx); + void GetFieldTestingFlag(HLERequestContext& ctx); + + AccountSettings account_settings{ + .flags = {}, + }; ColorSet color_set = ColorSet::BasicWhite; + + NotificationSettings notification_settings{ + .flags = {0x300}, + .volume = NotificationVolume::High, + .start_time = {.hour = 9, .minute = 0}, + .stop_time = {.hour = 21, .minute = 0}, + }; + + std::vector<AccountNotificationSettings> account_notifications{}; + + TvSettings tv_settings{ + .flags = {0xc}, + .tv_resolution = TvResolution::Auto, + .hdmi_content_type = HdmiContentType::Game, + .rgb_range = RgbRange::Auto, + .cmu_mode = CmuMode::None, + .tv_underscan = {}, + .tv_gama = 1.0f, + .constrast_ratio = 0.5f, + }; + + InitialLaunchSettings launch_settings{ + .flags = {0x10001}, + .timestamp = {}, + }; + + SleepSettings sleep_settings{ + .flags = {0x3}, + .handheld_sleep_plan = HandheldSleepPlan::Sleep10Min, + .console_sleep_plan = ConsoleSleepPlan::Sleep1Hour, + }; + + u32 applet_launch_flag{}; + + std::vector<EulaVersion> eula_versions{}; + + RegionCode region_code; + + LanguageCode language_code_setting; }; } // namespace Service::Set diff --git a/src/shader_recompiler/environment.h b/src/shader_recompiler/environment.h index 26e8307c1..15285ab0a 100644 --- a/src/shader_recompiler/environment.h +++ b/src/shader_recompiler/environment.h @@ -39,7 +39,7 @@ public: [[nodiscard]] virtual std::optional<ReplaceConstant> GetReplaceConstBuffer(u32 bank, u32 offset) = 0; - virtual void Dump(u64 hash) = 0; + virtual void Dump(u64 pipeline_hash, u64 shader_hash) = 0; [[nodiscard]] const ProgramHeader& SPH() const noexcept { return sph; diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp index 618cb6354..2888e0238 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp @@ -445,7 +445,8 @@ std::unique_ptr<GraphicsPipeline> ShaderCache::CreateGraphicsPipeline( ShaderContext::ShaderPools& pools, const GraphicsPipelineKey& key, std::span<Shader::Environment* const> envs, bool use_shader_workers, bool force_context_flush) try { - LOG_INFO(Render_OpenGL, "0x{:016x}", key.Hash()); + auto hash = key.Hash(); + LOG_INFO(Render_OpenGL, "0x{:016x}", hash); size_t env_index{}; u32 total_storage_buffers{}; std::array<Shader::IR::Program, Maxwell::MaxShaderProgram> programs; @@ -474,7 +475,7 @@ std::unique_ptr<GraphicsPipeline> ShaderCache::CreateGraphicsPipeline( Shader::Maxwell::Flow::CFG cfg(env, pools.flow_block, cfg_offset, index == 0); if (Settings::values.dump_shaders) { - env.Dump(key.unique_hashes[index]); + env.Dump(hash, key.unique_hashes[index]); } if (!uses_vertex_a || index != 1) { @@ -566,12 +567,13 @@ std::unique_ptr<ComputePipeline> ShaderCache::CreateComputePipeline( std::unique_ptr<ComputePipeline> ShaderCache::CreateComputePipeline( ShaderContext::ShaderPools& pools, const ComputePipelineKey& key, Shader::Environment& env, bool force_context_flush) try { - LOG_INFO(Render_OpenGL, "0x{:016x}", key.Hash()); + auto hash = key.Hash(); + LOG_INFO(Render_OpenGL, "0x{:016x}", hash); Shader::Maxwell::Flow::CFG cfg{env, pools.flow_block, env.StartAddress()}; if (Settings::values.dump_shaders) { - env.Dump(key.Hash()); + env.Dump(hash, key.unique_hash); } auto program{TranslateProgram(pools.inst, pools.block, env, cfg, host_info)}; diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index 4f84d8497..c1314ca99 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -584,7 +584,8 @@ std::unique_ptr<GraphicsPipeline> PipelineCache::CreateGraphicsPipeline( ShaderPools& pools, const GraphicsPipelineCacheKey& key, std::span<Shader::Environment* const> envs, PipelineStatistics* statistics, bool build_in_parallel) try { - LOG_INFO(Render_Vulkan, "0x{:016x}", key.Hash()); + auto hash = key.Hash(); + LOG_INFO(Render_Vulkan, "0x{:016x}", hash); size_t env_index{0}; std::array<Shader::IR::Program, Maxwell::MaxShaderProgram> programs; const bool uses_vertex_a{key.unique_hashes[0] != 0}; @@ -611,7 +612,7 @@ std::unique_ptr<GraphicsPipeline> PipelineCache::CreateGraphicsPipeline( const u32 cfg_offset{static_cast<u32>(env.StartAddress() + sizeof(Shader::ProgramHeader))}; Shader::Maxwell::Flow::CFG cfg(env, pools.flow_block, cfg_offset, index == 0); if (Settings::values.dump_shaders) { - env.Dump(key.unique_hashes[index]); + env.Dump(hash, key.unique_hashes[index]); } if (!uses_vertex_a || index != 1) { // Normal path @@ -712,18 +713,19 @@ std::unique_ptr<ComputePipeline> PipelineCache::CreateComputePipeline( std::unique_ptr<ComputePipeline> PipelineCache::CreateComputePipeline( ShaderPools& pools, const ComputePipelineCacheKey& key, Shader::Environment& env, PipelineStatistics* statistics, bool build_in_parallel) try { + auto hash = key.Hash(); if (device.HasBrokenCompute()) { - LOG_ERROR(Render_Vulkan, "Skipping 0x{:016x}", key.Hash()); + LOG_ERROR(Render_Vulkan, "Skipping 0x{:016x}", hash); return nullptr; } - LOG_INFO(Render_Vulkan, "0x{:016x}", key.Hash()); + LOG_INFO(Render_Vulkan, "0x{:016x}", hash); Shader::Maxwell::Flow::CFG cfg{env, pools.flow_block, env.StartAddress()}; // Dump it before error. if (Settings::values.dump_shaders) { - env.Dump(key.Hash()); + env.Dump(hash, key.unique_hash); } auto program{TranslateProgram(pools.inst, pools.block, env, cfg, host_info)}; diff --git a/src/video_core/shader_cache.cpp b/src/video_core/shader_cache.cpp index 01701201d..e81cd031b 100644 --- a/src/video_core/shader_cache.cpp +++ b/src/video_core/shader_cache.cpp @@ -51,6 +51,11 @@ bool ShaderCache::RefreshStages(std::array<u64, 6>& unique_hashes) { } const auto& shader_config{maxwell3d->regs.pipelines[index]}; const auto program{static_cast<Tegra::Engines::Maxwell3D::Regs::ShaderType>(index)}; + if (program == Tegra::Engines::Maxwell3D::Regs::ShaderType::Pixel && + !maxwell3d->regs.rasterize_enable) { + unique_hashes[index] = 0; + continue; + } const GPUVAddr shader_addr{base_addr + shader_config.offset}; const std::optional<VAddr> cpu_shader_addr{gpu_memory->GpuToCpuAddress(shader_addr)}; if (!cpu_shader_addr) { diff --git a/src/video_core/shader_cache.h b/src/video_core/shader_cache.h index de8e08002..a76896620 100644 --- a/src/video_core/shader_cache.h +++ b/src/video_core/shader_cache.h @@ -70,7 +70,7 @@ public: protected: struct GraphicsEnvironments { std::array<GraphicsEnvironment, NUM_PROGRAMS> envs; - std::array<Shader::Environment*, NUM_PROGRAMS> env_ptrs; + std::array<Shader::Environment*, NUM_PROGRAMS> env_ptrs{}; std::span<Shader::Environment* const> Span() const noexcept { return std::span(env_ptrs.begin(), std::ranges::find(env_ptrs, nullptr)); diff --git a/src/video_core/shader_environment.cpp b/src/video_core/shader_environment.cpp index c7cb56243..4edbe5700 100644 --- a/src/video_core/shader_environment.cpp +++ b/src/video_core/shader_environment.cpp @@ -102,7 +102,8 @@ static std::string_view StageToPrefix(Shader::Stage stage) { } } -static void DumpImpl(u64 hash, const u64* code, u32 read_highest, u32 read_lowest, +static void DumpImpl(u64 pipeline_hash, u64 shader_hash, std::span<const u64> code, + [[maybe_unused]] u32 read_highest, [[maybe_unused]] u32 read_lowest, u32 initial_offset, Shader::Stage stage) { const auto shader_dir{Common::FS::GetYuzuPath(Common::FS::YuzuPath::DumpDir)}; const auto base_dir{shader_dir / "shaders"}; @@ -111,13 +112,18 @@ static void DumpImpl(u64 hash, const u64* code, u32 read_highest, u32 read_lowes return; } const auto prefix = StageToPrefix(stage); - const auto name{base_dir / fmt::format("{}{:016x}.ash", prefix, hash)}; - const size_t real_size = read_highest - read_lowest + initial_offset; - const size_t padding_needed = ((32 - (real_size % 32)) % 32); + const auto name{base_dir / + fmt::format("{:016x}_{}_{:016x}.ash", pipeline_hash, prefix, shader_hash)}; std::fstream shader_file(name, std::ios::out | std::ios::binary); + ASSERT(initial_offset % sizeof(u64) == 0); const size_t jump_index = initial_offset / sizeof(u64); - shader_file.write(reinterpret_cast<const char*>(code + jump_index), real_size); - for (size_t i = 0; i < padding_needed; i++) { + const size_t code_size = code.size_bytes() - initial_offset; + shader_file.write(reinterpret_cast<const char*>(&code[jump_index]), code_size); + + // + 1 instruction, due to the fact that we skip the final self branch instruction in the code, + // but we need to consider it for padding, otherwise nvdisasm rages. + const size_t padding_needed = (32 - ((code_size + INST_SIZE) % 32)) % 32; + for (size_t i = 0; i < INST_SIZE + padding_needed; i++) { shader_file.put(0); } } @@ -197,8 +203,8 @@ u64 GenericEnvironment::CalculateHash() const { return Common::CityHash64(data.get(), size); } -void GenericEnvironment::Dump(u64 hash) { - DumpImpl(hash, code.data(), read_highest, read_lowest, initial_offset, stage); +void GenericEnvironment::Dump(u64 pipeline_hash, u64 shader_hash) { + DumpImpl(pipeline_hash, shader_hash, code, read_highest, read_lowest, initial_offset, stage); } void GenericEnvironment::Serialize(std::ofstream& file) const { @@ -282,6 +288,7 @@ std::optional<u64> GenericEnvironment::TryFindSize() { Tegra::Texture::TICEntry GenericEnvironment::ReadTextureInfo(GPUVAddr tic_addr, u32 tic_limit, bool via_header_index, u32 raw) { const auto handle{Tegra::Texture::TexturePair(raw, via_header_index)}; + ASSERT(handle.first <= tic_limit); const GPUVAddr descriptor_addr{tic_addr + handle.first * sizeof(Tegra::Texture::TICEntry)}; Tegra::Texture::TICEntry entry; gpu_memory->ReadBlock(descriptor_addr, &entry, sizeof(entry)); @@ -465,8 +472,8 @@ void FileEnvironment::Deserialize(std::ifstream& file) { .read(reinterpret_cast<char*>(&read_highest), sizeof(read_highest)) .read(reinterpret_cast<char*>(&viewport_transform_state), sizeof(viewport_transform_state)) .read(reinterpret_cast<char*>(&stage), sizeof(stage)); - code = std::make_unique<u64[]>(Common::DivCeil(code_size, sizeof(u64))); - file.read(reinterpret_cast<char*>(code.get()), code_size); + code.resize(Common::DivCeil(code_size, sizeof(u64))); + file.read(reinterpret_cast<char*>(code.data()), code_size); for (size_t i = 0; i < num_texture_types; ++i) { u32 key; Shader::TextureType type; @@ -509,8 +516,8 @@ void FileEnvironment::Deserialize(std::ifstream& file) { is_propietary_driver = texture_bound == 2; } -void FileEnvironment::Dump(u64 hash) { - DumpImpl(hash, code.get(), read_highest, read_lowest, initial_offset, stage); +void FileEnvironment::Dump(u64 pipeline_hash, u64 shader_hash) { + DumpImpl(pipeline_hash, shader_hash, code, read_highest, read_lowest, initial_offset, stage); } u64 FileEnvironment::ReadInstruction(u32 address) { diff --git a/src/video_core/shader_environment.h b/src/video_core/shader_environment.h index a0f61cbda..b90f3d44e 100644 --- a/src/video_core/shader_environment.h +++ b/src/video_core/shader_environment.h @@ -58,7 +58,7 @@ public: [[nodiscard]] u64 CalculateHash() const; - void Dump(u64 hash) override; + void Dump(u64 pipeline_hash, u64 shader_hash) override; void Serialize(std::ofstream& file) const; @@ -188,10 +188,10 @@ public: return cbuf_replacements.size() != 0; } - void Dump(u64 hash) override; + void Dump(u64 pipeline_hash, u64 shader_hash) override; private: - std::unique_ptr<u64[]> code; + std::vector<u64> code; std::unordered_map<u32, Shader::TextureType> texture_types; std::unordered_map<u32, Shader::TexturePixelFormat> texture_pixel_formats; std::unordered_map<u64, u32> cbuf_values; |