diff options
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/hle/kernel/handle_table.cpp | 2 | ||||
-rw-r--r-- | src/core/hle/kernel/mutex.cpp | 5 | ||||
-rw-r--r-- | src/core/hle/kernel/process_capability.cpp | 30 | ||||
-rw-r--r-- | src/core/hle/kernel/readable_event.cpp | 13 | ||||
-rw-r--r-- | src/core/hle/kernel/resource_limit.cpp | 2 | ||||
-rw-r--r-- | src/core/hle/kernel/svc.cpp | 7 | ||||
-rw-r--r-- | src/core/hle/kernel/thread.cpp | 2 | ||||
-rw-r--r-- | src/core/hle/service/am/am.cpp | 17 | ||||
-rw-r--r-- | src/core/hle/service/audio/audin_u.cpp | 70 | ||||
-rw-r--r-- | src/core/hle/service/audio/audin_u.h | 29 | ||||
-rw-r--r-- | src/core/hle/service/caps/caps_su.cpp | 11 | ||||
-rw-r--r-- | src/core/hle/service/caps/caps_su.h | 3 |
12 files changed, 178 insertions, 13 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..00860fcbd 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" @@ -23,10 +24,12 @@ void ReadableEvent::Acquire(Thread* thread) { } void ReadableEvent::Signal() { - if (!is_signaled) { - is_signaled = true; - SynchronizationObject::Signal(); - }; + if (is_signaled) { + return; + } + + is_signaled = true; + SynchronizationObject::Signal(); } void ReadableEvent::Clear() { @@ -35,6 +38,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/am/am.cpp b/src/core/hle/service/am/am.cpp index 9450de6e9..a967e6ef7 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -1335,12 +1335,23 @@ void IApplicationFunctions::SetTerminateResult(Kernel::HLERequestContext& ctx) { } void IApplicationFunctions::GetDisplayVersion(Kernel::HLERequestContext& ctx) { - LOG_WARNING(Service_AM, "(STUBBED) called"); + LOG_DEBUG(Service_AM, "called"); + + std::array<u8, 0x10> version_string{}; + + FileSys::PatchManager pm{system.CurrentProcess()->GetTitleID()}; + const auto res = pm.GetControlMetadata(); + if (res.first != nullptr) { + const auto& version = res.first->GetVersionString(); + std::copy(version.begin(), version.end(), version_string.begin()); + } else { + constexpr u128 default_version = {1, 0}; + std::memcpy(version_string.data(), default_version.data(), sizeof(u128)); + } IPC::ResponseBuilder rb{ctx, 6}; rb.Push(RESULT_SUCCESS); - rb.Push<u64>(1); - rb.Push<u64>(0); + rb.PushRaw(version_string); } void IApplicationFunctions::GetDesiredLanguage(Kernel::HLERequestContext& ctx) { 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 b4d9355ef..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,7 +11,7 @@ namespace Service::Capture { CAPS_SU::CAPS_SU() : ServiceFramework("caps:su") { // clang-format off static const FunctionInfo functions[] = { - {32, nullptr, "SetShimLibraryVersion"}, + {32, &CAPS_SU::SetShimLibraryVersion, "SetShimLibraryVersion"}, {201, nullptr, "SaveScreenShot"}, {203, nullptr, "SaveScreenShotEx0"}, {205, nullptr, "SaveScreenShotEx1"}, @@ -22,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 |