summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README.md2
-rw-r--r--src/core/hle/service/am/am.cpp44
-rw-r--r--src/core/hle/service/am/am.h30
-rw-r--r--src/core/hle/service/am/applet_ae.cpp8
-rw-r--r--src/core/hle/service/audio/audctl.cpp46
-rw-r--r--src/core/hle/service/audio/audctl.h22
-rw-r--r--src/core/hle/service/olsc/olsc.cpp158
-rw-r--r--src/core/hle/service/pctl/pctl_module.cpp152
-rw-r--r--src/core/hle/service/set/set.cpp60
-rw-r--r--src/core/hle/service/set/set.h61
-rw-r--r--src/core/hle/service/set/set_sys.cpp375
-rw-r--r--src/core/hle/service/set/set_sys.h322
-rw-r--r--src/shader_recompiler/environment.h2
-rw-r--r--src/video_core/renderer_opengl/gl_shader_cache.cpp10
-rw-r--r--src/video_core/renderer_vulkan/vk_pipeline_cache.cpp12
-rw-r--r--src/video_core/shader_cache.cpp5
-rw-r--r--src/video_core/shader_cache.h2
-rw-r--r--src/video_core/shader_environment.cpp31
-rw-r--r--src/video_core/shader_environment.h6
19 files changed, 1171 insertions, 177 deletions
diff --git a/README.md b/README.md
index 1d5b4626f..d258584bf 100644
--- a/README.md
+++ b/README.md
@@ -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;