diff options
Diffstat (limited to 'src/core')
44 files changed, 391 insertions, 124 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 8546d3602..47418006b 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -606,11 +606,11 @@ endif() create_target_directory_groups(core) target_link_libraries(core PUBLIC common PRIVATE audio_core video_core) -target_link_libraries(core PUBLIC Boost::boost PRIVATE fmt json-headers mbedtls opus unicorn) +target_link_libraries(core PUBLIC Boost::boost PRIVATE fmt::fmt nlohmann_json::nlohmann_json mbedtls Opus::Opus unicorn) if (YUZU_ENABLE_BOXCAT) target_compile_definitions(core PRIVATE -DYUZU_ENABLE_BOXCAT) - target_link_libraries(core PRIVATE httplib json-headers zip) + target_link_libraries(core PRIVATE httplib nlohmann_json::nlohmann_json zip) endif() if (ENABLE_WEB_SERVICE) 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/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp index 91d94025c..ba0eac4c2 100644 --- a/src/core/hle/kernel/hle_ipc.cpp +++ b/src/core/hle/kernel/hle_ipc.cpp @@ -13,7 +13,6 @@ #include "common/common_funcs.h" #include "common/common_types.h" #include "common/logging/log.h" -#include "core/core.h" #include "core/hle/ipc_helpers.h" #include "core/hle/kernel/handle_table.h" #include "core/hle/kernel/hle_ipc.h" @@ -57,7 +56,6 @@ std::shared_ptr<WritableEvent> HLERequestContext::SleepClientThread( return true; }); - auto& kernel = Core::System::GetInstance().Kernel(); if (!writable_event) { // Create event if not provided const auto pair = WritableEvent::CreateEventPair(kernel, "HLE Pause Event: " + reason); @@ -79,9 +77,11 @@ std::shared_ptr<WritableEvent> HLERequestContext::SleepClientThread( return writable_event; } -HLERequestContext::HLERequestContext(std::shared_ptr<Kernel::ServerSession> server_session, +HLERequestContext::HLERequestContext(KernelCore& kernel, Core::Memory::Memory& memory, + std::shared_ptr<ServerSession> server_session, std::shared_ptr<Thread> thread) - : server_session(std::move(server_session)), thread(std::move(thread)) { + : server_session(std::move(server_session)), + thread(std::move(thread)), kernel{kernel}, memory{memory} { cmd_buf[0] = 0; } @@ -216,7 +216,6 @@ ResultCode HLERequestContext::PopulateFromIncomingCommandBuffer(const HandleTabl ResultCode HLERequestContext::WriteToOutgoingCommandBuffer(Thread& thread) { auto& owner_process = *thread.GetOwnerProcess(); auto& handle_table = owner_process.GetHandleTable(); - auto& memory = Core::System::GetInstance().Memory(); std::array<u32, IPC::COMMAND_BUFFER_LENGTH> dst_cmdbuf; memory.ReadBlock(owner_process, thread.GetTLSAddress(), dst_cmdbuf.data(), @@ -286,7 +285,6 @@ std::vector<u8> HLERequestContext::ReadBuffer(std::size_t buffer_index) const { std::vector<u8> buffer; const bool is_buffer_a{BufferDescriptorA().size() > buffer_index && BufferDescriptorA()[buffer_index].Size()}; - auto& memory = Core::System::GetInstance().Memory(); if (is_buffer_a) { ASSERT_MSG(BufferDescriptorA().size() > buffer_index, @@ -319,7 +317,6 @@ std::size_t HLERequestContext::WriteBuffer(const void* buffer, std::size_t size, size = buffer_size; // TODO(bunnei): This needs to be HW tested } - auto& memory = Core::System::GetInstance().Memory(); if (is_buffer_b) { ASSERT_MSG(BufferDescriptorB().size() > buffer_index, "BufferDescriptorB invalid buffer_index {}", buffer_index); diff --git a/src/core/hle/kernel/hle_ipc.h b/src/core/hle/kernel/hle_ipc.h index af3330297..b31673928 100644 --- a/src/core/hle/kernel/hle_ipc.h +++ b/src/core/hle/kernel/hle_ipc.h @@ -19,6 +19,10 @@ union ResultCode; +namespace Core::Memory { +class Memory; +} + namespace Service { class ServiceFrameworkBase; } @@ -28,6 +32,7 @@ namespace Kernel { class Domain; class HandleTable; class HLERequestContext; +class KernelCore; class Process; class ServerSession; class Thread; @@ -98,7 +103,8 @@ protected: */ class HLERequestContext { public: - explicit HLERequestContext(std::shared_ptr<ServerSession> session, + explicit HLERequestContext(KernelCore& kernel, Core::Memory::Memory& memory, + std::shared_ptr<ServerSession> session, std::shared_ptr<Thread> thread); ~HLERequestContext(); @@ -305,6 +311,9 @@ private: std::vector<std::shared_ptr<SessionRequestHandler>> domain_request_handlers; bool is_thread_waiting{}; + + KernelCore& kernel; + Core::Memory::Memory& memory; }; } // namespace Kernel diff --git a/src/core/hle/kernel/memory/address_space_info.cpp b/src/core/hle/kernel/memory/address_space_info.cpp index 27fae05e7..a523a2502 100644 --- a/src/core/hle/kernel/memory/address_space_info.cpp +++ b/src/core/hle/kernel/memory/address_space_info.cpp @@ -2,8 +2,8 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. -// This file references various implementation details from Atmosphère, an open-source firmware for -// the Nintendo Switch. Copyright 2018-2020 Atmosphère-NX. +// This file references various implementation details from Atmosphere, an open-source firmware for +// the Nintendo Switch. Copyright 2018-2020 Atmosphere-NX. #include <array> @@ -49,18 +49,18 @@ constexpr bool IsAllowedIndexForAddress(std::size_t index) { return index < std::size(AddressSpaceInfos) && AddressSpaceInfos[index].GetAddress() != Invalid; } -constexpr std::size_t - AddressSpaceIndices32Bit[static_cast<std::size_t>(AddressSpaceInfo::Type::Count)]{ +constexpr std::array<std::size_t, static_cast<std::size_t>(AddressSpaceInfo::Type::Count)> + AddressSpaceIndices32Bit{ 0, 1, 0, 2, 0, 3, }; -constexpr std::size_t - AddressSpaceIndices36Bit[static_cast<std::size_t>(AddressSpaceInfo::Type::Count)]{ +constexpr std::array<std::size_t, static_cast<std::size_t>(AddressSpaceInfo::Type::Count)> + AddressSpaceIndices36Bit{ 4, 5, 4, 6, 4, 7, }; -constexpr std::size_t - AddressSpaceIndices39Bit[static_cast<std::size_t>(AddressSpaceInfo::Type::Count)]{ +constexpr std::array<std::size_t, static_cast<std::size_t>(AddressSpaceInfo::Type::Count)> + AddressSpaceIndices39Bit{ 9, 8, 8, 10, 12, 11, }; diff --git a/src/core/hle/kernel/memory/address_space_info.h b/src/core/hle/kernel/memory/address_space_info.h index cc9a6421e..c479890be 100644 --- a/src/core/hle/kernel/memory/address_space_info.h +++ b/src/core/hle/kernel/memory/address_space_info.h @@ -2,12 +2,11 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. -// This file references various implementation details from Atmosphère, an open-source firmware for -// the Nintendo Switch. Copyright 2018-2020 Atmosphère-NX. +// This file references various implementation details from Atmosphere, an open-source firmware for +// the Nintendo Switch. Copyright 2018-2020 Atmosphere-NX. #pragma once -#include "common/common_funcs.h" #include "common/common_types.h" namespace Kernel::Memory { diff --git a/src/core/hle/kernel/memory/memory_block.h b/src/core/hle/kernel/memory/memory_block.h index 9db1f7b39..9d7839d08 100644 --- a/src/core/hle/kernel/memory/memory_block.h +++ b/src/core/hle/kernel/memory/memory_block.h @@ -2,8 +2,8 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. -// This file references various implementation details from Atmosphère, an open-source firmware for -// the Nintendo Switch. Copyright 2018-2020 Atmosphère-NX. +// This file references various implementation details from Atmosphere, an open-source firmware for +// the Nintendo Switch. Copyright 2018-2020 Atmosphere-NX. #pragma once diff --git a/src/core/hle/kernel/memory/memory_block_manager.cpp b/src/core/hle/kernel/memory/memory_block_manager.cpp index 900395c37..0732fa5a1 100644 --- a/src/core/hle/kernel/memory/memory_block_manager.cpp +++ b/src/core/hle/kernel/memory/memory_block_manager.cpp @@ -67,7 +67,6 @@ void MemoryBlockManager::Update(VAddr addr, std::size_t num_pages, MemoryState p MemoryPermission prev_perm, MemoryAttribute prev_attribute, MemoryState state, MemoryPermission perm, MemoryAttribute attribute) { - const std::size_t prev_count{memory_block_tree.size()}; const VAddr end_addr{addr + num_pages * PageSize}; iterator node{memory_block_tree.begin()}; @@ -109,7 +108,6 @@ void MemoryBlockManager::Update(VAddr addr, std::size_t num_pages, MemoryState p void MemoryBlockManager::Update(VAddr addr, std::size_t num_pages, MemoryState state, MemoryPermission perm, MemoryAttribute attribute) { - const std::size_t prev_count{memory_block_tree.size()}; const VAddr end_addr{addr + num_pages * PageSize}; iterator node{memory_block_tree.begin()}; @@ -145,7 +143,6 @@ void MemoryBlockManager::Update(VAddr addr, std::size_t num_pages, MemoryState s void MemoryBlockManager::UpdateLock(VAddr addr, std::size_t num_pages, LockFunc&& lock_func, MemoryPermission perm) { - const std::size_t prev_count{memory_block_tree.size()}; const VAddr end_addr{addr + num_pages * PageSize}; iterator node{memory_block_tree.begin()}; diff --git a/src/core/hle/kernel/memory/memory_block_manager.h b/src/core/hle/kernel/memory/memory_block_manager.h index 9451b5df6..6e1d41075 100644 --- a/src/core/hle/kernel/memory/memory_block_manager.h +++ b/src/core/hle/kernel/memory/memory_block_manager.h @@ -6,7 +6,6 @@ #include <functional> #include <list> -#include <memory> #include "common/common_types.h" #include "core/hle/kernel/memory/memory_block.h" diff --git a/src/core/hle/kernel/memory/memory_manager.cpp b/src/core/hle/kernel/memory/memory_manager.cpp index 3cd4f9e85..6b432e1b2 100644 --- a/src/core/hle/kernel/memory/memory_manager.cpp +++ b/src/core/hle/kernel/memory/memory_manager.cpp @@ -104,9 +104,9 @@ ResultCode MemoryManager::Allocate(PageLinkedList& page_list, std::size_t num_pa // Ensure that we don't leave anything un-freed auto group_guard = detail::ScopeExit([&] { for (const auto& it : page_list.Nodes()) { - const auto num_pages{std::min( + const auto min_num_pages{std::min( it.GetNumPages(), (chosen_manager.GetEndAddress() - it.GetAddress()) / PageSize)}; - chosen_manager.Free(it.GetAddress(), num_pages); + chosen_manager.Free(it.GetAddress(), min_num_pages); } }); @@ -165,9 +165,9 @@ ResultCode MemoryManager::Free(PageLinkedList& page_list, std::size_t num_pages, // Free all of the pages for (const auto& it : page_list.Nodes()) { - const auto num_pages{std::min( + const auto min_num_pages{std::min( it.GetNumPages(), (chosen_manager.GetEndAddress() - it.GetAddress()) / PageSize)}; - chosen_manager.Free(it.GetAddress(), num_pages); + chosen_manager.Free(it.GetAddress(), min_num_pages); } return RESULT_SUCCESS; diff --git a/src/core/hle/kernel/memory/memory_manager.h b/src/core/hle/kernel/memory/memory_manager.h index b078d7a5e..3cf444857 100644 --- a/src/core/hle/kernel/memory/memory_manager.h +++ b/src/core/hle/kernel/memory/memory_manager.h @@ -7,7 +7,6 @@ #include <array> #include <mutex> -#include "common/common_funcs.h" #include "common/common_types.h" #include "core/hle/kernel/memory/page_heap.h" #include "core/hle/result.h" diff --git a/src/core/hle/kernel/memory/page_heap.cpp b/src/core/hle/kernel/memory/page_heap.cpp index efcbb3cad..0ab1f7205 100644 --- a/src/core/hle/kernel/memory/page_heap.cpp +++ b/src/core/hle/kernel/memory/page_heap.cpp @@ -2,8 +2,8 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. -// This file references various implementation details from Atmosphère, an open-source firmware for -// the Nintendo Switch. Copyright 2018-2020 Atmosphère-NX. +// This file references various implementation details from Atmosphere, an open-source firmware for +// the Nintendo Switch. Copyright 2018-2020 Atmosphere-NX. #include "core/core.h" #include "core/hle/kernel/memory/page_heap.h" diff --git a/src/core/hle/kernel/memory/page_heap.h b/src/core/hle/kernel/memory/page_heap.h index 380c3f5a1..22b0de860 100644 --- a/src/core/hle/kernel/memory/page_heap.h +++ b/src/core/hle/kernel/memory/page_heap.h @@ -2,8 +2,8 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. -// This file references various implementation details from Atmosphère, an open-source firmware for -// the Nintendo Switch. Copyright 2018-2020 Atmosphère-NX. +// This file references various implementation details from Atmosphere, an open-source firmware for +// the Nintendo Switch. Copyright 2018-2020 Atmosphere-NX. #pragma once diff --git a/src/core/hle/kernel/memory/page_linked_list.h b/src/core/hle/kernel/memory/page_linked_list.h index 0668d00c6..45dc13eaf 100644 --- a/src/core/hle/kernel/memory/page_linked_list.h +++ b/src/core/hle/kernel/memory/page_linked_list.h @@ -7,7 +7,6 @@ #include <list> #include "common/assert.h" -#include "common/common_funcs.h" #include "common/common_types.h" #include "core/hle/kernel/memory/memory_types.h" #include "core/hle/result.h" diff --git a/src/core/hle/kernel/memory/page_table.cpp b/src/core/hle/kernel/memory/page_table.cpp index 3281611f8..5d6aac00f 100644 --- a/src/core/hle/kernel/memory/page_table.cpp +++ b/src/core/hle/kernel/memory/page_table.cpp @@ -6,7 +6,6 @@ #include "common/assert.h" #include "common/scope_exit.h" #include "core/core.h" -#include "core/device_memory.h" #include "core/hle/kernel/errors.h" #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/memory/address_space_info.h" diff --git a/src/core/hle/kernel/memory/page_table.h b/src/core/hle/kernel/memory/page_table.h index a867aa050..ce0d38849 100644 --- a/src/core/hle/kernel/memory/page_table.h +++ b/src/core/hle/kernel/memory/page_table.h @@ -4,16 +4,15 @@ #pragma once -#include <list> #include <memory> #include <mutex> -#include "common/common_funcs.h" #include "common/common_types.h" #include "common/page_table.h" #include "core/file_sys/program_metadata.h" #include "core/hle/kernel/memory/memory_block.h" #include "core/hle/kernel/memory/memory_manager.h" +#include "core/hle/result.h" namespace Core { class System; diff --git a/src/core/hle/kernel/memory/slab_heap.h b/src/core/hle/kernel/memory/slab_heap.h index be95fc3f7..465eaddb3 100644 --- a/src/core/hle/kernel/memory/slab_heap.h +++ b/src/core/hle/kernel/memory/slab_heap.h @@ -2,15 +2,14 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. -// This file references various implementation details from Atmosphère, an open-source firmware for -// the Nintendo Switch. Copyright 2018-2020 Atmosphère-NX. +// This file references various implementation details from Atmosphere, an open-source firmware for +// the Nintendo Switch. Copyright 2018-2020 Atmosphere-NX. #pragma once #include <atomic> #include "common/assert.h" -#include "common/common_funcs.h" #include "common/common_types.h" namespace Kernel::Memory { diff --git a/src/core/hle/kernel/memory/system_control.cpp b/src/core/hle/kernel/memory/system_control.cpp index 9cae3c6cb..2f98e9c4c 100644 --- a/src/core/hle/kernel/memory/system_control.cpp +++ b/src/core/hle/kernel/memory/system_control.cpp @@ -2,8 +2,6 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. -#pragma once - #include <random> #include "core/hle/kernel/memory/system_control.h" 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/server_session.cpp b/src/core/hle/kernel/server_session.cpp index 0f102ca44..25438b86b 100644 --- a/src/core/hle/kernel/server_session.cpp +++ b/src/core/hle/kernel/server_session.cpp @@ -137,8 +137,8 @@ ResultCode ServerSession::HandleDomainSyncRequest(Kernel::HLERequestContext& con ResultCode ServerSession::QueueSyncRequest(std::shared_ptr<Thread> thread, Core::Memory::Memory& memory) { u32* cmd_buf{reinterpret_cast<u32*>(memory.GetPointer(thread->GetTLSAddress()))}; - std::shared_ptr<Kernel::HLERequestContext> context{ - std::make_shared<Kernel::HLERequestContext>(SharedFrom(this), std::move(thread))}; + auto context = + std::make_shared<HLERequestContext>(kernel, memory, SharedFrom(this), std::move(thread)); context->PopulateFromIncomingCommandBuffer(kernel.CurrentProcess()->GetHandleTable(), cmd_buf); request_queue.Push(std::move(context)); 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..630a8b048 100644 --- a/src/core/hle/service/acc/acc.cpp +++ b/src/core/hle/service/acc/acc.cpp @@ -228,7 +228,8 @@ public: class IManagerForApplication final : public ServiceFramework<IManagerForApplication> { public: - IManagerForApplication() : ServiceFramework("IManagerForApplication") { + explicit IManagerForApplication(Common::UUID user_id) + : ServiceFramework("IManagerForApplication"), user_id(user_id) { // clang-format off static const FunctionInfo functions[] = { {0, &IManagerForApplication::CheckAvailability, "CheckAvailability"}, @@ -254,12 +255,14 @@ private: } void GetAccountId(Kernel::HLERequestContext& ctx) { - LOG_WARNING(Service_ACC, "(STUBBED) called"); - // Should return a nintendo account ID + LOG_DEBUG(Service_ACC, "called"); + IPC::ResponseBuilder rb{ctx, 4}; rb.Push(RESULT_SUCCESS); - rb.PushRaw<u64>(1); + rb.PushRaw<u64>(user_id.GetNintendoID()); } + + Common::UUID user_id; }; void Module::Interface::GetUserCount(Kernel::HLERequestContext& ctx) { @@ -319,46 +322,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 +366,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; } @@ -389,7 +385,7 @@ void Module::Interface::GetBaasAccountManagerForApplication(Kernel::HLERequestCo LOG_DEBUG(Service_ACC, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<IManagerForApplication>(); + rb.PushIpcInterface<IManagerForApplication>(profile_manager->GetLastOpenedUser()); } void Module::Interface::IsUserAccountSwitchLocked(Kernel::HLERequestContext& ctx) { @@ -428,6 +424,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 5695d2521..4df74c4f9 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; @@ -1343,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) { @@ -1500,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()); @@ -1514,14 +1525,15 @@ void InstallInterfaces(SM::ServiceManager& service_manager, std::make_shared<TCAP>()->InstallAsService(service_manager); } -IHomeMenuFunctions::IHomeMenuFunctions() : ServiceFramework("IHomeMenuFunctions") { +IHomeMenuFunctions::IHomeMenuFunctions(Kernel::KernelCore& kernel) + : ServiceFramework("IHomeMenuFunctions"), kernel(kernel) { // clang-format off static const FunctionInfo functions[] = { {10, &IHomeMenuFunctions::RequestToGetForeground, "RequestToGetForeground"}, {11, nullptr, "LockForeground"}, {12, nullptr, "UnlockForeground"}, {20, nullptr, "PopFromGeneralChannel"}, - {21, nullptr, "GetPopFromGeneralChannelEvent"}, + {21, &IHomeMenuFunctions::GetPopFromGeneralChannelEvent, "GetPopFromGeneralChannelEvent"}, {30, nullptr, "GetHomeButtonWriterLockAccessor"}, {31, nullptr, "GetWriterLockAccessorEx"}, {100, nullptr, "PopRequestLaunchApplicationForDebug"}, @@ -1531,6 +1543,9 @@ IHomeMenuFunctions::IHomeMenuFunctions() : ServiceFramework("IHomeMenuFunctions" // clang-format on RegisterHandlers(functions); + + pop_from_general_channel_event = Kernel::WritableEvent::CreateEventPair( + kernel, "IHomeMenuFunctions:PopFromGeneralChannelEvent"); } IHomeMenuFunctions::~IHomeMenuFunctions() = default; @@ -1542,6 +1557,14 @@ void IHomeMenuFunctions::RequestToGetForeground(Kernel::HLERequestContext& ctx) rb.Push(RESULT_SUCCESS); } +void IHomeMenuFunctions::GetPopFromGeneralChannelEvent(Kernel::HLERequestContext& ctx) { + LOG_WARNING(Service_AM, "(STUBBED) called"); + + IPC::ResponseBuilder rb{ctx, 2, 1}; + rb.Push(RESULT_SUCCESS); + rb.PushCopyObjects(pop_from_general_channel_event.readable); +} + IGlobalStateController::IGlobalStateController() : ServiceFramework("IGlobalStateController") { // clang-format off static const FunctionInfo functions[] = { diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h index 53cfce10f..469f7f814 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,20 +281,26 @@ 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; }; class IHomeMenuFunctions final : public ServiceFramework<IHomeMenuFunctions> { public: - IHomeMenuFunctions(); + explicit IHomeMenuFunctions(Kernel::KernelCore& kernel); ~IHomeMenuFunctions() override; private: void RequestToGetForeground(Kernel::HLERequestContext& ctx); + void GetPopFromGeneralChannelEvent(Kernel::HLERequestContext& ctx); + + Kernel::EventPair pop_from_general_channel_event; + Kernel::KernelCore& kernel; }; class IGlobalStateController final : public ServiceFramework<IGlobalStateController> { diff --git a/src/core/hle/service/am/applet_ae.cpp b/src/core/hle/service/am/applet_ae.cpp index e454b77d8..9df286d17 100644 --- a/src/core/hle/service/am/applet_ae.cpp +++ b/src/core/hle/service/am/applet_ae.cpp @@ -202,7 +202,7 @@ private: IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); - rb.PushIpcInterface<IHomeMenuFunctions>(); + rb.PushIpcInterface<IHomeMenuFunctions>(system.Kernel()); } void GetGlobalStateController(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/bcat/backend/boxcat.cpp b/src/core/hle/service/bcat/backend/boxcat.cpp index 5febe8fc1..d29e78d7e 100644 --- a/src/core/hle/service/bcat/backend/boxcat.cpp +++ b/src/core/hle/service/bcat/backend/boxcat.cpp @@ -4,8 +4,8 @@ #include <fmt/ostream.h> #include <httplib.h> -#include <json.hpp> #include <mbedtls/sha256.h> +#include <nlohmann/json.hpp> #include "common/hex_util.h" #include "common/logging/backend.h" #include "common/logging/log.h" 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) { diff --git a/src/core/reporter.cpp b/src/core/reporter.cpp index 558cbe6d7..76cfa5a17 100644 --- a/src/core/reporter.cpp +++ b/src/core/reporter.cpp @@ -4,11 +4,12 @@ #include <ctime> #include <fstream> +#include <iomanip> #include <fmt/chrono.h> #include <fmt/format.h> #include <fmt/ostream.h> -#include <json.hpp> +#include <nlohmann/json.hpp> #include "common/file_util.h" #include "common/hex_util.h" diff --git a/src/core/settings.cpp b/src/core/settings.cpp index cd6c257f5..2b0bdc4d3 100644 --- a/src/core/settings.cpp +++ b/src/core/settings.cpp @@ -96,6 +96,7 @@ void LogSettings() { LogSetting("Renderer_UseAsynchronousGpuEmulation", Settings::values.use_asynchronous_gpu_emulation); LogSetting("Renderer_UseVsync", Settings::values.use_vsync); + LogSetting("Renderer_AnisotropicFilteringLevel", Settings::values.max_anisotropy); LogSetting("Audio_OutputEngine", Settings::values.sink_id); LogSetting("Audio_EnableAudioStretching", Settings::values.enable_audio_stretching); LogSetting("Audio_OutputDevice", Settings::values.audio_device_id); |