Compare commits
19 Commits
android-29
...
android-35
Author | SHA1 | Date | |
---|---|---|---|
34df3d2f72 | |||
85e3575496 | |||
7f55c377b0 | |||
9893a4d918 | |||
bed2fc8707 | |||
8d2f0dc707 | |||
cb0b8442f0 | |||
089e385944 | |||
0d470b57ed | |||
755f45a522 | |||
4533769f7f | |||
00d9a9c44e | |||
35bdd5fff3 | |||
7707768f80 | |||
ae19eb1e10 | |||
a09507f271 | |||
dfb7fc8293 | |||
4bd4a95d84 | |||
dd1cbd9c56 |
10
README.md
10
README.md
@ -1,3 +1,11 @@
|
||||
| Pull Request | Commit | Title | Author | Merged? |
|
||||
|----|----|----|----|----|
|
||||
|
||||
|
||||
End of merge log. You can find the original README.md below the break.
|
||||
|
||||
-----
|
||||
|
||||
<!--
|
||||
SPDX-FileCopyrightText: 2018 yuzu Emulator Project
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
@ -40,7 +48,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!
|
||||
|
||||
|
@ -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"} {
|
||||
|
@ -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_);
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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> {
|
||||
|
@ -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::GetDeviceNickName(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_SET, "called");
|
||||
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);
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -106,6 +106,43 @@ bool IsASTCSupported() {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool HasSlowSoftwareAstc(std::string_view vendor_name, std::string_view renderer) {
|
||||
// ifdef for Unix reduces string comparisons for non-Windows drivers, and Intel
|
||||
#ifdef YUZU_UNIX
|
||||
// Sorted vaguely by how likely a vendor is to appear
|
||||
if (vendor_name == "AMD") {
|
||||
// RadeonSI
|
||||
return true;
|
||||
}
|
||||
if (vendor_name == "Intel") {
|
||||
// Must be inside YUZU_UNIX ifdef as the Windows driver uses the same vendor string
|
||||
// iris, crocus
|
||||
const bool is_intel_dg = (renderer.find("DG") != std::string_view::npos);
|
||||
return is_intel_dg;
|
||||
}
|
||||
if (vendor_name == "nouveau") {
|
||||
return true;
|
||||
}
|
||||
if (vendor_name == "X.Org") {
|
||||
// R600
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
if (vendor_name == "Collabora Ltd") {
|
||||
// Zink
|
||||
return true;
|
||||
}
|
||||
if (vendor_name == "Microsoft Corporation") {
|
||||
// d3d12
|
||||
return true;
|
||||
}
|
||||
if (vendor_name == "Mesa/X.org") {
|
||||
// llvmpipe, softpipe, virgl
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
[[nodiscard]] bool IsDebugToolAttached(std::span<const std::string_view> extensions) {
|
||||
const bool nsight = std::getenv("NVTX_INJECTION64_PATH") || std::getenv("NSIGHT_LAUNCHED");
|
||||
return nsight || HasExtension(extensions, "GL_EXT_debug_tool") ||
|
||||
@ -120,12 +157,16 @@ Device::Device(Core::Frontend::EmuWindow& emu_window) {
|
||||
}
|
||||
vendor_name = reinterpret_cast<const char*>(glGetString(GL_VENDOR));
|
||||
const std::string_view version = reinterpret_cast<const char*>(glGetString(GL_VERSION));
|
||||
const std::string_view renderer = reinterpret_cast<const char*>(glGetString(GL_RENDERER));
|
||||
const std::vector extensions = GetExtensions();
|
||||
|
||||
const bool is_nvidia = vendor_name == "NVIDIA Corporation";
|
||||
const bool is_amd = vendor_name == "ATI Technologies Inc.";
|
||||
const bool is_intel = vendor_name == "Intel";
|
||||
|
||||
const bool has_slow_software_astc =
|
||||
!is_nvidia && !is_amd && HasSlowSoftwareAstc(vendor_name, renderer);
|
||||
|
||||
#ifdef __unix__
|
||||
constexpr bool is_linux = true;
|
||||
#else
|
||||
@ -152,7 +193,7 @@ Device::Device(Core::Frontend::EmuWindow& emu_window) {
|
||||
has_vertex_viewport_layer = GLAD_GL_ARB_shader_viewport_layer_array;
|
||||
has_image_load_formatted = HasExtension(extensions, "GL_EXT_shader_image_load_formatted");
|
||||
has_texture_shadow_lod = HasExtension(extensions, "GL_EXT_texture_shadow_lod");
|
||||
has_astc = IsASTCSupported();
|
||||
has_astc = !has_slow_software_astc && IsASTCSupported();
|
||||
has_variable_aoffi = TestVariableAoffi();
|
||||
has_component_indexing_bug = is_amd;
|
||||
has_precise_bug = TestPreciseBug();
|
||||
|
@ -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)};
|
||||
|
@ -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)};
|
||||
|
@ -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) {
|
||||
|
@ -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));
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
Reference in New Issue
Block a user