From 7eea1fc4d694d5d6626087f8d5bffb1a3ccf39ad Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Sat, 10 May 2025 23:29:23 +0300 Subject: [PATCH 1/9] log error for videodec ,videodec2 (#2900) --- src/core/libraries/videodec/videodec.cpp | 11 +++++++++++ src/core/libraries/videodec/videodec2.cpp | 18 ++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/src/core/libraries/videodec/videodec.cpp b/src/core/libraries/videodec/videodec.cpp index 02ea61509..ae7d17560 100644 --- a/src/core/libraries/videodec/videodec.cpp +++ b/src/core/libraries/videodec/videodec.cpp @@ -17,10 +17,12 @@ int PS4_SYSV_ABI sceVideodecCreateDecoder(const OrbisVideodecConfigInfo* pCfgInf LOG_INFO(Lib_Videodec, "called"); if (!pCfgInfoIn || !pRsrcInfoIn || !pCtrlOut) { + LOG_ERROR(Lib_Videodec, "Invalid arguments"); return ORBIS_VIDEODEC_ERROR_ARGUMENT_POINTER; } if (pCfgInfoIn->thisSize != sizeof(OrbisVideodecConfigInfo) || pRsrcInfoIn->thisSize != sizeof(OrbisVideodecResourceInfo)) { + LOG_ERROR(Lib_Videodec, "Invalid struct size"); return ORBIS_VIDEODEC_ERROR_STRUCT_SIZE; } @@ -37,15 +39,18 @@ int PS4_SYSV_ABI sceVideodecDecode(OrbisVideodecCtrl* pCtrlIn, OrbisVideodecPictureInfo* pPictureInfoOut) { LOG_TRACE(Lib_Videodec, "called"); if (!pCtrlIn || !pInputDataIn || !pPictureInfoOut) { + LOG_ERROR(Lib_Videodec, "Invalid arguments"); return ORBIS_VIDEODEC_ERROR_ARGUMENT_POINTER; } if (pCtrlIn->thisSize != sizeof(OrbisVideodecCtrl) || pFrameBufferInOut->thisSize != sizeof(OrbisVideodecFrameBuffer)) { + LOG_ERROR(Lib_Videodec, "Invalid struct size"); return ORBIS_VIDEODEC_ERROR_STRUCT_SIZE; } VdecDecoder* decoder = (VdecDecoder*)pCtrlIn->handle; if (!decoder) { + LOG_ERROR(Lib_Videodec, "Invalid decoder handle"); return ORBIS_VIDEODEC_ERROR_HANDLE; } return decoder->Decode(*pInputDataIn, *pFrameBufferInOut, *pPictureInfoOut); @@ -56,6 +61,7 @@ int PS4_SYSV_ABI sceVideodecDeleteDecoder(OrbisVideodecCtrl* pCtrlIn) { VdecDecoder* decoder = (VdecDecoder*)pCtrlIn->handle; if (!decoder) { + LOG_ERROR(Lib_Videodec, "Invalid decoder handle"); return ORBIS_VIDEODEC_ERROR_HANDLE; } delete decoder; @@ -68,15 +74,18 @@ int PS4_SYSV_ABI sceVideodecFlush(OrbisVideodecCtrl* pCtrlIn, LOG_INFO(Lib_Videodec, "called"); if (!pFrameBufferInOut || !pPictureInfoOut) { + LOG_ERROR(Lib_Videodec, "Invalid arguments"); return ORBIS_VIDEODEC_ERROR_ARGUMENT_POINTER; } if (pFrameBufferInOut->thisSize != sizeof(OrbisVideodecFrameBuffer) || pPictureInfoOut->thisSize != sizeof(OrbisVideodecPictureInfo)) { + LOG_ERROR(Lib_Videodec, "Invalid struct size"); return ORBIS_VIDEODEC_ERROR_STRUCT_SIZE; } VdecDecoder* decoder = (VdecDecoder*)pCtrlIn->handle; if (!decoder) { + LOG_ERROR(Lib_Videodec, "Invalid decoder handle"); return ORBIS_VIDEODEC_ERROR_HANDLE; } return decoder->Flush(*pFrameBufferInOut, *pPictureInfoOut); @@ -92,10 +101,12 @@ int PS4_SYSV_ABI sceVideodecQueryResourceInfo(const OrbisVideodecConfigInfo* pCf LOG_INFO(Lib_Videodec, "called"); if (!pCfgInfoIn || !pRsrcInfoOut) { + LOG_ERROR(Lib_Videodec, "Invalid arguments"); return ORBIS_VIDEODEC_ERROR_ARGUMENT_POINTER; } if (pCfgInfoIn->thisSize != sizeof(OrbisVideodecConfigInfo) || pRsrcInfoOut->thisSize != sizeof(OrbisVideodecResourceInfo)) { + LOG_ERROR(Lib_Videodec, "Invalid struct size"); return ORBIS_VIDEODEC_ERROR_STRUCT_SIZE; } diff --git a/src/core/libraries/videodec/videodec2.cpp b/src/core/libraries/videodec/videodec2.cpp index a7e520b41..4f9379151 100644 --- a/src/core/libraries/videodec/videodec2.cpp +++ b/src/core/libraries/videodec/videodec2.cpp @@ -17,9 +17,11 @@ sceVideodec2QueryComputeMemoryInfo(OrbisVideodec2ComputeMemoryInfo* computeMemIn LOG_INFO(Lib_Vdec2, "called"); if (!computeMemInfo) { + LOG_ERROR(Lib_Vdec2, "Invalid arguments"); return ORBIS_VIDEODEC2_ERROR_ARGUMENT_POINTER; } if (computeMemInfo->thisSize != sizeof(OrbisVideodec2ComputeMemoryInfo)) { + LOG_ERROR(Lib_Vdec2, "Invalid struct size"); return ORBIS_VIDEODEC2_ERROR_STRUCT_SIZE; } @@ -47,10 +49,12 @@ sceVideodec2QueryDecoderMemoryInfo(const OrbisVideodec2DecoderConfigInfo* decode LOG_INFO(Lib_Vdec2, "called"); if (!decoderCfgInfo || !decoderMemInfo) { + LOG_ERROR(Lib_Vdec2, "Invalid arguments"); return ORBIS_VIDEODEC2_ERROR_ARGUMENT_POINTER; } if (decoderCfgInfo->thisSize != sizeof(OrbisVideodec2DecoderConfigInfo) || decoderMemInfo->thisSize != sizeof(OrbisVideodec2DecoderMemoryInfo)) { + LOG_ERROR(Lib_Vdec2, "Invalid struct size"); return ORBIS_VIDEODEC2_ERROR_STRUCT_SIZE; } @@ -74,10 +78,12 @@ s32 PS4_SYSV_ABI sceVideodec2CreateDecoder(const OrbisVideodec2DecoderConfigInfo LOG_INFO(Lib_Vdec2, "called"); if (!decoderCfgInfo || !decoderMemInfo || !decoder) { + LOG_ERROR(Lib_Vdec2, "Invalid arguments"); return ORBIS_VIDEODEC2_ERROR_ARGUMENT_POINTER; } if (decoderCfgInfo->thisSize != sizeof(OrbisVideodec2DecoderConfigInfo) || decoderMemInfo->thisSize != sizeof(OrbisVideodec2DecoderMemoryInfo)) { + LOG_ERROR(Lib_Vdec2, "Invalid struct size"); return ORBIS_VIDEODEC2_ERROR_STRUCT_SIZE; } @@ -89,6 +95,7 @@ s32 PS4_SYSV_ABI sceVideodec2DeleteDecoder(OrbisVideodec2Decoder decoder) { LOG_INFO(Lib_Vdec2, "called"); if (!decoder) { + LOG_ERROR(Lib_Vdec2, "Invalid arguments"); return ORBIS_VIDEODEC2_ERROR_DECODER_INSTANCE; } @@ -103,13 +110,16 @@ s32 PS4_SYSV_ABI sceVideodec2Decode(OrbisVideodec2Decoder decoder, LOG_TRACE(Lib_Vdec2, "called"); if (!decoder) { + LOG_ERROR(Lib_Vdec2, "Invalid decoder instance"); return ORBIS_VIDEODEC2_ERROR_DECODER_INSTANCE; } if (!inputData || !frameBuffer || !outputInfo) { + LOG_ERROR(Lib_Vdec2, "Invalid arguments"); return ORBIS_VIDEODEC2_ERROR_ARGUMENT_POINTER; } if (inputData->thisSize != sizeof(OrbisVideodec2InputData) || frameBuffer->thisSize != sizeof(OrbisVideodec2FrameBuffer)) { + LOG_ERROR(Lib_Vdec2, "Invalid struct size"); return ORBIS_VIDEODEC2_ERROR_STRUCT_SIZE; } @@ -122,13 +132,16 @@ s32 PS4_SYSV_ABI sceVideodec2Flush(OrbisVideodec2Decoder decoder, LOG_INFO(Lib_Vdec2, "called"); if (!decoder) { + LOG_ERROR(Lib_Vdec2, "Invalid decoder instance"); return ORBIS_VIDEODEC2_ERROR_DECODER_INSTANCE; } if (!frameBuffer || !outputInfo) { + LOG_ERROR(Lib_Vdec2, "Invalid arguments"); return ORBIS_VIDEODEC2_ERROR_ARGUMENT_POINTER; } if (frameBuffer->thisSize != sizeof(OrbisVideodec2FrameBuffer) || outputInfo->thisSize != sizeof(OrbisVideodec2OutputInfo)) { + LOG_ERROR(Lib_Vdec2, "Invalid struct size"); return ORBIS_VIDEODEC2_ERROR_STRUCT_SIZE; } @@ -139,6 +152,7 @@ s32 PS4_SYSV_ABI sceVideodec2Reset(OrbisVideodec2Decoder decoder) { LOG_INFO(Lib_Vdec2, "called"); if (!decoder) { + LOG_ERROR(Lib_Vdec2, "Invalid decoder instance"); return ORBIS_VIDEODEC2_ERROR_DECODER_INSTANCE; } @@ -150,12 +164,15 @@ s32 PS4_SYSV_ABI sceVideodec2GetPictureInfo(const OrbisVideodec2OutputInfo* outp LOG_TRACE(Lib_Vdec2, "called"); if (!outputInfo) { + LOG_ERROR(Lib_Vdec2, "Invalid arguments"); return ORBIS_VIDEODEC2_ERROR_ARGUMENT_POINTER; } if (outputInfo->thisSize != sizeof(OrbisVideodec2OutputInfo)) { + LOG_ERROR(Lib_Vdec2, "Invalid struct size"); return ORBIS_VIDEODEC2_ERROR_STRUCT_SIZE; } if (outputInfo->pictureCount == 0 || gPictureInfos.empty()) { + LOG_ERROR(Lib_Vdec2, "No picture info available"); return ORBIS_OK; } @@ -163,6 +180,7 @@ s32 PS4_SYSV_ABI sceVideodec2GetPictureInfo(const OrbisVideodec2OutputInfo* outp OrbisVideodec2AvcPictureInfo* picInfo = static_cast(p1stPictureInfoOut); if (picInfo->thisSize != sizeof(OrbisVideodec2AvcPictureInfo)) { + LOG_ERROR(Lib_Vdec2, "Invalid struct size"); return ORBIS_VIDEODEC2_ERROR_STRUCT_SIZE; } *picInfo = gPictureInfos.back(); From 6ece91c7632798474a2110ca0379985f183907eb Mon Sep 17 00:00:00 2001 From: Stephen Miller <56742918+StevenMiller123@users.noreply.github.com> Date: Sat, 10 May 2025 22:02:00 -0500 Subject: [PATCH 2/9] sceKernelVirtualQuery Fixes VI (#2904) * Reduce bitfield size Linux compilers automatically convert this, Windows not so much. * Static assert for VirtualQueryInfo struct size Since compilers can be weird, having a static assert for this will be helpful. Granted, this probably wont need changing after this PR. --- src/core/libraries/kernel/memory.h | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/core/libraries/kernel/memory.h b/src/core/libraries/kernel/memory.h index 6acb559d1..2ca7f2931 100644 --- a/src/core/libraries/kernel/memory.h +++ b/src/core/libraries/kernel/memory.h @@ -61,13 +61,15 @@ struct OrbisVirtualQueryInfo { size_t offset; s32 protection; s32 memory_type; - u32 is_flexible : 1; - u32 is_direct : 1; - u32 is_stack : 1; - u32 is_pooled : 1; - u32 is_committed : 1; + u8 is_flexible : 1; + u8 is_direct : 1; + u8 is_stack : 1; + u8 is_pooled : 1; + u8 is_committed : 1; char name[ORBIS_KERNEL_MAXIMUM_NAME_LENGTH]; }; +static_assert(sizeof(OrbisVirtualQueryInfo) == 72, + "OrbisVirtualQueryInfo struct size is incorrect"); struct OrbisKernelBatchMapEntry { void* start; From afcf3a12a3af90bd45114c8317fc8b56b28c611d Mon Sep 17 00:00:00 2001 From: Stephen Miller <56742918+StevenMiller123@users.noreply.github.com> Date: Sun, 11 May 2025 04:59:14 -0500 Subject: [PATCH 3/9] Core: Pooled Memory Fixes (#2895) * Update sceKernelMemoryPoolExpand Hardware tests show that this function is basically the same as sceKernelAllocateDirectMemory, with some minor differences. Update the memory searching code to match my updated AllocateDirectMemory code, with appropriate error conditions. * Update MemoryPoolReserve Only difference between real hw and our code is behavior with addr = 0. * Don't coalesce PoolReserved areas. Real hardware doesn't coalesce them. * Update PoolCommit Plenty of edge case behaviors to handle here. Addresses are treated as fixed, EINVAL is returned for bad mappings, name should be preserved from PoolReserving, committed areas should coalesce, reserved areas get their phys_base updated * Formatting * Adjust fixed PoolReserve path Hardware tests suggest this will overwrite all VMAs in the range. Run UnmapMemoryImpl on the full area, then reserve. Same logic applies to normal reservations too. Also adjusts logic of the non-fixed path to more closely align with hardware observations. * Remove phys_base modifications This can be handled later. Doing the logic properly would likely take work in MergeAdjacent, and would probably need to be applied to normal dmem mappings too. * Use VMAHandle.Contains() Why do extra math when we have a function specifically for this? * Update memory.cpp * Remove unnecessary code Since I've removed those two asserts, these two lines of code effectively do nothing. * Clang * Fix names * Fix PoolDecommit Should fix the address space regressions in UE titles on Windows. * Fix error log Should make the cause of this clearer? * Clang * Oops * Remove coalesce on PoolCommit Windows makes this more difficult. * Track pool budgets If you try to commit more pooled memory than is allocated, PoolCommit returns ENOMEM. Also fixes error conditions for PoolDecommit, that should return EINVAL if given an address that isn't part of the pool. Note: Seems like the pool budget can't hit zero? I used a <= comparison based on hardware tests, otherwise we're able to make more mappings than real hardware can. --- src/core/libraries/kernel/memory.cpp | 27 +++-- src/core/memory.cpp | 146 +++++++++++++++++---------- src/core/memory.h | 3 +- 3 files changed, 111 insertions(+), 65 deletions(-) diff --git a/src/core/libraries/kernel/memory.cpp b/src/core/libraries/kernel/memory.cpp index 495ddc52f..9fcaa2439 100644 --- a/src/core/libraries/kernel/memory.cpp +++ b/src/core/libraries/kernel/memory.cpp @@ -383,13 +383,12 @@ s32 PS4_SYSV_ABI sceKernelMemoryPoolExpand(u64 searchStart, u64 searchEnd, size_ LOG_ERROR(Kernel_Vmm, "Provided address range is invalid!"); return ORBIS_KERNEL_ERROR_EINVAL; } - const bool is_in_range = searchEnd - searchStart >= len; - if (len <= 0 || !Common::Is64KBAligned(len) || !is_in_range) { - LOG_ERROR(Kernel_Vmm, "Provided address range is invalid!"); + if (len <= 0 || !Common::Is64KBAligned(len)) { + LOG_ERROR(Kernel_Vmm, "Provided length {:#x} is invalid!", len); return ORBIS_KERNEL_ERROR_EINVAL; } if (alignment != 0 && !Common::Is64KBAligned(alignment)) { - LOG_ERROR(Kernel_Vmm, "Alignment value is invalid!"); + LOG_ERROR(Kernel_Vmm, "Alignment {:#x} is invalid!", alignment); return ORBIS_KERNEL_ERROR_EINVAL; } if (physAddrOut == nullptr) { @@ -397,8 +396,21 @@ s32 PS4_SYSV_ABI sceKernelMemoryPoolExpand(u64 searchStart, u64 searchEnd, size_ return ORBIS_KERNEL_ERROR_EINVAL; } + const bool is_in_range = searchEnd - searchStart >= len; + if (searchEnd <= searchStart || searchEnd < len || !is_in_range) { + LOG_ERROR(Kernel_Vmm, + "Provided address range is too small!" + " searchStart = {:#x}, searchEnd = {:#x}, length = {:#x}", + searchStart, searchEnd, len); + return ORBIS_KERNEL_ERROR_ENOMEM; + } + auto* memory = Core::Memory::Instance(); PAddr phys_addr = memory->PoolExpand(searchStart, searchEnd, len, alignment); + if (phys_addr == -1) { + return ORBIS_KERNEL_ERROR_ENOMEM; + } + *physAddrOut = static_cast(phys_addr); LOG_INFO(Kernel_Vmm, @@ -413,10 +425,6 @@ s32 PS4_SYSV_ABI sceKernelMemoryPoolReserve(void* addrIn, size_t len, size_t ali LOG_INFO(Kernel_Vmm, "addrIn = {}, len = {:#x}, alignment = {:#x}, flags = {:#x}", fmt::ptr(addrIn), len, alignment, flags); - if (addrIn == nullptr) { - LOG_ERROR(Kernel_Vmm, "Address is invalid!"); - return ORBIS_KERNEL_ERROR_EINVAL; - } if (len == 0 || !Common::Is2MBAligned(len)) { LOG_ERROR(Kernel_Vmm, "Map size is either zero or not 2MB aligned!"); return ORBIS_KERNEL_ERROR_EINVAL; @@ -469,9 +477,8 @@ s32 PS4_SYSV_ABI sceKernelMemoryPoolDecommit(void* addr, size_t len, int flags) const VAddr pool_addr = reinterpret_cast(addr); auto* memory = Core::Memory::Instance(); - memory->PoolDecommit(pool_addr, len); - return ORBIS_OK; + return memory->PoolDecommit(pool_addr, len); } int PS4_SYSV_ABI sceKernelMmap(void* addr, u64 len, int prot, int flags, int fd, size_t offset, diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 9861e813a..8fef8d102 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -109,31 +109,42 @@ bool MemoryManager::TryWriteBacking(void* address, const void* data, u32 num_byt PAddr MemoryManager::PoolExpand(PAddr search_start, PAddr search_end, size_t size, u64 alignment) { std::scoped_lock lk{mutex}; + alignment = alignment > 0 ? alignment : 64_KB; auto dmem_area = FindDmemArea(search_start); + auto mapping_start = search_start > dmem_area->second.base + ? Common::AlignUp(search_start, alignment) + : Common::AlignUp(dmem_area->second.base, alignment); + auto mapping_end = mapping_start + size; - const auto is_suitable = [&] { - const auto aligned_base = alignment > 0 ? Common::AlignUp(dmem_area->second.base, alignment) - : dmem_area->second.base; - const auto alignment_size = aligned_base - dmem_area->second.base; - const auto remaining_size = - dmem_area->second.size >= alignment_size ? dmem_area->second.size - alignment_size : 0; - return dmem_area->second.is_free && remaining_size >= size; - }; - while (!is_suitable() && dmem_area->second.GetEnd() <= search_end) { + // Find the first free, large enough dmem area in the range. + while (!dmem_area->second.is_free || dmem_area->second.GetEnd() < mapping_end) { + // The current dmem_area isn't suitable, move to the next one. dmem_area++; - } - ASSERT_MSG(is_suitable(), "Unable to find free direct memory area: size = {:#x}", size); + if (dmem_area == dmem_map.end()) { + break; + } - // Align free position - PAddr free_addr = dmem_area->second.base; - free_addr = alignment > 0 ? Common::AlignUp(free_addr, alignment) : free_addr; + // Update local variables based on the new dmem_area + mapping_start = Common::AlignUp(dmem_area->second.base, alignment); + mapping_end = mapping_start + size; + } + + if (dmem_area == dmem_map.end()) { + // There are no suitable mappings in this range + LOG_ERROR(Kernel_Vmm, "Unable to find free direct memory area: size = {:#x}", size); + return -1; + } // Add the allocated region to the list and commit its pages. - auto& area = CarveDmemArea(free_addr, size)->second; + auto& area = CarveDmemArea(mapping_start, size)->second; area.is_free = false; area.is_pooled = true; - return free_addr; + + // Track how much dmem was allocated for pools. + pool_budget += size; + + return mapping_start; } PAddr MemoryManager::Allocate(PAddr search_start, PAddr search_end, size_t size, u64 alignment, @@ -206,27 +217,27 @@ void MemoryManager::Free(PAddr phys_addr, size_t size) { int MemoryManager::PoolReserve(void** out_addr, VAddr virtual_addr, size_t size, MemoryMapFlags flags, u64 alignment) { std::scoped_lock lk{mutex}; - - virtual_addr = (virtual_addr == 0) ? impl.SystemManagedVirtualBase() : virtual_addr; alignment = alignment > 0 ? alignment : 2_MB; - VAddr mapped_addr = alignment > 0 ? Common::AlignUp(virtual_addr, alignment) : virtual_addr; + VAddr min_address = Common::AlignUp(impl.SystemManagedVirtualBase(), alignment); + VAddr mapped_addr = Common::AlignUp(virtual_addr, alignment); // Fixed mapping means the virtual address must exactly match the provided one. if (True(flags & MemoryMapFlags::Fixed)) { - auto& vma = FindVMA(mapped_addr)->second; - // If the VMA is mapped, unmap the region first. - if (vma.IsMapped()) { + // Make sure we're mapping to a valid address + mapped_addr = mapped_addr > min_address ? mapped_addr : min_address; + auto vma = FindVMA(mapped_addr)->second; + size_t remaining_size = vma.base + vma.size - mapped_addr; + // If the VMA is mapped or there's not enough space, unmap the region first. + if (vma.IsMapped() || remaining_size < size) { UnmapMemoryImpl(mapped_addr, size); vma = FindVMA(mapped_addr)->second; } - const size_t remaining_size = vma.base + vma.size - mapped_addr; - ASSERT_MSG(vma.type == VMAType::Free && remaining_size >= size, - "Memory region {:#x} to {:#x} is not large enough to reserve {:#x} to {:#x}", - vma.base, vma.base + vma.size, virtual_addr, virtual_addr + size); } - // Find the first free area starting with provided virtual address. if (False(flags & MemoryMapFlags::Fixed)) { + // When MemoryMapFlags::Fixed is not specified, and mapped_addr is 0, + // search from address 0x200000000 instead. + mapped_addr = mapped_addr == 0 ? 0x200000000 : mapped_addr; mapped_addr = SearchFree(mapped_addr, size, alignment); if (mapped_addr == -1) { // No suitable memory areas to map to @@ -241,7 +252,6 @@ int MemoryManager::PoolReserve(void** out_addr, VAddr virtual_addr, size_t size, new_vma.prot = MemoryProt::NoAccess; new_vma.name = "anon"; new_vma.type = VMAType::PoolReserved; - MergeAdjacent(vma_map, new_vma_handle); *out_addr = std::bit_cast(mapped_addr); return ORBIS_OK; @@ -258,15 +268,12 @@ int MemoryManager::Reserve(void** out_addr, VAddr virtual_addr, size_t size, Mem // Fixed mapping means the virtual address must exactly match the provided one. if (True(flags & MemoryMapFlags::Fixed)) { auto vma = FindVMA(mapped_addr)->second; - // If the VMA is mapped, unmap the region first. - if (vma.IsMapped()) { + size_t remaining_size = vma.base + vma.size - mapped_addr; + // If the VMA is mapped or there's not enough space, unmap the region first. + if (vma.IsMapped() || remaining_size < size) { UnmapMemoryImpl(mapped_addr, size); vma = FindVMA(mapped_addr)->second; } - const size_t remaining_size = vma.base + vma.size - mapped_addr; - ASSERT_MSG(vma.type == VMAType::Free && remaining_size >= size, - "Memory region {:#x} to {:#x} is not large enough to reserve {:#x} to {:#x}", - vma.base, vma.base + vma.size, virtual_addr, virtual_addr + size); } // Find the first free area starting with provided virtual address. @@ -296,30 +303,47 @@ int MemoryManager::PoolCommit(VAddr virtual_addr, size_t size, MemoryProt prot) const u64 alignment = 64_KB; - // When virtual addr is zero, force it to virtual_base. The guest cannot pass Fixed - // flag so we will take the branch that searches for free (or reserved) mappings. - virtual_addr = (virtual_addr == 0) ? impl.SystemManagedVirtualBase() : virtual_addr; + // Input addresses to PoolCommit are treated as fixed. VAddr mapped_addr = Common::AlignUp(virtual_addr, alignment); - // This should return SCE_KERNEL_ERROR_ENOMEM but shouldn't normally happen. - const auto& vma = FindVMA(mapped_addr)->second; - const size_t remaining_size = vma.base + vma.size - mapped_addr; - ASSERT_MSG(!vma.IsMapped() && remaining_size >= size, - "Memory region {:#x} to {:#x} isn't free enough to map region {:#x} to {:#x}", - vma.base, vma.base + vma.size, virtual_addr, virtual_addr + size); + auto& vma = FindVMA(mapped_addr)->second; + if (vma.type != VMAType::PoolReserved) { + // If we're attempting to commit non-pooled memory, return EINVAL + LOG_ERROR(Kernel_Vmm, "Attempting to commit non-pooled memory at {:#x}", mapped_addr); + return ORBIS_KERNEL_ERROR_EINVAL; + } - // Perform the mapping. - void* out_addr = impl.Map(mapped_addr, size, alignment, -1, false); - TRACK_ALLOC(out_addr, size, "VMEM"); + if (!vma.Contains(mapped_addr, size)) { + // If there's not enough space to commit, return EINVAL + LOG_ERROR(Kernel_Vmm, + "Pooled region {:#x} to {:#x} is not large enough to commit from {:#x} to {:#x}", + vma.base, vma.base + vma.size, mapped_addr, mapped_addr + size); + return ORBIS_KERNEL_ERROR_EINVAL; + } - auto& new_vma = CarveVMA(mapped_addr, size)->second; + if (pool_budget <= size) { + // If there isn't enough pooled memory to perform the mapping, return ENOMEM + LOG_ERROR(Kernel_Vmm, "Not enough pooled memory to perform mapping"); + return ORBIS_KERNEL_ERROR_ENOMEM; + } else { + // Track how much pooled memory this commit will take + pool_budget -= size; + } + + // Carve out the new VMA representing this mapping + const auto new_vma_handle = CarveVMA(mapped_addr, size); + auto& new_vma = new_vma_handle->second; new_vma.disallow_merge = false; new_vma.prot = prot; - new_vma.name = ""; + new_vma.name = "anon"; new_vma.type = Core::VMAType::Pooled; new_vma.is_exec = false; new_vma.phys_base = 0; + // Perform the mapping + void* out_addr = impl.Map(mapped_addr, size, alignment, -1, false); + TRACK_ALLOC(out_addr, size, "VMEM"); + if (IsValidGpuMapping(mapped_addr, size)) { rasterizer->MapMemory(mapped_addr, size); } @@ -438,7 +462,7 @@ int MemoryManager::MapFile(void** out_addr, VAddr virtual_addr, size_t size, Mem return ORBIS_OK; } -void MemoryManager::PoolDecommit(VAddr virtual_addr, size_t size) { +s32 MemoryManager::PoolDecommit(VAddr virtual_addr, size_t size) { std::scoped_lock lk{mutex}; const auto it = FindVMA(virtual_addr); @@ -453,6 +477,16 @@ void MemoryManager::PoolDecommit(VAddr virtual_addr, size_t size) { const auto start_in_vma = virtual_addr - vma_base_addr; const auto type = vma_base.type; + if (type != VMAType::PoolReserved && type != VMAType::Pooled) { + LOG_ERROR(Kernel_Vmm, "Attempting to decommit non-pooled memory!"); + return ORBIS_KERNEL_ERROR_EINVAL; + } + + if (type == VMAType::Pooled) { + // Track how much pooled memory is decommitted + pool_budget += size; + } + if (IsValidGpuMapping(virtual_addr, size)) { rasterizer->UnmapMemory(virtual_addr, size); } @@ -464,13 +498,17 @@ void MemoryManager::PoolDecommit(VAddr virtual_addr, size_t size) { vma.prot = MemoryProt::NoAccess; vma.phys_base = 0; vma.disallow_merge = false; - vma.name = ""; + vma.name = "anon"; MergeAdjacent(vma_map, new_it); - // Unmap the memory region. - impl.Unmap(vma_base_addr, vma_base_size, start_in_vma, start_in_vma + size, phys_base, is_exec, - false, false); - TRACK_FREE(virtual_addr, "VMEM"); + if (type != VMAType::PoolReserved) { + // Unmap the memory region. + impl.Unmap(vma_base_addr, vma_base_size, start_in_vma, start_in_vma + size, phys_base, + is_exec, false, false); + TRACK_FREE(virtual_addr, "VMEM"); + } + + return ORBIS_OK; } s32 MemoryManager::UnmapMemory(VAddr virtual_addr, size_t size) { diff --git a/src/core/memory.h b/src/core/memory.h index 3a204eb96..4920aa397 100644 --- a/src/core/memory.h +++ b/src/core/memory.h @@ -198,7 +198,7 @@ public: int MapFile(void** out_addr, VAddr virtual_addr, size_t size, MemoryProt prot, MemoryMapFlags flags, uintptr_t fd, size_t offset); - void PoolDecommit(VAddr virtual_addr, size_t size); + s32 PoolDecommit(VAddr virtual_addr, size_t size); s32 UnmapMemory(VAddr virtual_addr, size_t size); @@ -274,6 +274,7 @@ private: size_t total_direct_size{}; size_t total_flexible_size{}; size_t flexible_usage{}; + size_t pool_budget{}; Vulkan::Rasterizer* rasterizer{}; friend class ::Core::Devtools::Widget::MemoryMapViewer; From ff1339b0b663fe45c3376083bb3377b3deb99dbb Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Sun, 11 May 2025 19:03:55 +0300 Subject: [PATCH 4/9] [Libs] Camera (#2902) * stubbed camera lib * function definations * added error codes --- CMakeLists.txt | 6 + src/common/logging/filter.cpp | 1 + src/common/logging/types.h | 1 + src/core/libraries/camera/camera.cpp | 517 +++++++++++++++++++++++ src/core/libraries/camera/camera.h | 308 ++++++++++++++ src/core/libraries/camera/camera_error.h | 29 ++ src/core/libraries/libs.cpp | 2 + 7 files changed, 864 insertions(+) create mode 100644 src/core/libraries/camera/camera.cpp create mode 100644 src/core/libraries/camera/camera.h create mode 100644 src/core/libraries/camera/camera_error.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 9b10d0e5b..c182e0658 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -601,6 +601,11 @@ set(MISC_LIBS src/core/libraries/screenshot/screenshot.cpp src/core/libraries/signin_dialog/signindialog.h ) +set(CAMERA_LIBS src/core/libraries/camera/camera.cpp + src/core/libraries/camera/camera.h + src/core/libraries/camera/camera_error.h +) + set(DEV_TOOLS src/core/devtools/layer.cpp src/core/devtools/layer.h src/core/devtools/options.cpp @@ -764,6 +769,7 @@ set(CORE src/core/aerolib/stubs.cpp ${FIBER_LIB} ${VDEC_LIB} ${VR_LIBS} + ${CAMERA_LIBS} ${DEV_TOOLS} src/core/debug_state.cpp src/core/debug_state.h diff --git a/src/common/logging/filter.cpp b/src/common/logging/filter.cpp index 622af93cc..1b605e9ed 100644 --- a/src/common/logging/filter.cpp +++ b/src/common/logging/filter.cpp @@ -138,6 +138,7 @@ bool ParseFilterRule(Filter& instance, Iterator begin, Iterator end) { SUB(Lib, Zlib) \ SUB(Lib, Hmd) \ SUB(Lib, SigninDialog) \ + SUB(Lib, Camera) \ CLS(Frontend) \ CLS(Render) \ SUB(Render, Vulkan) \ diff --git a/src/common/logging/types.h b/src/common/logging/types.h index 27a87e082..5746b648e 100644 --- a/src/common/logging/types.h +++ b/src/common/logging/types.h @@ -105,6 +105,7 @@ enum class Class : u8 { Lib_Zlib, ///< The LibSceZlib implementation. Lib_Hmd, ///< The LibSceHmd implementation. Lib_SigninDialog, ///< The LibSigninDialog implementation. + Lib_Camera, ///< The LibCamera implementation. Frontend, ///< Emulator UI Render, ///< Video Core Render_Vulkan, ///< Vulkan backend diff --git a/src/core/libraries/camera/camera.cpp b/src/core/libraries/camera/camera.cpp new file mode 100644 index 000000000..996d1c895 --- /dev/null +++ b/src/core/libraries/camera/camera.cpp @@ -0,0 +1,517 @@ +// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "common/logging/log.h" +#include "core/libraries/camera/camera.h" +#include "core/libraries/camera/camera_error.h" +#include "core/libraries/error_codes.h" +#include "core/libraries/libs.h" + +namespace Libraries::Camera { + +s32 PS4_SYSV_ABI sceCameraAccGetData() { + LOG_ERROR(Lib_Camera, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceCameraAudioClose() { + LOG_ERROR(Lib_Camera, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceCameraAudioGetData() { + LOG_ERROR(Lib_Camera, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceCameraAudioGetData2() { + LOG_ERROR(Lib_Camera, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceCameraAudioOpen() { + LOG_ERROR(Lib_Camera, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceCameraAudioReset() { + LOG_ERROR(Lib_Camera, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceCameraChangeAppModuleState() { + LOG_ERROR(Lib_Camera, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceCameraClose(s32 handle) { + LOG_ERROR(Lib_Camera, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceCameraCloseByHandle() { + LOG_ERROR(Lib_Camera, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceCameraDeviceOpen() { + LOG_ERROR(Lib_Camera, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceCameraGetAttribute(s32 handle, OrbisCameraAttribute* pAttribute) { + LOG_ERROR(Lib_Camera, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceCameraGetAutoExposureGain(s32 handle, OrbisCameraChannel channel, u32* pEnable, + void* pOption) { + LOG_ERROR(Lib_Camera, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceCameraGetAutoWhiteBalance(s32 handle, OrbisCameraChannel channel, u32* pEnable, + void* pOption) { + LOG_ERROR(Lib_Camera, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceCameraGetCalibData() { + LOG_ERROR(Lib_Camera, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceCameraGetCalibDataFromDevice() { + LOG_ERROR(Lib_Camera, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceCameraGetCalibrationData() { + LOG_ERROR(Lib_Camera, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceCameraGetConfig(s32 handle, OrbisCameraConfig* pConfig) { + LOG_ERROR(Lib_Camera, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceCameraGetContrast(s32 handle, OrbisCameraChannel channel, u32* pContrast, + void* pOption) { + LOG_ERROR(Lib_Camera, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceCameraGetDefectivePixelCancellation(s32 handle, OrbisCameraChannel channel, + u32* pEnable, void* pOption) { + LOG_ERROR(Lib_Camera, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceCameraGetDeviceConfig() { + LOG_ERROR(Lib_Camera, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceCameraGetDeviceConfigWithoutHandle() { + LOG_ERROR(Lib_Camera, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceCameraGetDeviceID() { + LOG_ERROR(Lib_Camera, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceCameraGetDeviceIDWithoutOpen() { + LOG_ERROR(Lib_Camera, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceCameraGetDeviceInfo(s32 reserved, OrbisCameraDeviceInfo* pDeviceInfo) { + LOG_ERROR(Lib_Camera, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceCameraGetExposureGain(s32 handle, OrbisCameraChannel channel, + OrbisCameraExposureGain* pExposureGain, void* pOption) { + LOG_ERROR(Lib_Camera, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceCameraGetFrameData(int handle, OrbisCameraFrameData* pFrameData) { + LOG_ERROR(Lib_Camera, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceCameraGetGamma(s32 handle, OrbisCameraChannel channel, OrbisCameraGamma* pGamma, + void* pOption) { + LOG_ERROR(Lib_Camera, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceCameraGetHue(s32 handle, OrbisCameraChannel channel, s32* pHue, void* pOption) { + LOG_ERROR(Lib_Camera, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceCameraGetLensCorrection(s32 handle, OrbisCameraChannel channel, u32* pEnable, + void* pOption) { + LOG_ERROR(Lib_Camera, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceCameraGetMmapConnectedCount() { + LOG_ERROR(Lib_Camera, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceCameraGetProductInfo() { + LOG_ERROR(Lib_Camera, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceCameraGetRegister() { + LOG_ERROR(Lib_Camera, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceCameraGetRegistryInfo() { + LOG_ERROR(Lib_Camera, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceCameraGetSaturation(s32 handle, OrbisCameraChannel channel, u32* pSaturation, + void* pOption) { + LOG_ERROR(Lib_Camera, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceCameraGetSharpness(s32 handle, OrbisCameraChannel channel, u32* pSharpness, + void* pOption) { + LOG_ERROR(Lib_Camera, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceCameraGetVrCaptureInfo() { + LOG_ERROR(Lib_Camera, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceCameraGetWhiteBalance(s32 handle, OrbisCameraChannel channel, + OrbisCameraWhiteBalance* pWhiteBalance, void* pOption) { + LOG_ERROR(Lib_Camera, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceCameraInitializeRegistryCalibData() { + LOG_ERROR(Lib_Camera, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceCameraIsAttached(s32 index) { + LOG_ERROR(Lib_Camera, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceCameraIsConfigChangeDone() { + LOG_ERROR(Lib_Camera, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceCameraIsValidFrameData(int handle, OrbisCameraFrameData* pFrameData) { + LOG_ERROR(Lib_Camera, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceCameraOpen(Libraries::UserService::OrbisUserServiceUserId userId, s32 type, + s32 index, OrbisCameraOpenParameter* pParam) { + LOG_ERROR(Lib_Camera, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceCameraOpenByModuleId() { + LOG_ERROR(Lib_Camera, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceCameraRemoveAppModuleFocus() { + LOG_ERROR(Lib_Camera, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceCameraSetAppModuleFocus() { + LOG_ERROR(Lib_Camera, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceCameraSetAttribute(s32 handle, OrbisCameraAttribute* pAttribute) { + LOG_ERROR(Lib_Camera, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceCameraSetAttributeInternal() { + LOG_ERROR(Lib_Camera, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceCameraSetAutoExposureGain(s32 handle, OrbisCameraChannel channel, u32 enable, + void* pOption) { + LOG_ERROR(Lib_Camera, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceCameraSetAutoWhiteBalance(s32 handle, OrbisCameraChannel channel, u32 enable, + void* pOption) { + LOG_ERROR(Lib_Camera, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceCameraSetCalibData() { + LOG_ERROR(Lib_Camera, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceCameraSetConfig(s32 handle, OrbisCameraConfig* pConfig) { + LOG_ERROR(Lib_Camera, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceCameraSetConfigInternal() { + LOG_ERROR(Lib_Camera, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceCameraSetContrast(s32 handle, OrbisCameraChannel channel, u32 contrast, + void* pOption) { + LOG_ERROR(Lib_Camera, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceCameraSetDebugStop() { + LOG_ERROR(Lib_Camera, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceCameraSetDefectivePixelCancellation(s32 handle, OrbisCameraChannel channel, + u32 enable, void* pOption) { + LOG_ERROR(Lib_Camera, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceCameraSetDefectivePixelCancellationInternal() { + LOG_ERROR(Lib_Camera, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceCameraSetExposureGain(s32 handle, OrbisCameraChannel channel, + OrbisCameraExposureGain* pExposureGain, void* pOption) { + LOG_ERROR(Lib_Camera, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceCameraSetForceActivate() { + LOG_ERROR(Lib_Camera, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceCameraSetGamma(s32 handle, OrbisCameraChannel channel, OrbisCameraGamma* pGamma, + void* pOption) { + LOG_ERROR(Lib_Camera, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceCameraSetHue(s32 handle, OrbisCameraChannel channel, s32 hue, void* pOption) { + LOG_ERROR(Lib_Camera, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceCameraSetLensCorrection(s32 handle, OrbisCameraChannel channel, u32 enable, + void* pOption) { + LOG_ERROR(Lib_Camera, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceCameraSetLensCorrectionInternal() { + LOG_ERROR(Lib_Camera, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceCameraSetProcessFocus() { + LOG_ERROR(Lib_Camera, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceCameraSetProcessFocusByHandle() { + LOG_ERROR(Lib_Camera, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceCameraSetRegister() { + LOG_ERROR(Lib_Camera, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceCameraSetSaturation(s32 handle, OrbisCameraChannel channel, u32 saturation, + void* pOption) { + LOG_ERROR(Lib_Camera, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceCameraSetSharpness(s32 handle, OrbisCameraChannel channel, u32 sharpness, + void* pOption) { + LOG_ERROR(Lib_Camera, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceCameraSetTrackerMode() { + LOG_ERROR(Lib_Camera, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceCameraSetUacModeInternal() { + LOG_ERROR(Lib_Camera, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceCameraSetVideoSync(s32 handle, OrbisCameraVideoSyncParameter* pVideoSync) { + LOG_ERROR(Lib_Camera, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceCameraSetVideoSyncInternal() { + LOG_ERROR(Lib_Camera, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceCameraSetWhiteBalance(s32 handle, OrbisCameraChannel channel, + OrbisCameraWhiteBalance* pWhiteBalance, void* pOption) { + LOG_ERROR(Lib_Camera, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceCameraStart(s32 handle, OrbisCameraStartParameter* pParam) { + LOG_ERROR(Lib_Camera, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceCameraStartByHandle() { + LOG_ERROR(Lib_Camera, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceCameraStop(s32 handle) { + LOG_ERROR(Lib_Camera, "(STUBBED) called"); + return ORBIS_OK; +} + +s32 PS4_SYSV_ABI sceCameraStopByHandle() { + LOG_ERROR(Lib_Camera, "(STUBBED) called"); + return ORBIS_OK; +} + +void RegisterlibSceCamera(Core::Loader::SymbolsResolver* sym) { + LIB_FUNCTION("QhjrPkRPUZQ", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraAccGetData); + LIB_FUNCTION("UFonL7xopFM", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraAudioClose); + LIB_FUNCTION("fkZE7Hup2ro", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraAudioGetData); + LIB_FUNCTION("hftC5A1C8OQ", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraAudioGetData2); + LIB_FUNCTION("DhqqFiBU+6g", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraAudioOpen); + LIB_FUNCTION("wyU98EXAYxU", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraAudioReset); + LIB_FUNCTION("Y0pCDajzkVQ", "libSceCamera", 1, "libSceCamera", 1, 1, + sceCameraChangeAppModuleState); + LIB_FUNCTION("OMS9LlcrvBo", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraClose); + LIB_FUNCTION("ztqH5qNTpTk", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraCloseByHandle); + LIB_FUNCTION("nBH6i2s4Glc", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraDeviceOpen); + LIB_FUNCTION("0btIPD5hg5A", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraGetAttribute); + LIB_FUNCTION("oEi6vM-3E2c", "libSceCamera", 1, "libSceCamera", 1, 1, + sceCameraGetAutoExposureGain); + LIB_FUNCTION("qTPRMh4eY60", "libSceCamera", 1, "libSceCamera", 1, 1, + sceCameraGetAutoWhiteBalance); + LIB_FUNCTION("hHA1frlMxYE", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraGetCalibData); + LIB_FUNCTION("5Oie5RArfWs", "libSceCamera", 1, "libSceCamera", 1, 1, + sceCameraGetCalibDataFromDevice); + LIB_FUNCTION("RHYJ7GKOSMg", "libSceCamera", 1, "libSceCamera", 1, 1, + sceCameraGetCalibrationData); + LIB_FUNCTION("ZaqmGEtYuL0", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraGetConfig); + LIB_FUNCTION("a5xFueMZIMs", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraGetContrast); + LIB_FUNCTION("tslCukqFE+E", "libSceCamera", 1, "libSceCamera", 1, 1, + sceCameraGetDefectivePixelCancellation); + LIB_FUNCTION("DSOLCrc3Kh8", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraGetDeviceConfig); + LIB_FUNCTION("n+rFeP1XXyM", "libSceCamera", 1, "libSceCamera", 1, 1, + sceCameraGetDeviceConfigWithoutHandle); + LIB_FUNCTION("jTJCdyv9GLU", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraGetDeviceID); + LIB_FUNCTION("-H3UwGQvNZI", "libSceCamera", 1, "libSceCamera", 1, 1, + sceCameraGetDeviceIDWithoutOpen); + LIB_FUNCTION("WZpxnSAM-ds", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraGetDeviceInfo); + LIB_FUNCTION("ObIste7hqdk", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraGetExposureGain); + LIB_FUNCTION("mxgMmR+1Kr0", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraGetFrameData); + LIB_FUNCTION("WVox2rwGuSc", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraGetGamma); + LIB_FUNCTION("zrIUDKZx0iE", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraGetHue); + LIB_FUNCTION("XqYRHc4aw3w", "libSceCamera", 1, "libSceCamera", 1, 1, + sceCameraGetLensCorrection); + LIB_FUNCTION("B260o9pSzM8", "libSceCamera", 1, "libSceCamera", 1, 1, + sceCameraGetMmapConnectedCount); + LIB_FUNCTION("ULxbwqiYYuU", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraGetProductInfo); + LIB_FUNCTION("olojYZKYiYs", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraGetRegister); + LIB_FUNCTION("hawKak+Auw4", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraGetRegistryInfo); + LIB_FUNCTION("RTDOsWWqdME", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraGetSaturation); + LIB_FUNCTION("c6Fp9M1EXXc", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraGetSharpness); + LIB_FUNCTION("IAz2HgZQWzE", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraGetVrCaptureInfo); + LIB_FUNCTION("HX5524E5tMY", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraGetWhiteBalance); + LIB_FUNCTION("0wnf2a60FqI", "libSceCamera", 1, "libSceCamera", 1, 1, + sceCameraInitializeRegistryCalibData); + LIB_FUNCTION("p6n3Npi3YY4", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraIsAttached); + LIB_FUNCTION("wQfd7kfRZvo", "libSceCamera", 1, "libSceCamera", 1, 1, + sceCameraIsConfigChangeDone); + LIB_FUNCTION("U3BVwQl2R5Q", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraIsValidFrameData); + LIB_FUNCTION("BHn83xrF92E", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraOpen); + LIB_FUNCTION("eTywOSWsEiI", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraOpenByModuleId); + LIB_FUNCTION("py8p6kZcHmA", "libSceCamera", 1, "libSceCamera", 1, 1, + sceCameraRemoveAppModuleFocus); + LIB_FUNCTION("j5isFVIlZLk", "libSceCamera", 1, "libSceCamera", 1, 1, + sceCameraSetAppModuleFocus); + LIB_FUNCTION("doPlf33ab-U", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraSetAttribute); + LIB_FUNCTION("96F7zp1Xo+k", "libSceCamera", 1, "libSceCamera", 1, 1, + sceCameraSetAttributeInternal); + LIB_FUNCTION("yfSdswDaElo", "libSceCamera", 1, "libSceCamera", 1, 1, + sceCameraSetAutoExposureGain); + LIB_FUNCTION("zIKL4kZleuc", "libSceCamera", 1, "libSceCamera", 1, 1, + sceCameraSetAutoWhiteBalance); + LIB_FUNCTION("LEMk5cTHKEA", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraSetCalibData); + LIB_FUNCTION("VQ+5kAqsE2Q", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraSetConfig); + LIB_FUNCTION("9+SNhbctk64", "libSceCamera", 1, "libSceCamera", 1, 1, + sceCameraSetConfigInternal); + LIB_FUNCTION("3i5MEzrC1pg", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraSetContrast); + LIB_FUNCTION("vejouEusC7g", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraSetDebugStop); + LIB_FUNCTION("jMv40y2A23g", "libSceCamera", 1, "libSceCamera", 1, 1, + sceCameraSetDefectivePixelCancellation); + LIB_FUNCTION("vER3cIMBHqI", "libSceCamera", 1, "libSceCamera", 1, 1, + sceCameraSetDefectivePixelCancellationInternal); + LIB_FUNCTION("wgBMXJJA6K4", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraSetExposureGain); + LIB_FUNCTION("jeTpU0MqKU0", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraSetForceActivate); + LIB_FUNCTION("lhEIsHzB8r4", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraSetGamma); + LIB_FUNCTION("QI8GVJUy2ZY", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraSetHue); + LIB_FUNCTION("K7W7H4ZRwbc", "libSceCamera", 1, "libSceCamera", 1, 1, + sceCameraSetLensCorrection); + LIB_FUNCTION("eHa3vhGu2rQ", "libSceCamera", 1, "libSceCamera", 1, 1, + sceCameraSetLensCorrectionInternal); + LIB_FUNCTION("lS0tM6n+Q5E", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraSetProcessFocus); + LIB_FUNCTION("NVITuK83Z7o", "libSceCamera", 1, "libSceCamera", 1, 1, + sceCameraSetProcessFocusByHandle); + LIB_FUNCTION("8MjO05qk5hA", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraSetRegister); + LIB_FUNCTION("bSKEi2PzzXI", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraSetSaturation); + LIB_FUNCTION("P-7MVfzvpsM", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraSetSharpness); + LIB_FUNCTION("3VJOpzKoIeM", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraSetTrackerMode); + LIB_FUNCTION("nnR7KAIDPv8", "libSceCamera", 1, "libSceCamera", 1, 1, + sceCameraSetUacModeInternal); + LIB_FUNCTION("wpeyFwJ+UEI", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraSetVideoSync); + LIB_FUNCTION("8WtmqmE4edw", "libSceCamera", 1, "libSceCamera", 1, 1, + sceCameraSetVideoSyncInternal); + LIB_FUNCTION("k3zPIcgFNv0", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraSetWhiteBalance); + LIB_FUNCTION("9EpRYMy7rHU", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraStart); + LIB_FUNCTION("cLxF1QtHch0", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraStartByHandle); + LIB_FUNCTION("2G2C0nmd++M", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraStop); + LIB_FUNCTION("+X1Kgnn3bzg", "libSceCamera", 1, "libSceCamera", 1, 1, sceCameraStopByHandle); +}; + +} // namespace Libraries::Camera \ No newline at end of file diff --git a/src/core/libraries/camera/camera.h b/src/core/libraries/camera/camera.h new file mode 100644 index 000000000..51aa8b729 --- /dev/null +++ b/src/core/libraries/camera/camera.h @@ -0,0 +1,308 @@ +// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#include "common/types.h" + +namespace Core::Loader { +class SymbolsResolver; +} + +namespace Libraries::Camera { + +constexpr int ORBIS_CAMERA_MAX_DEVICE_NUM = 2; +constexpr int ORBIS_CAMERA_MAX_FORMAT_LEVEL_NUM = 4; + +enum OrbisCameraChannel { + ORBIS_CAMERA_CHANNEL_0 = 1, + ORBIS_CAMERA_CHANNEL_1 = 2, + ORBIS_CAMERA_CHANNEL_BOTH = 3, +}; + +struct OrbisCameraOpenParameter { + u32 sizeThis; + u32 reserved1; + u32 reserved2; + u32 reserved3; +}; + +enum OrbisCameraConfigType { + ORBIS_CAMERA_CONFIG_TYPE1 = 0x01, + ORBIS_CAMERA_CONFIG_TYPE2 = 0x02, + ORBIS_CAMERA_CONFIG_TYPE3 = 0x03, + ORBIS_CAMERA_CONFIG_TYPE4 = 0x04, + ORBIS_CAMERA_CONFIG_TYPE5 = 0x05, + ORBIS_CAMERA_CONFIG_EXTENTION = 0x10, +}; + +enum OrbisCameraResolution { + ORBIS_CAMERA_RESOLUTION_1280X800 = 0x0, + ORBIS_CAMERA_RESOLUTION_640X400 = 0x1, + ORBIS_CAMERA_RESOLUTION_320X200 = 0x2, + ORBIS_CAMERA_RESOLUTION_160X100 = 0x3, + ORBIS_CAMERA_RESOLUTION_320X192 = 0x4, + ORBIS_CAMERA_RESOLUTION_SPECIFIED_WIDTH_HEIGHT, + ORBIS_CAMERA_RESOLUTION_UNKNOWN = 0xFF, +}; + +enum OrbisCameraFramerate { + ORBIS_CAMERA_FRAMERATE_UNKNOWN = 0, + ORBIS_CAMERA_FRAMERATE_7_5 = 7, + ORBIS_CAMERA_FRAMERATE_15 = 15, + ORBIS_CAMERA_FRAMERATE_30 = 30, + ORBIS_CAMERA_FRAMERATE_60 = 60, + ORBIS_CAMERA_FRAMERATE_120 = 120, + ORBIS_CAMERA_FRAMERATE_240 = 240, +}; + +enum OrbisCameraBaseFormat { + ORBIS_CAMERA_FORMAT_YUV422 = 0x0, + ORBIS_CAMERA_FORMAT_RAW16, + ORBIS_CAMERA_FORMAT_RAW8, + ORBIS_CAMERA_FORMAT_NO_USE = 0x10, + ORBIS_CAMERA_FORMAT_UNKNOWN = 0xFF, +}; + +enum OrbisCameraScaleFormat { + ORBIS_CAMERA_SCALE_FORMAT_YUV422 = 0x0, + ORBIS_CAMERA_SCALE_FORMAT_Y16 = 0x3, + ORBIS_CAMERA_SCALE_FORMAT_Y8, + ORBIS_CAMERA_SCALE_FORMAT_NO_USE = 0x10, + ORBIS_CAMERA_SCALE_FORMAT_UNKNOWN = 0xFF, +}; + +struct OrbisCameraFormat { + OrbisCameraBaseFormat formatLevel0; + OrbisCameraScaleFormat formatLevel1; + OrbisCameraScaleFormat formatLevel2; + OrbisCameraScaleFormat formatLevel3; +}; + +struct OrbisCameraConfigExtention { + OrbisCameraFormat format; + OrbisCameraResolution resolution; + OrbisCameraFramerate framerate; + u32 width; + u32 height; + u32 reserved1; + void* pBaseOption; +}; + +struct OrbisCameraConfig { + u32 sizeThis; + OrbisCameraConfigType configType; + OrbisCameraConfigExtention configExtention[ORBIS_CAMERA_MAX_DEVICE_NUM]; +}; + +enum OrbisCameraAecAgcTarget { + ORBIS_CAMERA_ATTRIBUTE_AECAGC_TARGET_DEF = 0x00, + ORBIS_CAMERA_ATTRIBUTE_AECAGC_TARGET_2_0 = 0x20, + ORBIS_CAMERA_ATTRIBUTE_AECAGC_TARGET_1_6 = 0x16, + ORBIS_CAMERA_ATTRIBUTE_AECAGC_TARGET_1_4 = 0x14, + ORBIS_CAMERA_ATTRIBUTE_AECAGC_TARGET_1_2 = 0x12, + ORBIS_CAMERA_ATTRIBUTE_AECAGC_TARGET_1_0 = 0x10, + ORBIS_CAMERA_ATTRIBUTE_AECAGC_TARGET_0_8 = 0x08, + ORBIS_CAMERA_ATTRIBUTE_AECAGC_TARGET_0_6 = 0x06, + ORBIS_CAMERA_ATTRIBUTE_AECAGC_TARGET_0_4 = 0x04, + ORBIS_CAMERA_ATTRIBUTE_AECAGC_TARGET_0_2 = 0x02, +}; + +struct OrbisCameraDeviceInfo { + u32 sizeThis; + u32 infoRevision; + u32 deviceRevision; + u32 padding; +}; + +struct OrbisCameraStartParameter { + u32 sizeThis; + u32 formatLevel[ORBIS_CAMERA_MAX_DEVICE_NUM]; + void* pStartOption; +}; + +struct OrbisCameraVideoSyncParameter { + u32 sizeThis; + u32 videoSyncMode; + void* pModeOption; +}; + +struct OrbisCameraFramePosition { + u32 x; + u32 y; + u32 xSize; + u32 ySize; +}; + +struct OrbisCameraAutoExposureGainTarget { + u32 sizeThis; + OrbisCameraAecAgcTarget target; +}; + +struct OrbisCameraExposureGain { + u32 exposureControl; + u32 exposure; + u32 gain; + u32 mode; +}; + +struct OrbisCameraWhiteBalance { + u32 whiteBalanceControl; + u32 gainRed; + u32 gainBlue; + u32 gainGreen; +}; + +struct OrbisCameraGamma { + u32 gammaControl; + u32 value; + u8 reserved[16]; +}; + +struct OrbisCameraMeta { + u32 metaMode; + u32 format[ORBIS_CAMERA_MAX_DEVICE_NUM][ORBIS_CAMERA_MAX_FORMAT_LEVEL_NUM]; + u64 frame[ORBIS_CAMERA_MAX_DEVICE_NUM]; + u64 timestamp[ORBIS_CAMERA_MAX_DEVICE_NUM]; + u32 deviceTimestamp[ORBIS_CAMERA_MAX_DEVICE_NUM]; + OrbisCameraExposureGain exposureGain[ORBIS_CAMERA_MAX_DEVICE_NUM]; + OrbisCameraWhiteBalance whiteBalance[ORBIS_CAMERA_MAX_DEVICE_NUM]; + OrbisCameraGamma gamma[ORBIS_CAMERA_MAX_DEVICE_NUM]; + u32 luminance[ORBIS_CAMERA_MAX_DEVICE_NUM]; + float acceleration_x; + float acceleration_y; + float acceleration_z; + u64 vcounter; + u32 reserved[14]; +}; + +struct OrbisCameraFrameData { + u32 sizeThis; + u32 readMode; + OrbisCameraFramePosition framePosition[ORBIS_CAMERA_MAX_DEVICE_NUM] + [ORBIS_CAMERA_MAX_FORMAT_LEVEL_NUM]; + void* pFramePointerList[ORBIS_CAMERA_MAX_DEVICE_NUM][ORBIS_CAMERA_MAX_FORMAT_LEVEL_NUM]; + u32 frameSize[ORBIS_CAMERA_MAX_DEVICE_NUM][ORBIS_CAMERA_MAX_FORMAT_LEVEL_NUM]; + u32 status[ORBIS_CAMERA_MAX_DEVICE_NUM]; + OrbisCameraMeta meta; + void* pFramePointerListGarlic[ORBIS_CAMERA_MAX_DEVICE_NUM][ORBIS_CAMERA_MAX_FORMAT_LEVEL_NUM]; +}; + +struct OrbisCameraAttribute { + u32 sizeThis; + OrbisCameraChannel channel; + OrbisCameraFramePosition framePosition; + OrbisCameraExposureGain exposureGain; + OrbisCameraWhiteBalance whiteBalance; + OrbisCameraGamma gamma; + u32 saturation; + u32 contrast; + u32 sharpness; + s32 hue; + u32 reserved1; + u32 reserved2; + u32 reserved3; + u32 reserved4; +}; + +s32 PS4_SYSV_ABI sceCameraAccGetData(); +s32 PS4_SYSV_ABI sceCameraAudioClose(); +s32 PS4_SYSV_ABI sceCameraAudioGetData(); +s32 PS4_SYSV_ABI sceCameraAudioGetData2(); +s32 PS4_SYSV_ABI sceCameraAudioOpen(); +s32 PS4_SYSV_ABI sceCameraAudioReset(); +s32 PS4_SYSV_ABI sceCameraChangeAppModuleState(); +s32 PS4_SYSV_ABI sceCameraClose(s32 handle); +s32 PS4_SYSV_ABI sceCameraCloseByHandle(); +s32 PS4_SYSV_ABI sceCameraDeviceOpen(); +s32 PS4_SYSV_ABI sceCameraGetAttribute(s32 handle, OrbisCameraAttribute* pAttribute); +s32 PS4_SYSV_ABI sceCameraGetAutoExposureGain(s32 handle, OrbisCameraChannel channel, u32* pEnable, + void* pOption); +s32 PS4_SYSV_ABI sceCameraGetAutoWhiteBalance(s32 handle, OrbisCameraChannel channel, u32* pEnable, + void* pOption); +s32 PS4_SYSV_ABI sceCameraGetCalibData(); +s32 PS4_SYSV_ABI sceCameraGetCalibDataFromDevice(); +s32 PS4_SYSV_ABI sceCameraGetCalibrationData(); +s32 PS4_SYSV_ABI sceCameraGetConfig(s32 handle, OrbisCameraConfig* pConfig); +s32 PS4_SYSV_ABI sceCameraGetContrast(s32 handle, OrbisCameraChannel channel, u32* pContrast, + void* pOption); +s32 PS4_SYSV_ABI sceCameraGetDefectivePixelCancellation(s32 handle, OrbisCameraChannel channel, + u32* pEnable, void* pOption); +s32 PS4_SYSV_ABI sceCameraGetDeviceConfig(); +s32 PS4_SYSV_ABI sceCameraGetDeviceConfigWithoutHandle(); +s32 PS4_SYSV_ABI sceCameraGetDeviceID(); +s32 PS4_SYSV_ABI sceCameraGetDeviceIDWithoutOpen(); +s32 PS4_SYSV_ABI sceCameraGetDeviceInfo(s32 reserved, OrbisCameraDeviceInfo* pDeviceInfo); +s32 PS4_SYSV_ABI sceCameraGetExposureGain(s32 handle, OrbisCameraChannel channel, + OrbisCameraExposureGain* pExposureGain, void* pOption); +s32 PS4_SYSV_ABI sceCameraGetFrameData(int handle, OrbisCameraFrameData* pFrameData); +s32 PS4_SYSV_ABI sceCameraGetGamma(s32 handle, OrbisCameraChannel channel, OrbisCameraGamma* pGamma, + void* pOption); +s32 PS4_SYSV_ABI sceCameraGetHue(s32 handle, OrbisCameraChannel channel, s32* pHue, void* pOption); +s32 PS4_SYSV_ABI sceCameraGetLensCorrection(s32 handle, OrbisCameraChannel channel, u32* pEnable, + void* pOption); +s32 PS4_SYSV_ABI sceCameraGetMmapConnectedCount(); +s32 PS4_SYSV_ABI sceCameraGetProductInfo(); +s32 PS4_SYSV_ABI sceCameraGetRegister(); +s32 PS4_SYSV_ABI sceCameraGetRegistryInfo(); +s32 PS4_SYSV_ABI sceCameraGetSaturation(s32 handle, OrbisCameraChannel channel, u32* pSaturation, + void* pOption); +s32 PS4_SYSV_ABI sceCameraGetSharpness(s32 handle, OrbisCameraChannel channel, u32* pSharpness, + void* pOption); +s32 PS4_SYSV_ABI sceCameraGetVrCaptureInfo(); +s32 PS4_SYSV_ABI sceCameraGetWhiteBalance(s32 handle, OrbisCameraChannel channel, + OrbisCameraWhiteBalance* pWhiteBalance, void* pOption); +s32 PS4_SYSV_ABI sceCameraInitializeRegistryCalibData(); +s32 PS4_SYSV_ABI sceCameraIsAttached(s32 index); +s32 PS4_SYSV_ABI sceCameraIsConfigChangeDone(); +s32 PS4_SYSV_ABI sceCameraIsValidFrameData(int handle, OrbisCameraFrameData* pFrameData); +s32 PS4_SYSV_ABI sceCameraOpen(Libraries::UserService::OrbisUserServiceUserId userId, s32 type, + s32 index, OrbisCameraOpenParameter* pParam); +s32 PS4_SYSV_ABI sceCameraOpenByModuleId(); +s32 PS4_SYSV_ABI sceCameraRemoveAppModuleFocus(); +s32 PS4_SYSV_ABI sceCameraSetAppModuleFocus(); +s32 PS4_SYSV_ABI sceCameraSetAttribute(s32 handle, OrbisCameraAttribute* pAttribute); +s32 PS4_SYSV_ABI sceCameraSetAttributeInternal(); +s32 PS4_SYSV_ABI sceCameraSetAutoExposureGain(s32 handle, OrbisCameraChannel channel, u32 enable, + void* pOption); +s32 PS4_SYSV_ABI sceCameraSetAutoWhiteBalance(s32 handle, OrbisCameraChannel channel, u32 enable, + void* pOption); +s32 PS4_SYSV_ABI sceCameraSetCalibData(); +s32 PS4_SYSV_ABI sceCameraSetConfig(s32 handle, OrbisCameraConfig* pConfig); +s32 PS4_SYSV_ABI sceCameraSetConfigInternal(); +s32 PS4_SYSV_ABI sceCameraSetContrast(s32 handle, OrbisCameraChannel channel, u32 contrast, + void* pOption); +s32 PS4_SYSV_ABI sceCameraSetDebugStop(); +s32 PS4_SYSV_ABI sceCameraSetDefectivePixelCancellation(s32 handle, OrbisCameraChannel channel, + u32 enable, void* pOption); +s32 PS4_SYSV_ABI sceCameraSetDefectivePixelCancellationInternal(); +s32 PS4_SYSV_ABI sceCameraSetExposureGain(s32 handle, OrbisCameraChannel channel, + OrbisCameraExposureGain* pExposureGain, void* pOption); +s32 PS4_SYSV_ABI sceCameraSetForceActivate(); +s32 PS4_SYSV_ABI sceCameraSetGamma(s32 handle, OrbisCameraChannel channel, OrbisCameraGamma* pGamma, + void* pOption); +s32 PS4_SYSV_ABI sceCameraSetHue(s32 handle, OrbisCameraChannel channel, s32 hue, void* pOption); +s32 PS4_SYSV_ABI sceCameraSetLensCorrection(s32 handle, OrbisCameraChannel channel, u32 enable, + void* pOption); +s32 PS4_SYSV_ABI sceCameraSetLensCorrectionInternal(); +s32 PS4_SYSV_ABI sceCameraSetProcessFocus(); +s32 PS4_SYSV_ABI sceCameraSetProcessFocusByHandle(); +s32 PS4_SYSV_ABI sceCameraSetRegister(); +s32 PS4_SYSV_ABI sceCameraSetSaturation(s32 handle, OrbisCameraChannel channel, u32 saturation, + void* pOption); +s32 PS4_SYSV_ABI sceCameraSetSharpness(s32 handle, OrbisCameraChannel channel, u32 sharpness, + void* pOption); +s32 PS4_SYSV_ABI sceCameraSetTrackerMode(); +s32 PS4_SYSV_ABI sceCameraSetUacModeInternal(); +s32 PS4_SYSV_ABI sceCameraSetVideoSync(s32 handle, OrbisCameraVideoSyncParameter* pVideoSync); +s32 PS4_SYSV_ABI sceCameraSetVideoSyncInternal(); +s32 PS4_SYSV_ABI sceCameraSetWhiteBalance(s32 handle, OrbisCameraChannel channel, + OrbisCameraWhiteBalance* pWhiteBalance, void* pOption); +s32 PS4_SYSV_ABI sceCameraStart(s32 handle, OrbisCameraStartParameter* pParam); +s32 PS4_SYSV_ABI sceCameraStartByHandle(); +s32 PS4_SYSV_ABI sceCameraStop(s32 handle); +s32 PS4_SYSV_ABI sceCameraStopByHandle(); + +void RegisterlibSceCamera(Core::Loader::SymbolsResolver* sym); +} // namespace Libraries::Camera \ No newline at end of file diff --git a/src/core/libraries/camera/camera_error.h b/src/core/libraries/camera/camera_error.h new file mode 100644 index 000000000..acb04dd02 --- /dev/null +++ b/src/core/libraries/camera/camera_error.h @@ -0,0 +1,29 @@ +// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +constexpr int ORBIS_CAMERA_ERROR_PARAM = 0x802E0000; +constexpr int ORBIS_CAMERA_ERROR_ALREADY_INIT = 0x802E0001; +constexpr int ORBIS_CAMERA_ERROR_NOT_INIT = 0x802E0002; +constexpr int ORBIS_CAMERA_ERROR_ALREADY_OPEN = 0x802E0003; +constexpr int ORBIS_CAMERA_ERROR_NOT_OPEN = 0x802E0004; +constexpr int ORBIS_CAMERA_ERROR_ALREADY_START = 0x802E0005; +constexpr int ORBIS_CAMERA_ERROR_NOT_START = 0x802E0006; +constexpr int ORBIS_CAMERA_ERROR_FORMAT_UNKNOWN = 0x802E0007; +constexpr int ORBIS_CAMERA_ERROR_RESOLUTION_UNKNOWN = 0x802E0008; +constexpr int ORBIS_CAMERA_ERROR_BAD_FRAMERATE = 0x802E0009; +constexpr int ORBIS_CAMERA_ERROR_TIMEOUT = 0x802E000A; +constexpr int ORBIS_CAMERA_ERROR_ATTRIBUTE_UNKNOWN = 0x802E000B; +constexpr int ORBIS_CAMERA_ERROR_BUSY = 0x802E000C; +constexpr int ORBIS_CAMERA_ERROR_UNKNOWN_CONFIG = 0x802E000D; +constexpr int ORBIS_CAMERA_ERROR_ALREADY_READ = 0x802E000F; +constexpr int ORBIS_CAMERA_ERROR_NOT_CONNECTED = 0x802E0010; +constexpr int ORBIS_CAMERA_ERROR_NOT_SUPPORTED = 0x802E0011; +constexpr int ORBIS_CAMERA_ERROR_INVALID_CONFIG = 0x802E0013; +constexpr int ORBIS_CAMERA_ERROR_MAX_HANDLE = 0x802E0014; +constexpr int ORBIS_CAMERA_ERROR_MAX_PROCESS = 0x802E00FB; +constexpr int ORBIS_CAMERA_ERROR_COPYOUT_FAILED = 0x802E00FC; +constexpr int ORBIS_CAMERA_ERROR_COPYIN_FAILED = 0x802E00FD; +constexpr int ORBIS_CAMERA_ERROR_KPROC_CREATE = 0x802E00FE; +constexpr int ORBIS_CAMERA_ERROR_FATAL = 0x802E00FF; \ No newline at end of file diff --git a/src/core/libraries/libs.cpp b/src/core/libraries/libs.cpp index 3826ff793..5ef4b259d 100644 --- a/src/core/libraries/libs.cpp +++ b/src/core/libraries/libs.cpp @@ -8,6 +8,7 @@ #include "core/libraries/audio/audioout.h" #include "core/libraries/audio3d/audio3d.h" #include "core/libraries/avplayer/avplayer.h" +#include "core/libraries/camera/camera.h" #include "core/libraries/disc_map/disc_map.h" #include "core/libraries/game_live_streaming/gamelivestreaming.h" #include "core/libraries/gnmdriver/gnmdriver.h" @@ -122,6 +123,7 @@ void InitHLELibs(Core::Loader::SymbolsResolver* sym) { Libraries::DiscMap::RegisterlibSceDiscMap(sym); Libraries::Ulobjmgr::RegisterlibSceUlobjmgr(sym); Libraries::SigninDialog::RegisterlibSceSigninDialog(sym); + Libraries::Camera::RegisterlibSceCamera(sym); } } // namespace Libraries From 3a090e988cf66131b1af4b7309c0a59c6ea45581 Mon Sep 17 00:00:00 2001 From: squidbus <175574877+squidbus@users.noreply.github.com> Date: Sun, 11 May 2025 14:22:17 -0700 Subject: [PATCH 5/9] kernel: Clean up and fix some mistakes. (#2907) --- src/common/va_ctx.h | 2 +- src/core/libraries/kernel/aio.cpp | 2 +- src/core/libraries/kernel/kernel.h | 18 +++++------------- src/core/libraries/kernel/threads/pthread.cpp | 11 ++++------- src/core/libraries/kernel/threads/pthread.h | 3 ++- .../libraries/kernel/threads/pthread_attr.cpp | 19 ++++++++++--------- src/core/libraries/libs.h | 10 ++-------- src/core/linker.cpp | 5 +++-- 8 files changed, 28 insertions(+), 42 deletions(-) diff --git a/src/common/va_ctx.h b/src/common/va_ctx.h index e0b8c0bab..cffe468ff 100644 --- a/src/common/va_ctx.h +++ b/src/common/va_ctx.h @@ -8,7 +8,7 @@ #define VA_ARGS \ uint64_t rdi, uint64_t rsi, uint64_t rdx, uint64_t rcx, uint64_t r8, uint64_t r9, \ uint64_t overflow_arg_area, __m128 xmm0, __m128 xmm1, __m128 xmm2, __m128 xmm3, \ - __m128 xmm4, __m128 xmm5, __m128 xmm6, __m128 xmm7, ... + __m128 xmm4, __m128 xmm5, __m128 xmm6, __m128 xmm7 #define VA_CTX(ctx) \ alignas(16)::Common::VaCtx ctx{}; \ diff --git a/src/core/libraries/kernel/aio.cpp b/src/core/libraries/kernel/aio.cpp index e017010cb..1d746860b 100644 --- a/src/core/libraries/kernel/aio.cpp +++ b/src/core/libraries/kernel/aio.cpp @@ -19,7 +19,7 @@ namespace Libraries::Kernel { static s32* id_state; static s32 id_index; -s32 sceKernelAioInitializeImpl(void* p, s32 size) { +s32 PS4_SYSV_ABI sceKernelAioInitializeImpl(void* p, s32 size) { return 0; } diff --git a/src/core/libraries/kernel/kernel.h b/src/core/libraries/kernel/kernel.h index 4d68aa357..aaa22aec1 100644 --- a/src/core/libraries/kernel/kernel.h +++ b/src/core/libraries/kernel/kernel.h @@ -3,9 +3,6 @@ #pragma once -#include -#include -#include "common/string_literal.h" #include "common/types.h" #include "core/libraries/kernel/orbis_error.h" @@ -20,26 +17,21 @@ int ErrnoToSceKernelError(int e); void SetPosixErrno(int e); int* PS4_SYSV_ABI __Error(); -template -struct WrapperImpl; +template +struct OrbisWrapperImpl; -template -struct WrapperImpl { - static constexpr StringLiteral Name{name}; +template +struct OrbisWrapperImpl { static R PS4_SYSV_ABI wrap(Args... args) { u32 ret = f(args...); if (ret != 0) { - // LOG_ERROR(Lib_Kernel, "Function {} returned {}", std::string_view{name.value}, ret); ret += ORBIS_KERNEL_ERROR_UNKNOWN; } return ret; } }; -template -constexpr auto OrbisWrapper = WrapperImpl::wrap; - -#define ORBIS(func) WrapperImpl<#func, decltype(&func), func>::wrap +#define ORBIS(func) (Libraries::Kernel::OrbisWrapperImpl::wrap) int* PS4_SYSV_ABI __Error(); diff --git a/src/core/libraries/kernel/threads/pthread.cpp b/src/core/libraries/kernel/threads/pthread.cpp index e791e74bf..a51f1f6e8 100644 --- a/src/core/libraries/kernel/threads/pthread.cpp +++ b/src/core/libraries/kernel/threads/pthread.cpp @@ -581,12 +581,9 @@ int PS4_SYSV_ABI posix_pthread_setaffinity_np(PthreadT thread, size_t cpusetsize return thread->SetAffinity(cpusetp); } -int PS4_SYSV_ABI scePthreadSetaffinity(PthreadT thread, const Cpuset mask) { - int result = posix_pthread_setaffinity_np(thread, 0x10, &mask); - if (result != 0) { - return ErrnoToSceKernelError(result); - } - return 0; +int PS4_SYSV_ABI scePthreadSetaffinity(PthreadT thread, const u64 mask) { + const Cpuset cpuset = {.bits = mask}; + return posix_pthread_setaffinity_np(thread, sizeof(Cpuset), &cpuset); } void RegisterThread(Core::Loader::SymbolsResolver* sym) { @@ -635,7 +632,7 @@ void RegisterThread(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("W0Hpm2X0uPE", "libkernel", 1, "libkernel", 1, 1, ORBIS(posix_pthread_setprio)); LIB_FUNCTION("rNhWz+lvOMU", "libkernel", 1, "libkernel", 1, 1, _sceKernelSetThreadDtors); LIB_FUNCTION("6XG4B33N09g", "libkernel", 1, "libkernel", 1, 1, sched_yield); - LIB_FUNCTION("bt3CTBKmGyI", "libkernel", 1, "libkernel", 1, 1, scePthreadSetaffinity) + LIB_FUNCTION("bt3CTBKmGyI", "libkernel", 1, "libkernel", 1, 1, ORBIS(scePthreadSetaffinity)); } } // namespace Libraries::Kernel diff --git a/src/core/libraries/kernel/threads/pthread.h b/src/core/libraries/kernel/threads/pthread.h index 09eed11b8..ebcc4aed3 100644 --- a/src/core/libraries/kernel/threads/pthread.h +++ b/src/core/libraries/kernel/threads/pthread.h @@ -159,6 +159,7 @@ enum class SchedPolicy : u32 { struct Cpuset { u64 bits; + u64 _reserved; }; struct PthreadAttr { @@ -269,7 +270,7 @@ struct Pthread { bool no_cancel; bool cancel_async; bool cancelling; - Cpuset sigmask; + u64 sigmask; bool unblock_sigcancel; bool in_sigsuspend; bool force_exit; diff --git a/src/core/libraries/kernel/threads/pthread_attr.cpp b/src/core/libraries/kernel/threads/pthread_attr.cpp index a8e60ccf8..02a8cb1c7 100644 --- a/src/core/libraries/kernel/threads/pthread_attr.cpp +++ b/src/core/libraries/kernel/threads/pthread_attr.cpp @@ -243,7 +243,7 @@ int PS4_SYSV_ABI posix_pthread_attr_getaffinity_np(const PthreadAttrT* pattr, si if (attr->cpuset != nullptr) memcpy(cpusetp, attr->cpuset, std::min(cpusetsize, attr->cpusetsize)); else - memset(cpusetp, -1, sizeof(Cpuset)); + memset(cpusetp, -1, cpusetsize); return 0; } @@ -259,30 +259,31 @@ int PS4_SYSV_ABI posix_pthread_attr_setaffinity_np(PthreadAttrT* pattr, size_t c if (cpusetsize == 0 || cpusetp == nullptr) { if (attr->cpuset != nullptr) { free(attr->cpuset); - attr->cpuset = NULL; + attr->cpuset = nullptr; attr->cpusetsize = 0; } return 0; } if (attr->cpuset == nullptr) { - attr->cpuset = (Cpuset*)calloc(1, sizeof(Cpuset)); + attr->cpuset = static_cast(calloc(1, sizeof(Cpuset))); attr->cpusetsize = sizeof(Cpuset); } - memcpy(attr->cpuset, cpusetp, sizeof(Cpuset)); + memcpy(attr->cpuset, cpusetp, cpusetsize); return 0; } -int PS4_SYSV_ABI scePthreadAttrGetaffinity(PthreadAttrT* param_1, Cpuset* mask) { +int PS4_SYSV_ABI scePthreadAttrGetaffinity(PthreadAttrT* param_1, u64* mask) { Cpuset cpuset; - const int ret = posix_pthread_attr_getaffinity_np(param_1, 0x10, &cpuset); + const int ret = posix_pthread_attr_getaffinity_np(param_1, sizeof(Cpuset), &cpuset); if (ret == 0) { - *mask = cpuset; + *mask = cpuset.bits; } return ret; } -int PS4_SYSV_ABI scePthreadAttrSetaffinity(PthreadAttrT* attr, const Cpuset mask) { - return posix_pthread_attr_setaffinity_np(attr, 0x10, &mask); +int PS4_SYSV_ABI scePthreadAttrSetaffinity(PthreadAttrT* attr, const u64 mask) { + const Cpuset cpuset = {.bits = mask}; + return posix_pthread_attr_setaffinity_np(attr, sizeof(Cpuset), &cpuset); } void RegisterThreadAttr(Core::Loader::SymbolsResolver* sym) { diff --git a/src/core/libraries/libs.h b/src/core/libraries/libs.h index aa5ba4a97..7e073db8e 100644 --- a/src/core/libraries/libs.h +++ b/src/core/libraries/libs.h @@ -3,14 +3,9 @@ #pragma once -#include - -#include "common/logging/log.h" #include "core/loader/elf.h" #include "core/loader/symbols_resolver.h" -#define W(foo) foo - #define LIB_FUNCTION(nid, lib, libversion, mod, moduleVersionMajor, moduleVersionMinor, function) \ { \ Core::Loader::SymbolResolver sr{}; \ @@ -25,7 +20,7 @@ sym->AddSymbol(sr, func); \ } -#define LIB_OBJ(nid, lib, libversion, mod, moduleVersionMajor, moduleVersionMinor, function) \ +#define LIB_OBJ(nid, lib, libversion, mod, moduleVersionMajor, moduleVersionMinor, obj) \ { \ Core::Loader::SymbolResolver sr{}; \ sr.name = nid; \ @@ -35,8 +30,7 @@ sr.module_version_major = moduleVersionMajor; \ sr.module_version_minor = moduleVersionMinor; \ sr.type = Core::Loader::SymbolType::Object; \ - auto func = reinterpret_cast(function); \ - sym->AddSymbol(sr, func); \ + sym->AddSymbol(sr, reinterpret_cast(obj)); \ } namespace Libraries { diff --git a/src/core/linker.cpp b/src/core/linker.cpp index 0f86376af..eced87968 100644 --- a/src/core/linker.cpp +++ b/src/core/linker.cpp @@ -127,7 +127,7 @@ void Linker::Execute(const std::vector args) { } } params.entry_addr = module->GetEntryAddress(); - RunMainEntry(¶ms); + ExecuteGuest(RunMainEntry, ¶ms); }); } @@ -366,7 +366,8 @@ void* Linker::TlsGetAddr(u64 module_index, u64 offset) { if (!addr) { // Module was just loaded by above code. Allocate TLS block for it. const u32 init_image_size = module->tls.init_image_size; - u8* dest = reinterpret_cast(heap_api->heap_malloc(module->tls.image_size)); + u8* dest = reinterpret_cast( + Core::ExecuteGuest(heap_api->heap_malloc, module->tls.image_size)); const u8* src = reinterpret_cast(module->tls.image_virtual_addr); std::memcpy(dest, src, init_image_size); std::memset(dest + init_image_size, 0, module->tls.image_size - init_image_size); From c0562a6b1bb1bfb13ee80c061058682fca02edd6 Mon Sep 17 00:00:00 2001 From: squidbus <175574877+squidbus@users.noreply.github.com> Date: Sun, 11 May 2025 14:23:49 -0700 Subject: [PATCH 6/9] qt: Delay physical device enumeration to settings open. (#2908) --- src/qt_gui/main_window.cpp | 19 ++----------------- src/qt_gui/main_window.h | 3 --- src/qt_gui/settings_dialog.cpp | 23 ++++++++++++++++++++--- src/qt_gui/settings_dialog.h | 3 +-- 4 files changed, 23 insertions(+), 25 deletions(-) diff --git a/src/qt_gui/main_window.cpp b/src/qt_gui/main_window.cpp index 36037fd4c..8eeec3536 100644 --- a/src/qt_gui/main_window.cpp +++ b/src/qt_gui/main_window.cpp @@ -24,7 +24,6 @@ #include "main_window.h" #include "settings_dialog.h" -#include "video_core/renderer_vulkan/vk_instance.h" #ifdef ENABLE_DISCORD_RPC #include "common/discord_rpc_handler.h" #endif @@ -53,7 +52,6 @@ bool MainWindow::Init() { CreateConnects(); SetLastUsedTheme(); SetLastIconSizeBullet(); - GetPhysicalDevices(); // show ui setMinimumSize(720, 405); std::string window_title = ""; @@ -368,19 +366,6 @@ void MainWindow::CheckUpdateMain(bool checkSave) { } #endif -void MainWindow::GetPhysicalDevices() { - Vulkan::Instance instance(false, false); - auto physical_devices = instance.GetPhysicalDevices(); - for (const vk::PhysicalDevice physical_device : physical_devices) { - auto prop = physical_device.getProperties(); - QString name = QString::fromUtf8(prop.deviceName, -1); - if (prop.apiVersion < Vulkan::TargetVulkanApiVersion) { - name += tr(" * Unsupported Vulkan Version"); - } - m_physical_devices.push_back(name); - } -} - void MainWindow::CreateConnects() { connect(this, &MainWindow::WindowResized, this, &MainWindow::HandleResize); connect(ui->mw_searchbar, &QLineEdit::textChanged, this, &MainWindow::SearchGameTable); @@ -421,7 +406,7 @@ void MainWindow::CreateConnects() { &MainWindow::StartGame); connect(ui->configureAct, &QAction::triggered, this, [this]() { - auto settingsDialog = new SettingsDialog(m_physical_devices, m_compat_info, this); + auto settingsDialog = new SettingsDialog(m_compat_info, this); connect(settingsDialog, &SettingsDialog::LanguageChanged, this, &MainWindow::OnLanguageChanged); @@ -454,7 +439,7 @@ void MainWindow::CreateConnects() { }); connect(ui->settingsButton, &QPushButton::clicked, this, [this]() { - auto settingsDialog = new SettingsDialog(m_physical_devices, m_compat_info, this); + auto settingsDialog = new SettingsDialog(m_compat_info, this); connect(settingsDialog, &SettingsDialog::LanguageChanged, this, &MainWindow::OnLanguageChanged); diff --git a/src/qt_gui/main_window.h b/src/qt_gui/main_window.h index 5d05bfca4..a5ec08d36 100644 --- a/src/qt_gui/main_window.h +++ b/src/qt_gui/main_window.h @@ -60,7 +60,6 @@ private: void toggleFullscreen(); void CreateRecentGameActions(); void CreateDockWindows(); - void GetPhysicalDevices(); void LoadGameLists(); #ifdef ENABLE_UPDATER @@ -96,8 +95,6 @@ private: QScopedPointer m_elf_viewer; // Status Bar. QScopedPointer statusBar; - // Available GPU devices - std::vector m_physical_devices; PSF psf; diff --git a/src/qt_gui/settings_dialog.cpp b/src/qt_gui/settings_dialog.cpp index 5ee802b0c..914cc5470 100644 --- a/src/qt_gui/settings_dialog.cpp +++ b/src/qt_gui/settings_dialog.cpp @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include #include #include #include @@ -25,6 +26,7 @@ #include "common/logging/filter.h" #include "settings_dialog.h" #include "ui_settings_dialog.h" +#include "video_core/renderer_vulkan/vk_instance.h" QStringList languageNames = {"Arabic", "Czech", "Danish", @@ -67,8 +69,9 @@ QMap chooseHomeTabMap; int backgroundImageOpacitySlider_backup; int bgm_volume_backup; -SettingsDialog::SettingsDialog(std::span physical_devices, - std::shared_ptr m_compat_info, +static std::vector m_physical_devices; + +SettingsDialog::SettingsDialog(std::shared_ptr m_compat_info, QWidget* parent) : QDialog(parent), ui(new Ui::SettingsDialog) { ui->setupUi(this); @@ -89,9 +92,23 @@ SettingsDialog::SettingsDialog(std::span physical_devices, {tr("Input"), "Input"}, {tr("Paths"), "Paths"}, {tr("Debug"), "Debug"}}; + if (m_physical_devices.empty()) { + // Populate cache of physical devices. + Vulkan::Instance instance(false, false); + auto physical_devices = instance.GetPhysicalDevices(); + for (const vk::PhysicalDevice physical_device : physical_devices) { + auto prop = physical_device.getProperties(); + QString name = QString::fromUtf8(prop.deviceName, -1); + if (prop.apiVersion < Vulkan::TargetVulkanApiVersion) { + name += tr(" * Unsupported Vulkan Version"); + } + m_physical_devices.push_back(name); + } + } + // Add list of available GPUs ui->graphicsAdapterBox->addItem(tr("Auto Select")); // -1, auto selection - for (const auto& device : physical_devices) { + for (const auto& device : m_physical_devices) { ui->graphicsAdapterBox->addItem(device); } diff --git a/src/qt_gui/settings_dialog.h b/src/qt_gui/settings_dialog.h index 09aa2b855..cdf9be80e 100644 --- a/src/qt_gui/settings_dialog.h +++ b/src/qt_gui/settings_dialog.h @@ -20,8 +20,7 @@ class SettingsDialog; class SettingsDialog : public QDialog { Q_OBJECT public: - explicit SettingsDialog(std::span physical_devices, - std::shared_ptr m_compat_info, + explicit SettingsDialog(std::shared_ptr m_compat_info, QWidget* parent = nullptr); ~SettingsDialog(); From 6206986914314ebb9318ded5c2c4d9d6bd0fe9c3 Mon Sep 17 00:00:00 2001 From: Stephen Miller <56742918+StevenMiller123@users.noreply.github.com> Date: Sun, 11 May 2025 21:51:03 -0500 Subject: [PATCH 7/9] libkernel: Implement sceKernelMemoryPoolBatch (#2909) * Implement sceKernelMemoryPoolBatch I've tested Commit and Decommit on real hardware, haven't tested Protect or TypeProtect yet. Implementation is primarily based on our sceKernelBatchMap implementation. * Clang --- src/core/libraries/kernel/memory.cpp | 54 ++++++++++++++++++++++++++++ src/core/libraries/kernel/memory.h | 44 +++++++++++++++++++++++ 2 files changed, 98 insertions(+) diff --git a/src/core/libraries/kernel/memory.cpp b/src/core/libraries/kernel/memory.cpp index 9fcaa2439..dd0e07302 100644 --- a/src/core/libraries/kernel/memory.cpp +++ b/src/core/libraries/kernel/memory.cpp @@ -481,6 +481,59 @@ s32 PS4_SYSV_ABI sceKernelMemoryPoolDecommit(void* addr, size_t len, int flags) return memory->PoolDecommit(pool_addr, len); } +s32 PS4_SYSV_ABI sceKernelMemoryPoolBatch(const OrbisKernelMemoryPoolBatchEntry* entries, s32 count, + s32* num_processed, s32 flags) { + if (entries == nullptr) { + return ORBIS_KERNEL_ERROR_EINVAL; + } + s32 result = ORBIS_OK; + s32 processed = 0; + + for (s32 i = 0; i < count; i++, processed++) { + OrbisKernelMemoryPoolBatchEntry entry = entries[i]; + switch (entry.opcode) { + case OrbisKernelMemoryPoolOpcode::Commit: { + result = sceKernelMemoryPoolCommit(entry.commit_params.addr, entry.commit_params.len, + entry.commit_params.type, entry.commit_params.prot, + entry.flags); + break; + } + case OrbisKernelMemoryPoolOpcode::Decommit: { + result = sceKernelMemoryPoolDecommit(entry.decommit_params.addr, + entry.decommit_params.len, entry.flags); + break; + } + case OrbisKernelMemoryPoolOpcode::Protect: { + result = sceKernelMProtect(entry.protect_params.addr, entry.protect_params.len, + entry.protect_params.prot); + break; + } + case OrbisKernelMemoryPoolOpcode::TypeProtect: { + result = sceKernelMTypeProtect( + entry.type_protect_params.addr, entry.type_protect_params.len, + entry.type_protect_params.type, entry.type_protect_params.prot); + break; + } + case OrbisKernelMemoryPoolOpcode::Move: { + UNREACHABLE_MSG("Unimplemented sceKernelMemoryPoolBatch opcode Move"); + } + default: { + result = ORBIS_KERNEL_ERROR_EINVAL; + break; + } + } + + if (result != ORBIS_OK) { + break; + } + } + + if (num_processed != nullptr) { + *num_processed = processed; + } + return result; +} + int PS4_SYSV_ABI sceKernelMmap(void* addr, u64 len, int prot, int flags, int fd, size_t offset, void** res) { LOG_INFO(Kernel_Vmm, "called addr = {}, len = {}, prot = {}, flags = {}, fd = {}, offset = {}", @@ -612,6 +665,7 @@ void RegisterMemory(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("pU-QydtGcGY", "libkernel", 1, "libkernel", 1, 1, sceKernelMemoryPoolReserve); LIB_FUNCTION("Vzl66WmfLvk", "libkernel", 1, "libkernel", 1, 1, sceKernelMemoryPoolCommit); LIB_FUNCTION("LXo1tpFqJGs", "libkernel", 1, "libkernel", 1, 1, sceKernelMemoryPoolDecommit); + LIB_FUNCTION("YN878uKRBbE", "libkernel", 1, "libkernel", 1, 1, sceKernelMemoryPoolBatch); LIB_FUNCTION("BPE9s9vQQXo", "libkernel", 1, "libkernel", 1, 1, posix_mmap); LIB_FUNCTION("BPE9s9vQQXo", "libScePosix", 1, "libkernel", 1, 1, posix_mmap); diff --git a/src/core/libraries/kernel/memory.h b/src/core/libraries/kernel/memory.h index 2ca7f2931..3e2bf8de5 100644 --- a/src/core/libraries/kernel/memory.h +++ b/src/core/libraries/kernel/memory.h @@ -81,6 +81,48 @@ struct OrbisKernelBatchMapEntry { int operation; }; +enum class OrbisKernelMemoryPoolOpcode : u32 { + Commit = 1, + Decommit = 2, + Protect = 3, + TypeProtect = 4, + Move = 5, +}; + +struct OrbisKernelMemoryPoolBatchEntry { + OrbisKernelMemoryPoolOpcode opcode; + u32 flags; + union { + struct { + void* addr; + u64 len; + u8 prot; + u8 type; + } commit_params; + struct { + void* addr; + u64 len; + } decommit_params; + struct { + void* addr; + u64 len; + u8 prot; + } protect_params; + struct { + void* addr; + u64 len; + u8 prot; + u8 type; + } type_protect_params; + struct { + void* dest_addr; + void* src_addr; + u64 len; + } move_params; + uintptr_t padding[3]; + }; +}; + u64 PS4_SYSV_ABI sceKernelGetDirectMemorySize(); int PS4_SYSV_ABI sceKernelAllocateDirectMemory(s64 searchStart, s64 searchEnd, u64 len, u64 alignment, int memoryType, s64* physAddrOut); @@ -130,6 +172,8 @@ s32 PS4_SYSV_ABI sceKernelMemoryPoolReserve(void* addrIn, size_t len, size_t ali void** addrOut); s32 PS4_SYSV_ABI sceKernelMemoryPoolCommit(void* addr, size_t len, int type, int prot, int flags); s32 PS4_SYSV_ABI sceKernelMemoryPoolDecommit(void* addr, size_t len, int flags); +s32 PS4_SYSV_ABI sceKernelMemoryPoolBatch(const OrbisKernelMemoryPoolBatchEntry* entries, s32 count, + s32* num_processed, s32 flags); int PS4_SYSV_ABI sceKernelMunmap(void* addr, size_t len); From 02d3ed4973960e8a4a2ac454dc3e46d5d804a743 Mon Sep 17 00:00:00 2001 From: squidbus <175574877+squidbus@users.noreply.github.com> Date: Sun, 11 May 2025 20:27:43 -0700 Subject: [PATCH 8/9] liverpool: Log more information on SetQueueReg. (#2912) --- src/video_core/amdgpu/liverpool.cpp | 5 +++++ src/video_core/amdgpu/pm4_cmds.h | 15 +++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/src/video_core/amdgpu/liverpool.cpp b/src/video_core/amdgpu/liverpool.cpp index 4c8e3367a..598288085 100644 --- a/src/video_core/amdgpu/liverpool.cpp +++ b/src/video_core/amdgpu/liverpool.cpp @@ -864,6 +864,11 @@ Liverpool::Task Liverpool::ProcessCompute(const u32* acb, u32 acb_dwords, u32 vq } break; } + case PM4ItOpcode::SetQueueReg: { + const auto* set_data = reinterpret_cast(header); + UNREACHABLE_MSG("Encountered compute SetQueueReg: vqid = {}, reg_offset = {:#x}", + set_data->vqid.Value(), set_data->reg_offset.Value()); + } case PM4ItOpcode::DispatchDirect: { const auto* dispatch_direct = reinterpret_cast(header); auto& cs_program = GetCsRegs(); diff --git a/src/video_core/amdgpu/pm4_cmds.h b/src/video_core/amdgpu/pm4_cmds.h index 6b55f5b65..cd175f6c9 100644 --- a/src/video_core/amdgpu/pm4_cmds.h +++ b/src/video_core/amdgpu/pm4_cmds.h @@ -211,6 +211,21 @@ struct PM4CmdSetData { } }; +struct PM4CmdSetQueueReg { + PM4Type3Header header; + union { + u32 raw; + BitField<0, 8, u32> reg_offset; ///< Offset in DWords from the register base address + BitField<15, 1, u32> defer_exec; ///< Defer execution + BitField<16, 10, u32> vqid; ///< Queue ID + }; + u32 data[0]; + + [[nodiscard]] u32 Size() const { + return header.count << 2u; + } +}; + struct PM4CmdNop { PM4Type3Header header; u32 data_block[0]; From 678f18ddb95773186877504b1b668e2a3c8d8785 Mon Sep 17 00:00:00 2001 From: squidbus <175574877+squidbus@users.noreply.github.com> Date: Sun, 11 May 2025 20:27:54 -0700 Subject: [PATCH 9/9] core: Introduce host call wrapper. (#2913) --- src/core/libraries/kernel/threads.h | 2 +- src/core/libraries/libs.h | 3 ++- src/core/tls.h | 12 ++++++++++++ 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/core/libraries/kernel/threads.h b/src/core/libraries/kernel/threads.h index 409136968..7b75d54bf 100644 --- a/src/core/libraries/kernel/threads.h +++ b/src/core/libraries/kernel/threads.h @@ -35,7 +35,7 @@ public: this->func = std::move(func); PthreadAttrT attr{}; posix_pthread_attr_init(&attr); - posix_pthread_create(&thread, &attr, RunWrapper, this); + posix_pthread_create(&thread, &attr, HOST_CALL(RunWrapper), this); posix_pthread_attr_destroy(&attr); } diff --git a/src/core/libraries/libs.h b/src/core/libraries/libs.h index 7e073db8e..d9c8216a5 100644 --- a/src/core/libraries/libs.h +++ b/src/core/libraries/libs.h @@ -5,6 +5,7 @@ #include "core/loader/elf.h" #include "core/loader/symbols_resolver.h" +#include "core/tls.h" #define LIB_FUNCTION(nid, lib, libversion, mod, moduleVersionMajor, moduleVersionMinor, function) \ { \ @@ -16,7 +17,7 @@ sr.module_version_major = moduleVersionMajor; \ sr.module_version_minor = moduleVersionMinor; \ sr.type = Core::Loader::SymbolType::Function; \ - auto func = reinterpret_cast(function); \ + auto func = reinterpret_cast(HOST_CALL(function)); \ sym->AddSymbol(sr, func); \ } diff --git a/src/core/tls.h b/src/core/tls.h index 46ca8153b..d1d490465 100644 --- a/src/core/tls.h +++ b/src/core/tls.h @@ -58,4 +58,16 @@ ReturnType ExecuteGuest(PS4_SYSV_ABI ReturnType (*func)(FuncArgs...), CallArgs&& return func(std::forward(args)...); } +template +struct HostCallWrapperImpl; + +template +struct HostCallWrapperImpl { + static ReturnType PS4_SYSV_ABI wrap(Args... args) { + return func(args...); + } +}; + +#define HOST_CALL(func) (Core::HostCallWrapperImpl::wrap) + } // namespace Core