diff options
Diffstat (limited to 'src/core/hle')
22 files changed, 298 insertions, 59 deletions
diff --git a/src/core/hle/kernel/handle_table.cpp b/src/core/hle/kernel/handle_table.cpp index e441a27fc..35448b576 100644 --- a/src/core/hle/kernel/handle_table.cpp +++ b/src/core/hle/kernel/handle_table.cpp @@ -30,6 +30,7 @@ HandleTable::~HandleTable() = default; ResultCode HandleTable::SetSize(s32 handle_table_size) { if (static_cast<u32>(handle_table_size) > MAX_COUNT) { + LOG_ERROR(Kernel, "Handle table size {} is greater than {}", handle_table_size, MAX_COUNT); return ERR_OUT_OF_MEMORY; } @@ -80,6 +81,7 @@ ResultVal<Handle> HandleTable::Duplicate(Handle handle) { ResultCode HandleTable::Close(Handle handle) { if (!IsValid(handle)) { + LOG_ERROR(Kernel, "Handle is not valid! handle={:08X}", handle); return ERR_INVALID_HANDLE; } diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp index eff4e45b0..7869eb32b 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp @@ -7,6 +7,7 @@ #include <vector> #include "common/assert.h" +#include "common/logging/log.h" #include "core/core.h" #include "core/hle/kernel/errors.h" #include "core/hle/kernel/handle_table.h" @@ -67,6 +68,7 @@ ResultCode Mutex::TryAcquire(VAddr address, Handle holding_thread_handle, Handle requesting_thread_handle) { // The mutex address must be 4-byte aligned if ((address % sizeof(u32)) != 0) { + LOG_ERROR(Kernel, "Address is not 4-byte aligned! address={:016X}", address); return ERR_INVALID_ADDRESS; } @@ -88,6 +90,8 @@ ResultCode Mutex::TryAcquire(VAddr address, Handle holding_thread_handle, } if (holding_thread == nullptr) { + LOG_ERROR(Kernel, "Holding thread does not exist! thread_handle={:08X}", + holding_thread_handle); return ERR_INVALID_HANDLE; } @@ -109,6 +113,7 @@ ResultCode Mutex::TryAcquire(VAddr address, Handle holding_thread_handle, ResultCode Mutex::Release(VAddr address) { // The mutex address must be 4-byte aligned if ((address % sizeof(u32)) != 0) { + LOG_ERROR(Kernel, "Address is not 4-byte aligned! address={:016X}", address); return ERR_INVALID_ADDRESS; } diff --git a/src/core/hle/kernel/process_capability.cpp b/src/core/hle/kernel/process_capability.cpp index 48e5ae682..63880f13d 100644 --- a/src/core/hle/kernel/process_capability.cpp +++ b/src/core/hle/kernel/process_capability.cpp @@ -3,6 +3,7 @@ // Refer to the license.txt file included. #include "common/bit_util.h" +#include "common/logging/log.h" #include "core/hle/kernel/errors.h" #include "core/hle/kernel/handle_table.h" #include "core/hle/kernel/memory/page_table.h" @@ -119,22 +120,30 @@ ResultCode ProcessCapabilities::ParseCapabilities(const u32* capabilities, // The MapPhysical type uses two descriptor flags for its parameters. // If there's only one, then there's a problem. if (i >= num_capabilities) { + LOG_ERROR(Kernel, "Invalid combination! i={}", i); return ERR_INVALID_COMBINATION; } const auto size_flags = capabilities[i]; if (GetCapabilityType(size_flags) != CapabilityType::MapPhysical) { + LOG_ERROR(Kernel, "Invalid capability type! size_flags={}", size_flags); return ERR_INVALID_COMBINATION; } const auto result = HandleMapPhysicalFlags(descriptor, size_flags, page_table); if (result.IsError()) { + LOG_ERROR(Kernel, "Failed to map physical flags! descriptor={}, size_flags={}", + descriptor, size_flags); return result; } } else { const auto result = ParseSingleFlagCapability(set_flags, set_svc_bits, descriptor, page_table); if (result.IsError()) { + LOG_ERROR( + Kernel, + "Failed to parse capability flag! set_flags={}, set_svc_bits={}, descriptor={}", + set_flags, set_svc_bits, descriptor); return result; } } @@ -162,6 +171,9 @@ ResultCode ProcessCapabilities::ParseSingleFlagCapability(u32& set_flags, u32& s const u32 flag_length = GetFlagBitOffset(type); const u32 set_flag = 1U << flag_length; if ((set_flag & set_flags & InitializeOnceMask) != 0) { + LOG_ERROR(Kernel, + "Attempted to initialize flags that may only be initialized once. set_flags={}", + set_flags); return ERR_INVALID_COMBINATION; } set_flags |= set_flag; @@ -187,6 +199,7 @@ ResultCode ProcessCapabilities::ParseSingleFlagCapability(u32& set_flags, u32& s break; } + LOG_ERROR(Kernel, "Invalid capability type! type={}", static_cast<u32>(type)); return ERR_INVALID_CAPABILITY_DESCRIPTOR; } @@ -208,23 +221,31 @@ void ProcessCapabilities::Clear() { ResultCode ProcessCapabilities::HandlePriorityCoreNumFlags(u32 flags) { if (priority_mask != 0 || core_mask != 0) { + LOG_ERROR(Kernel, "Core or priority mask are not zero! priority_mask={}, core_mask={}", + priority_mask, core_mask); return ERR_INVALID_CAPABILITY_DESCRIPTOR; } const u32 core_num_min = (flags >> 16) & 0xFF; const u32 core_num_max = (flags >> 24) & 0xFF; if (core_num_min > core_num_max) { + LOG_ERROR(Kernel, "Core min is greater than core max! core_num_min={}, core_num_max={}", + core_num_min, core_num_max); return ERR_INVALID_COMBINATION; } const u32 priority_min = (flags >> 10) & 0x3F; const u32 priority_max = (flags >> 4) & 0x3F; if (priority_min > priority_max) { + LOG_ERROR(Kernel, + "Priority min is greater than priority max! priority_min={}, priority_max={}", + core_num_min, priority_max); return ERR_INVALID_COMBINATION; } // The switch only has 4 usable cores. if (core_num_max >= 4) { + LOG_ERROR(Kernel, "Invalid max cores specified! core_num_max={}", core_num_max); return ERR_INVALID_PROCESSOR_ID; } @@ -259,6 +280,7 @@ ResultCode ProcessCapabilities::HandleSyscallFlags(u32& set_svc_bits, u32 flags) } if (svc_number >= svc_capabilities.size()) { + LOG_ERROR(Kernel, "Process svc capability is out of range! svc_number={}", svc_number); return ERR_OUT_OF_RANGE; } @@ -295,6 +317,8 @@ ResultCode ProcessCapabilities::HandleInterruptFlags(u32 flags) { // emulate that, it's sufficient to mark every interrupt as defined. if (interrupt >= interrupt_capabilities.size()) { + LOG_ERROR(Kernel, "Process interrupt capability is out of range! svc_number={}", + interrupt); return ERR_OUT_OF_RANGE; } @@ -307,6 +331,7 @@ ResultCode ProcessCapabilities::HandleInterruptFlags(u32 flags) { ResultCode ProcessCapabilities::HandleProgramTypeFlags(u32 flags) { const u32 reserved = flags >> 17; if (reserved != 0) { + LOG_ERROR(Kernel, "Reserved value is non-zero! reserved={}", reserved); return ERR_RESERVED_VALUE; } @@ -324,6 +349,9 @@ ResultCode ProcessCapabilities::HandleKernelVersionFlags(u32 flags) { const u32 major_version = kernel_version >> 19; if (major_version != 0 || flags < 0x80000) { + LOG_ERROR(Kernel, + "Kernel version is non zero or flags are too small! major_version={}, flags={}", + major_version, flags); return ERR_INVALID_CAPABILITY_DESCRIPTOR; } @@ -334,6 +362,7 @@ ResultCode ProcessCapabilities::HandleKernelVersionFlags(u32 flags) { ResultCode ProcessCapabilities::HandleHandleTableFlags(u32 flags) { const u32 reserved = flags >> 26; if (reserved != 0) { + LOG_ERROR(Kernel, "Reserved value is non-zero! reserved={}", reserved); return ERR_RESERVED_VALUE; } @@ -344,6 +373,7 @@ ResultCode ProcessCapabilities::HandleHandleTableFlags(u32 flags) { ResultCode ProcessCapabilities::HandleDebugFlags(u32 flags) { const u32 reserved = flags >> 19; if (reserved != 0) { + LOG_ERROR(Kernel, "Reserved value is non-zero! reserved={}", reserved); return ERR_RESERVED_VALUE; } diff --git a/src/core/hle/kernel/readable_event.cpp b/src/core/hle/kernel/readable_event.cpp index 9d3d3a81b..e2a404d07 100644 --- a/src/core/hle/kernel/readable_event.cpp +++ b/src/core/hle/kernel/readable_event.cpp @@ -4,6 +4,7 @@ #include <algorithm> #include "common/assert.h" +#include "common/logging/log.h" #include "core/hle/kernel/errors.h" #include "core/hle/kernel/object.h" #include "core/hle/kernel/readable_event.h" @@ -35,6 +36,8 @@ void ReadableEvent::Clear() { ResultCode ReadableEvent::Reset() { if (!is_signaled) { + LOG_ERROR(Kernel, "Handle is not signaled! object_id={}, object_type={}, object_name={}", + GetObjectId(), GetTypeName(), GetName()); return ERR_INVALID_STATE; } diff --git a/src/core/hle/kernel/resource_limit.cpp b/src/core/hle/kernel/resource_limit.cpp index 96e5b9892..d9beaa3a4 100644 --- a/src/core/hle/kernel/resource_limit.cpp +++ b/src/core/hle/kernel/resource_limit.cpp @@ -69,6 +69,8 @@ ResultCode ResourceLimit::SetLimitValue(ResourceType resource, s64 value) { limit[index] = value; return RESULT_SUCCESS; } else { + LOG_ERROR(Kernel, "Limit value is too large! resource={}, value={}, index={}", + static_cast<u32>(resource), value, index); return ERR_INVALID_STATE; } } diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 41ef2caf6..4ae4529f5 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -685,6 +685,8 @@ static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, u64 ha case GetInfoType::TotalPhysicalMemoryAvailableWithoutSystemResource: case GetInfoType::TotalPhysicalMemoryUsedWithoutSystemResource: { if (info_sub_id != 0) { + LOG_ERROR(Kernel_SVC, "Info sub id is non zero! info_id={}, info_sub_id={}", info_id, + info_sub_id); return ERR_INVALID_ENUM_VALUE; } @@ -692,6 +694,8 @@ static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, u64 ha system.Kernel().CurrentProcess()->GetHandleTable(); const auto process = current_process_handle_table.Get<Process>(static_cast<Handle>(handle)); if (!process) { + LOG_ERROR(Kernel_SVC, "Process is not valid! info_id={}, info_sub_id={}, handle={:08X}", + info_id, info_sub_id, handle); return ERR_INVALID_HANDLE; } @@ -783,10 +787,13 @@ static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, u64 ha case GetInfoType::RegisterResourceLimit: { if (handle != 0) { + LOG_ERROR(Kernel, "Handle is non zero! handle={:08X}", handle); return ERR_INVALID_HANDLE; } if (info_sub_id != 0) { + LOG_ERROR(Kernel, "Info sub id is non zero! info_id={}, info_sub_id={}", info_id, + info_sub_id); return ERR_INVALID_COMBINATION; } diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index a919750a6..db7f379ac 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -423,6 +423,8 @@ ResultCode Thread::SetCoreAndAffinityMask(s32 new_core, u64 new_affinity_mask) { if (new_core == THREADPROCESSORID_DONT_UPDATE) { new_core = use_override ? ideal_core_override : ideal_core; if ((new_affinity_mask & (1ULL << new_core)) == 0) { + LOG_ERROR(Kernel, "New affinity mask is incorrect! new_core={}, new_affinity_mask={}", + new_core, new_affinity_mask); return ERR_INVALID_COMBINATION; } } diff --git a/src/core/hle/service/acc/acc.cpp b/src/core/hle/service/acc/acc.cpp index cfac8ca9a..9a7992f58 100644 --- a/src/core/hle/service/acc/acc.cpp +++ b/src/core/hle/service/acc/acc.cpp @@ -319,46 +319,37 @@ void Module::Interface::IsUserRegistrationRequestPermitted(Kernel::HLERequestCon void Module::Interface::InitializeApplicationInfo(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - auto pid = rp.Pop<u64>(); - LOG_DEBUG(Service_ACC, "called, process_id={}", pid); + LOG_DEBUG(Service_ACC, "called"); IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(InitializeApplicationInfoBase(pid)); + rb.Push(InitializeApplicationInfoBase()); } void Module::Interface::InitializeApplicationInfoRestricted(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - auto pid = rp.Pop<u64>(); - LOG_WARNING(Service_ACC, "(Partial implementation) called, process_id={}", pid); + LOG_WARNING(Service_ACC, "(Partial implementation) called"); // TODO(ogniK): We require checking if the user actually owns the title and what not. As of // currently, we assume the user owns the title. InitializeApplicationInfoBase SHOULD be called // first then we do extra checks if the game is a digital copy. IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(InitializeApplicationInfoBase(pid)); + rb.Push(InitializeApplicationInfoBase()); } -ResultCode Module::Interface::InitializeApplicationInfoBase(u64 process_id) { +ResultCode Module::Interface::InitializeApplicationInfoBase() { if (application_info) { LOG_ERROR(Service_ACC, "Application already initialized"); return ERR_ACCOUNTINFO_ALREADY_INITIALIZED; } - const auto& list = system.Kernel().GetProcessList(); - const auto iter = std::find_if(list.begin(), list.end(), [&process_id](const auto& process) { - return process->GetProcessID() == process_id; - }); - - if (iter == list.end()) { - LOG_ERROR(Service_ACC, "Failed to find process ID"); - application_info.application_type = ApplicationType::Unknown; - - return ERR_ACCOUNTINFO_BAD_APPLICATION; - } - - const auto launch_property = system.GetARPManager().GetLaunchProperty((*iter)->GetTitleID()); + // TODO(ogniK): This should be changed to reflect the target process for when we have multiple + // processes emulated. As we don't actually have pid support we should assume we're just using + // our own process + const auto& current_process = system.Kernel().CurrentProcess(); + const auto launch_property = + system.GetARPManager().GetLaunchProperty(current_process->GetTitleID()); if (launch_property.Failed()) { LOG_ERROR(Service_ACC, "Failed to get launch property"); @@ -372,10 +363,12 @@ ResultCode Module::Interface::InitializeApplicationInfoBase(u64 process_id) { case FileSys::StorageId::Host: case FileSys::StorageId::NandUser: case FileSys::StorageId::SdCard: + case FileSys::StorageId::None: // Yuzu specific, differs from hardware application_info.application_type = ApplicationType::Digital; break; default: - LOG_ERROR(Service_ACC, "Invalid game storage ID"); + LOG_ERROR(Service_ACC, "Invalid game storage ID! storage_id={}", + launch_property->base_game_storage_id); return ERR_ACCOUNTINFO_BAD_APPLICATION; } @@ -428,6 +421,17 @@ void Module::Interface::GetProfileEditor(Kernel::HLERequestContext& ctx) { rb.PushIpcInterface<IProfileEditor>(user_id, *profile_manager); } +void Module::Interface::ListQualifiedUsers(Kernel::HLERequestContext& ctx) { + LOG_DEBUG(Service_ACC, "called"); + + // All users should be qualified. We don't actually have parental control or anything to do with + // nintendo online currently. We're just going to assume the user running the game has access to + // the game regardless of parental control settings. + ctx.WriteBuffer(profile_manager->GetAllUsers()); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); +} + void Module::Interface::TrySelectUserWithoutInteraction(Kernel::HLERequestContext& ctx) { LOG_DEBUG(Service_ACC, "called"); // A u8 is passed into this function which we can safely ignore. It's to determine if we have diff --git a/src/core/hle/service/acc/acc.h b/src/core/hle/service/acc/acc.h index 7a7dc9ec6..74ca39d6e 100644 --- a/src/core/hle/service/acc/acc.h +++ b/src/core/hle/service/acc/acc.h @@ -33,9 +33,10 @@ public: void TrySelectUserWithoutInteraction(Kernel::HLERequestContext& ctx); void IsUserAccountSwitchLocked(Kernel::HLERequestContext& ctx); void GetProfileEditor(Kernel::HLERequestContext& ctx); + void ListQualifiedUsers(Kernel::HLERequestContext& ctx); private: - ResultCode InitializeApplicationInfoBase(u64 process_id); + ResultCode InitializeApplicationInfoBase(); enum class ApplicationType : u32_le { GameCard = 0, diff --git a/src/core/hle/service/acc/acc_su.cpp b/src/core/hle/service/acc/acc_su.cpp index ae88deda5..2eefc6df5 100644 --- a/src/core/hle/service/acc/acc_su.cpp +++ b/src/core/hle/service/acc/acc_su.cpp @@ -35,7 +35,7 @@ ACC_SU::ACC_SU(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> p {113, nullptr, "GetSaveDataThumbnailExistence"}, {120, nullptr, "ListOpenUsersInApplication"}, {130, nullptr, "ActivateOpenContextRetention"}, - {140, nullptr, "ListQualifiedUsers"}, + {140, &ACC_SU::ListQualifiedUsers, "ListQualifiedUsers"}, {150, nullptr, "AuthenticateApplicationAsync"}, {190, nullptr, "GetUserLastOpenedApplication"}, {191, nullptr, "ActivateOpenContextHolder"}, diff --git a/src/core/hle/service/acc/acc_u0.cpp b/src/core/hle/service/acc/acc_u0.cpp index 0ac19f4ff..fb4e7e772 100644 --- a/src/core/hle/service/acc/acc_u0.cpp +++ b/src/core/hle/service/acc/acc_u0.cpp @@ -32,7 +32,7 @@ ACC_U0::ACC_U0(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> p {130, nullptr, "LoadOpenContext"}, {131, nullptr, "ListOpenContextStoredUsers"}, {140, &ACC_U0::InitializeApplicationInfoRestricted, "InitializeApplicationInfoRestricted"}, - {141, nullptr, "ListQualifiedUsers"}, + {141, &ACC_U0::ListQualifiedUsers, "ListQualifiedUsers"}, {150, &ACC_U0::IsUserAccountSwitchLocked, "IsUserAccountSwitchLocked"}, }; // clang-format on diff --git a/src/core/hle/service/acc/acc_u1.cpp b/src/core/hle/service/acc/acc_u1.cpp index 2b9c11928..9f29cdc82 100644 --- a/src/core/hle/service/acc/acc_u1.cpp +++ b/src/core/hle/service/acc/acc_u1.cpp @@ -34,7 +34,7 @@ ACC_U1::ACC_U1(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> p {112, nullptr, "LoadSaveDataThumbnail"}, {113, nullptr, "GetSaveDataThumbnailExistence"}, {130, nullptr, "ActivateOpenContextRetention"}, - {140, nullptr, "ListQualifiedUsers"}, + {140, &ACC_U1::ListQualifiedUsers, "ListQualifiedUsers"}, {150, nullptr, "AuthenticateApplicationAsync"}, {190, nullptr, "GetUserLastOpenedApplication"}, {191, nullptr, "ActivateOpenContextHolder"}, diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index 9522f8c4b..a967e6ef7 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -52,11 +52,6 @@ enum class LaunchParameterKind : u32 { AccountPreselectedUser = 2, }; -enum class VrMode : u8 { - Disabled = 0, - Enabled = 1, -}; - constexpr u32 LAUNCH_PARAMETER_ACCOUNT_PRESELECTED_USER_MAGIC = 0xC79497CA; struct LaunchParameterAccountPreselectedUser { @@ -685,27 +680,21 @@ void ICommonStateGetter::GetCurrentFocusState(Kernel::HLERequestContext& ctx) { } void ICommonStateGetter::IsVrModeEnabled(Kernel::HLERequestContext& ctx) { - LOG_WARNING(Service_AM, "(STUBBED) called"); + LOG_DEBUG(Service_AM, "called"); IPC::ResponseBuilder rb{ctx, 3}; rb.Push(RESULT_SUCCESS); - rb.PushEnum(VrMode::Disabled); + rb.Push(vr_mode_state); } void ICommonStateGetter::SetVrModeEnabled(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; - const auto is_vr_mode_enabled = rp.Pop<bool>(); + vr_mode_state = rp.Pop<bool>(); - LOG_WARNING(Service_AM, "(STUBBED) called. is_vr_mode_enabled={}", is_vr_mode_enabled); + LOG_WARNING(Service_AM, "VR Mode is {}", vr_mode_state ? "on" : "off"); IPC::ResponseBuilder rb{ctx, 2}; - if (!is_vr_mode_enabled) { - rb.Push(RESULT_SUCCESS); - } else { - // TODO: Find better error code for this - UNIMPLEMENTED_MSG("is_vr_mode_enabled={}", is_vr_mode_enabled); - rb.Push(RESULT_UNKNOWN); - } + rb.Push(RESULT_SUCCESS); } void ICommonStateGetter::SetLcdBacklighOffEnabled(Kernel::HLERequestContext& ctx) { @@ -1169,7 +1158,7 @@ IApplicationFunctions::IApplicationFunctions(Core::System& system_) {121, nullptr, "ClearUserChannel"}, {122, nullptr, "UnpopToUserChannel"}, {130, &IApplicationFunctions::GetGpuErrorDetectedSystemEvent, "GetGpuErrorDetectedSystemEvent"}, - {140, nullptr, "GetFriendInvitationStorageChannelEvent"}, + {140, &IApplicationFunctions::GetFriendInvitationStorageChannelEvent, "GetFriendInvitationStorageChannelEvent"}, {141, nullptr, "TryPopFromFriendInvitationStorageChannel"}, {150, nullptr, "GetNotificationStorageChannelEvent"}, {151, nullptr, "TryPopFromNotificationStorageChannel"}, @@ -1186,6 +1175,9 @@ IApplicationFunctions::IApplicationFunctions(Core::System& system_) auto& kernel = system.Kernel(); gpu_error_detected_event = Kernel::WritableEvent::CreateEventPair( kernel, "IApplicationFunctions:GpuErrorDetectedSystemEvent"); + + friend_invitation_storage_channel_event = Kernel::WritableEvent::CreateEventPair( + kernel, "IApplicationFunctions:FriendInvitationStorageChannelEvent"); } IApplicationFunctions::~IApplicationFunctions() = default; @@ -1511,6 +1503,14 @@ void IApplicationFunctions::GetGpuErrorDetectedSystemEvent(Kernel::HLERequestCon rb.PushCopyObjects(gpu_error_detected_event.readable); } +void IApplicationFunctions::GetFriendInvitationStorageChannelEvent(Kernel::HLERequestContext& ctx) { + LOG_DEBUG(Service_AM, "called"); + + IPC::ResponseBuilder rb{ctx, 2, 1}; + rb.Push(RESULT_SUCCESS); + rb.PushCopyObjects(friend_invitation_storage_channel_event.readable); +} + void InstallInterfaces(SM::ServiceManager& service_manager, std::shared_ptr<NVFlinger::NVFlinger> nvflinger, Core::System& system) { auto message_queue = std::make_shared<AppletMessageQueue>(system.Kernel()); diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h index 53cfce10f..dfa701d73 100644 --- a/src/core/hle/service/am/am.h +++ b/src/core/hle/service/am/am.h @@ -191,6 +191,7 @@ private: Core::System& system; std::shared_ptr<AppletMessageQueue> msg_queue; + bool vr_mode_state{}; }; class IStorageImpl { @@ -280,10 +281,12 @@ private: void QueryApplicationPlayStatistics(Kernel::HLERequestContext& ctx); void QueryApplicationPlayStatisticsByUid(Kernel::HLERequestContext& ctx); void GetGpuErrorDetectedSystemEvent(Kernel::HLERequestContext& ctx); + void GetFriendInvitationStorageChannelEvent(Kernel::HLERequestContext& ctx); bool launch_popped_application_specific = false; bool launch_popped_account_preselect = false; Kernel::EventPair gpu_error_detected_event; + Kernel::EventPair friend_invitation_storage_channel_event; Core::System& system; }; diff --git a/src/core/hle/service/audio/audin_u.cpp b/src/core/hle/service/audio/audin_u.cpp index d7f1d348d..3e2299426 100644 --- a/src/core/hle/service/audio/audin_u.cpp +++ b/src/core/hle/service/audio/audin_u.cpp @@ -2,6 +2,9 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include "common/logging/log.h" +#include "core/hle/ipc_helpers.h" +#include "core/hle/kernel/hle_ipc.h" #include "core/hle/service/audio/audin_u.h" namespace Service::Audio { @@ -36,11 +39,12 @@ public: AudInU::AudInU() : ServiceFramework("audin:u") { // clang-format off static const FunctionInfo functions[] = { - {0, nullptr, "ListAudioIns"}, - {1, nullptr, "OpenAudioIn"}, - {2, nullptr, "Unknown"}, - {3, nullptr, "OpenAudioInAuto"}, - {4, nullptr, "ListAudioInsAuto"}, + {0, &AudInU::ListAudioIns, "ListAudioIns"}, + {1, &AudInU::OpenAudioIn, "OpenAudioIn"}, + {2, &AudInU::ListAudioIns, "ListAudioInsAuto"}, + {3, &AudInU::OpenAudioIn, "OpenAudioInAuto"}, + {4, &AudInU::ListAudioInsAutoFiltered, "ListAudioInsAutoFiltered"}, + {5, &AudInU::OpenAudioInProtocolSpecified, "OpenAudioInProtocolSpecified"}, }; // clang-format on @@ -49,4 +53,60 @@ AudInU::AudInU() : ServiceFramework("audin:u") { AudInU::~AudInU() = default; +void AudInU::ListAudioIns(Kernel::HLERequestContext& ctx) { + LOG_DEBUG(Service_Audio, "called"); + const std::size_t count = ctx.GetWriteBufferSize() / sizeof(AudioInDeviceName); + + const std::size_t device_count = std::min(count, audio_device_names.size()); + std::vector<AudioInDeviceName> device_names; + device_names.reserve(device_count); + + for (std::size_t i = 0; i < device_count; i++) { + const auto& device_name = audio_device_names[i]; + auto& entry = device_names.emplace_back(); + device_name.copy(entry.data(), device_name.size()); + } + + ctx.WriteBuffer(device_names); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(RESULT_SUCCESS); + rb.Push(static_cast<u32>(device_names.size())); +} + +void AudInU::ListAudioInsAutoFiltered(Kernel::HLERequestContext& ctx) { + LOG_DEBUG(Service_Audio, "called"); + constexpr u32 device_count = 0; + + // Since we don't actually use any other audio input devices, we return 0 devices. Filtered + // device listing just omits the default input device + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(RESULT_SUCCESS); + rb.Push(static_cast<u32>(device_count)); +} + +void AudInU::OpenInOutImpl(Kernel::HLERequestContext& ctx) { + AudInOutParams params{}; + params.channel_count = 2; + params.sample_format = SampleFormat::PCM16; + params.sample_rate = 48000; + params.state = State::Started; + + IPC::ResponseBuilder rb{ctx, 6, 0, 1}; + rb.Push(RESULT_SUCCESS); + rb.PushRaw<AudInOutParams>(params); + rb.PushIpcInterface<IAudioIn>(); +} + +void AudInU::OpenAudioIn(Kernel::HLERequestContext& ctx) { + LOG_WARNING(Service_Audio, "(STUBBED) called"); + OpenInOutImpl(ctx); +} + +void AudInU::OpenAudioInProtocolSpecified(Kernel::HLERequestContext& ctx) { + LOG_WARNING(Service_Audio, "(STUBBED) called"); + OpenInOutImpl(ctx); +} + } // namespace Service::Audio diff --git a/src/core/hle/service/audio/audin_u.h b/src/core/hle/service/audio/audin_u.h index 0538b9560..a599f4a64 100644 --- a/src/core/hle/service/audio/audin_u.h +++ b/src/core/hle/service/audio/audin_u.h @@ -16,6 +16,35 @@ class AudInU final : public ServiceFramework<AudInU> { public: explicit AudInU(); ~AudInU() override; + +private: + enum class SampleFormat : u32_le { + PCM16 = 2, + }; + + enum class State : u32_le { + Started = 0, + Stopped = 1, + }; + + struct AudInOutParams { + u32_le sample_rate{}; + u32_le channel_count{}; + SampleFormat sample_format{}; + State state{}; + }; + static_assert(sizeof(AudInOutParams) == 0x10, "AudInOutParams is an invalid size"); + + using AudioInDeviceName = std::array<char, 256>; + static constexpr std::array<std::string_view, 1> audio_device_names{{ + "BuiltInHeadset", + }}; + + void ListAudioIns(Kernel::HLERequestContext& ctx); + void ListAudioInsAutoFiltered(Kernel::HLERequestContext& ctx); + void OpenInOutImpl(Kernel::HLERequestContext& ctx); + void OpenAudioIn(Kernel::HLERequestContext& ctx); + void OpenAudioInProtocolSpecified(Kernel::HLERequestContext& ctx); }; } // namespace Service::Audio diff --git a/src/core/hle/service/caps/caps_su.cpp b/src/core/hle/service/caps/caps_su.cpp index 2b4c2d808..e8b0698e8 100644 --- a/src/core/hle/service/caps/caps_su.cpp +++ b/src/core/hle/service/caps/caps_su.cpp @@ -2,6 +2,8 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include "common/logging/log.h" +#include "core/hle/ipc_helpers.h" #include "core/hle/service/caps/caps_su.h" namespace Service::Capture { @@ -9,8 +11,11 @@ namespace Service::Capture { CAPS_SU::CAPS_SU() : ServiceFramework("caps:su") { // clang-format off static const FunctionInfo functions[] = { + {32, &CAPS_SU::SetShimLibraryVersion, "SetShimLibraryVersion"}, {201, nullptr, "SaveScreenShot"}, {203, nullptr, "SaveScreenShotEx0"}, + {205, nullptr, "SaveScreenShotEx1"}, + {210, nullptr, "SaveScreenShotEx2"}, }; // clang-format on @@ -19,4 +24,11 @@ CAPS_SU::CAPS_SU() : ServiceFramework("caps:su") { CAPS_SU::~CAPS_SU() = default; +void CAPS_SU::SetShimLibraryVersion(Kernel::HLERequestContext& ctx) { + LOG_WARNING(Service_Capture, "(STUBBED) called"); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); +} + } // namespace Service::Capture diff --git a/src/core/hle/service/caps/caps_su.h b/src/core/hle/service/caps/caps_su.h index cb11f7c9a..c494d7c84 100644 --- a/src/core/hle/service/caps/caps_su.h +++ b/src/core/hle/service/caps/caps_su.h @@ -16,6 +16,9 @@ class CAPS_SU final : public ServiceFramework<CAPS_SU> { public: explicit CAPS_SU(); ~CAPS_SU() override; + +private: + void SetShimLibraryVersion(Kernel::HLERequestContext& ctx); }; } // namespace Service::Capture diff --git a/src/core/hle/service/filesystem/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp_srv.cpp index 6b9b4f3b9..f6503fe2f 100644 --- a/src/core/hle/service/filesystem/fsp_srv.cpp +++ b/src/core/hle/service/filesystem/fsp_srv.cpp @@ -316,8 +316,8 @@ public: {8, &IFileSystem::OpenFile, "OpenFile"}, {9, &IFileSystem::OpenDirectory, "OpenDirectory"}, {10, &IFileSystem::Commit, "Commit"}, - {11, nullptr, "GetFreeSpaceSize"}, - {12, nullptr, "GetTotalSpaceSize"}, + {11, &IFileSystem::GetFreeSpaceSize, "GetFreeSpaceSize"}, + {12, &IFileSystem::GetTotalSpaceSize, "GetTotalSpaceSize"}, {13, &IFileSystem::CleanDirectoryRecursively, "CleanDirectoryRecursively"}, {14, nullptr, "GetFileTimeStampRaw"}, {15, nullptr, "QueryEntry"}, diff --git a/src/core/hle/service/nim/nim.cpp b/src/core/hle/service/nim/nim.cpp index e85f123e2..f19affce7 100644 --- a/src/core/hle/service/nim/nim.cpp +++ b/src/core/hle/service/nim/nim.cpp @@ -15,6 +15,66 @@ namespace Service::NIM { +class IShopServiceAsync final : public ServiceFramework<IShopServiceAsync> { +public: + IShopServiceAsync() : ServiceFramework("IShopServiceAsync") { + // clang-format off + static const FunctionInfo functions[] = { + {0, nullptr, "Cancel"}, + {1, nullptr, "GetSize"}, + {2, nullptr, "Read"}, + {3, nullptr, "GetErrorCode"}, + {4, nullptr, "Request"}, + {5, nullptr, "Prepare"}, + }; + // clang-format on + + RegisterHandlers(functions); + } +}; + +class IShopServiceAccessor final : public ServiceFramework<IShopServiceAccessor> { +public: + IShopServiceAccessor() : ServiceFramework("IShopServiceAccessor") { + // clang-format off + static const FunctionInfo functions[] = { + {0, &IShopServiceAccessor::CreateAsyncInterface, "CreateAsyncInterface"}, + }; + // clang-format on + + RegisterHandlers(functions); + } + +private: + void CreateAsyncInterface(Kernel::HLERequestContext& ctx) { + LOG_WARNING(Service_NIM, "(STUBBED) called"); + IPC::ResponseBuilder rb{ctx, 2, 0, 1}; + rb.Push(RESULT_SUCCESS); + rb.PushIpcInterface<IShopServiceAsync>(); + } +}; + +class IShopServiceAccessServer final : public ServiceFramework<IShopServiceAccessServer> { +public: + IShopServiceAccessServer() : ServiceFramework("IShopServiceAccessServer") { + // clang-format off + static const FunctionInfo functions[] = { + {0, &IShopServiceAccessServer::CreateAccessorInterface, "CreateAccessorInterface"}, + }; + // clang-format on + + RegisterHandlers(functions); + } + +private: + void CreateAccessorInterface(Kernel::HLERequestContext& ctx) { + LOG_WARNING(Service_NIM, "(STUBBED) called"); + IPC::ResponseBuilder rb{ctx, 2, 0, 1}; + rb.Push(RESULT_SUCCESS); + rb.PushIpcInterface<IShopServiceAccessor>(); + } +}; + class NIM final : public ServiceFramework<NIM> { public: explicit NIM() : ServiceFramework{"nim"} { @@ -78,7 +138,7 @@ public: explicit NIM_ECA() : ServiceFramework{"nim:eca"} { // clang-format off static const FunctionInfo functions[] = { - {0, nullptr, "CreateServerInterface"}, + {0, &NIM_ECA::CreateServerInterface, "CreateServerInterface"}, {1, nullptr, "RefreshDebugAvailability"}, {2, nullptr, "ClearDebugResponse"}, {3, nullptr, "RegisterDebugResponse"}, @@ -87,6 +147,14 @@ public: RegisterHandlers(functions); } + +private: + void CreateServerInterface(Kernel::HLERequestContext& ctx) { + LOG_WARNING(Service_NIM, "(STUBBED) called"); + IPC::ResponseBuilder rb{ctx, 2, 0, 1}; + rb.Push(RESULT_SUCCESS); + rb.PushIpcInterface<IShopServiceAccessServer>(); + } }; class NIM_SHP final : public ServiceFramework<NIM_SHP> { diff --git a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h index 642b0a2cb..07b644ec5 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_ctrl_gpu.h @@ -159,9 +159,10 @@ private: static_assert(sizeof(IoctlFlushL2) == 8, "IoctlFlushL2 is incorrect size"); struct IoctlGetGpuTime { - u64_le gpu_time; + u64_le gpu_time{}; + INSERT_PADDING_WORDS(2); }; - static_assert(sizeof(IoctlGetGpuTime) == 8, "IoctlGetGpuTime is incorrect size"); + static_assert(sizeof(IoctlGetGpuTime) == 0x10, "IoctlGetGpuTime is incorrect size"); u32 GetCharacteristics(const std::vector<u8>& input, std::vector<u8>& output, std::vector<u8>& output2, IoctlVersion version); diff --git a/src/core/hle/service/ptm/psm.cpp b/src/core/hle/service/ptm/psm.cpp index c2d5fda94..12d154ecf 100644 --- a/src/core/hle/service/ptm/psm.cpp +++ b/src/core/hle/service/ptm/psm.cpp @@ -12,9 +12,6 @@ namespace Service::PSM { -constexpr u32 BATTERY_FULLY_CHARGED = 100; // 100% Full -constexpr u32 BATTERY_CURRENTLY_CHARGING = 1; // Plugged into an official dock - class PSM final : public ServiceFramework<PSM> { public: explicit PSM() : ServiceFramework{"psm"} { @@ -48,20 +45,30 @@ public: private: void GetBatteryChargePercentage(Kernel::HLERequestContext& ctx) { - LOG_WARNING(Service_PSM, "(STUBBED) called"); + LOG_DEBUG(Service_PSM, "called"); IPC::ResponseBuilder rb{ctx, 3}; rb.Push(RESULT_SUCCESS); - rb.Push<u32>(BATTERY_FULLY_CHARGED); + rb.Push<u32>(battery_charge_percentage); } void GetChargerType(Kernel::HLERequestContext& ctx) { - LOG_WARNING(Service_PSM, "(STUBBED) called"); + LOG_DEBUG(Service_PSM, "called"); IPC::ResponseBuilder rb{ctx, 3}; rb.Push(RESULT_SUCCESS); - rb.Push<u32>(BATTERY_CURRENTLY_CHARGING); + rb.PushEnum(charger_type); } + + enum class ChargerType : u32 { + Unplugged = 0, + RegularCharger = 1, + LowPowerCharger = 2, + Unknown = 3, + }; + + u32 battery_charge_percentage{100}; // 100% + ChargerType charger_type{ChargerType::RegularCharger}; }; void InstallInterfaces(SM::ServiceManager& sm) { |