diff --git a/CMakeLists.txt b/CMakeLists.txt index 79cdc553..44ce20d0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,7 +41,7 @@ add_executable(shadps4 src/Core/PS4/HLE/Kernel/Objects/physical_memory.cpp src/Util/string_util.cpp src/Util/string_util.cpp - "src/Util/Singleton.h" "src/Util/Disassembler.cpp" "src/Util/Disassembler.h" "src/Core/PS4/Util/aerolib.h" "src/Core/PS4/Loader/SymbolsResolver.h" "src/Core/PS4/Loader/SymbolsResolver.cpp" "src/Core/PS4/HLE/Libs.cpp" "src/Core/PS4/HLE/Libs.h" "src/Core/PS4/HLE/LibC.cpp" "src/Core/PS4/HLE/LibC.h" "src/Lib/Timer.cpp" "src/Lib/Timer.h" "src/Core/PS4/HLE/LibKernel.cpp" "src/Core/PS4/HLE/LibKernel.h" "src/Core/PS4/HLE/LibSceVideoOut.cpp" "src/Core/PS4/HLE/LibSceVideoOut.h" "src/Core/PS4/HLE/LibSceGnmDriver.cpp" "src/Core/PS4/HLE/LibSceGnmDriver.h" "src/Core/PS4/HLE/Kernel/ThreadManagement.cpp" "src/Core/PS4/HLE/Kernel/ThreadManagement.h" "src/Core/PS4/HLE/ErrorCodes.h" "src/debug.h" "src/Core/PS4/HLE/Kernel/memory_management.cpp" "src/Core/PS4/HLE/Kernel/memory_management.h") + "src/Util/Singleton.h" "src/Util/Disassembler.cpp" "src/Util/Disassembler.h" "src/Core/PS4/Util/aerolib.h" "src/Core/PS4/Loader/SymbolsResolver.h" "src/Core/PS4/Loader/SymbolsResolver.cpp" "src/Core/PS4/HLE/Libs.cpp" "src/Core/PS4/HLE/Libs.h" "src/Core/PS4/HLE/LibC.cpp" "src/Core/PS4/HLE/LibC.h" "src/Lib/Timer.cpp" "src/Lib/Timer.h" "src/Core/PS4/HLE/LibKernel.cpp" "src/Core/PS4/HLE/LibKernel.h" "src/Core/PS4/HLE/LibSceVideoOut.cpp" "src/Core/PS4/HLE/LibSceVideoOut.h" "src/Core/PS4/HLE/LibSceGnmDriver.cpp" "src/Core/PS4/HLE/LibSceGnmDriver.h" "src/Core/PS4/HLE/Kernel/ThreadManagement.cpp" "src/Core/PS4/HLE/Kernel/ThreadManagement.h" "src/Core/PS4/HLE/ErrorCodes.h" "src/debug.h" "src/Core/PS4/HLE/Kernel/memory_management.cpp" "src/Core/PS4/HLE/Kernel/memory_management.h" "src/Core/PS4/GPU/gpu_memory.cpp" "src/Core/PS4/GPU/gpu_memory.h") find_package(OpenGL REQUIRED) target_link_libraries(shadps4 PUBLIC fmt mincore spdlog IMGUI SDL3-shared ${OPENGL_LIBRARY}) diff --git a/src/Core/PS4/GPU/gpu_memory.cpp b/src/Core/PS4/GPU/gpu_memory.cpp new file mode 100644 index 00000000..eb488d2e --- /dev/null +++ b/src/Core/PS4/GPU/gpu_memory.cpp @@ -0,0 +1,5 @@ +#include "gpu_memory.h" + +namespace GPU { +void GpuMemorySetAllocArea(u64 virtual_addr, u64 size) {} +} // namespace GPU \ No newline at end of file diff --git a/src/Core/PS4/GPU/gpu_memory.h b/src/Core/PS4/GPU/gpu_memory.h new file mode 100644 index 00000000..84d77c07 --- /dev/null +++ b/src/Core/PS4/GPU/gpu_memory.h @@ -0,0 +1,9 @@ +#pragma once + +#include + +namespace GPU { +enum class GPUMemoryMode : u32 { NoAccess = 0, Read = 1, Write = 2, ReadWrite = 3 }; + +void GpuMemorySetAllocArea(u64 virtual_addr, u64 size); +} \ No newline at end of file diff --git a/src/Core/PS4/HLE/Kernel/Objects/physical_memory.cpp b/src/Core/PS4/HLE/Kernel/Objects/physical_memory.cpp index 5e9e5d5d..647c33d0 100644 --- a/src/Core/PS4/HLE/Kernel/Objects/physical_memory.cpp +++ b/src/Core/PS4/HLE/Kernel/Objects/physical_memory.cpp @@ -24,6 +24,11 @@ bool PhysicalMemory::Alloc(u64 searchStart, u64 searchEnd, u64 len, u64 alignmen block.size = len; block.start_addr = find_free_pos; block.memoryType = memoryType; + block.gpu_mode = GPU::GPUMemoryMode::NoAccess; + block.map_size = 0; + block.map_virtual_addr = 0; + block.prot = 0; + block.cpu_mode = VirtualMemory::MemoryMode::NoAccess; m_allocatedBlocks.push_back(block); @@ -33,4 +38,23 @@ bool PhysicalMemory::Alloc(u64 searchStart, u64 searchEnd, u64 len, u64 alignmen return false; } +bool PhysicalMemory::Map(u64 virtual_addr, u64 phys_addr, u64 len, int prot, VirtualMemory::MemoryMode cpu_mode, GPU::GPUMemoryMode gpu_mode) { + for (auto& b : m_allocatedBlocks) { + if (phys_addr >= b.start_addr && phys_addr < b.start_addr + b.size) { + if (b.map_virtual_addr != 0 || b.map_size != 0) { + return false; + } + + b.map_virtual_addr = virtual_addr; + b.map_size = len; + b.prot = prot; + b.cpu_mode = cpu_mode; + b.gpu_mode = gpu_mode; + + return true; + } + } + + return false; +} } // namespace HLE::Kernel::Objects diff --git a/src/Core/PS4/HLE/Kernel/Objects/physical_memory.h b/src/Core/PS4/HLE/Kernel/Objects/physical_memory.h index 71d2e076..5ef4e89a 100644 --- a/src/Core/PS4/HLE/Kernel/Objects/physical_memory.h +++ b/src/Core/PS4/HLE/Kernel/Objects/physical_memory.h @@ -1,6 +1,7 @@ #pragma once #include - +#include +#include #include namespace HLE::Kernel::Objects { @@ -11,12 +12,18 @@ class PhysicalMemory { u64 start_addr; u64 size; int memoryType; + u64 map_virtual_addr; + u64 map_size; + int prot; + VirtualMemory::MemoryMode cpu_mode; + GPU::GPUMemoryMode gpu_mode; }; PhysicalMemory() {} virtual ~PhysicalMemory() {} public: bool Alloc(u64 searchStart, u64 searchEnd, u64 len, u64 alignment, u64* physAddrOut, int memoryType); + bool Map(u64 virtual_addr, u64 phys_addr, u64 len, int prot, VirtualMemory::MemoryMode cpu_mode, GPU::GPUMemoryMode gpu_mode); private: std::vector m_allocatedBlocks; diff --git a/src/Core/PS4/HLE/Kernel/memory_management.cpp b/src/Core/PS4/HLE/Kernel/memory_management.cpp index 37530ab9..26af2888 100644 --- a/src/Core/PS4/HLE/Kernel/memory_management.cpp +++ b/src/Core/PS4/HLE/Kernel/memory_management.cpp @@ -1,5 +1,7 @@ #include "memory_management.h" +#include +#include #include #include @@ -65,14 +67,63 @@ int PS4_SYSV_ABI sceKernelAllocateDirectMemory(s64 searchStart, s64 searchEnd, u int PS4_SYSV_ABI sceKernelMapDirectMemory(void** addr, u64 len, int prot, int flags, s64 directMemoryStart, u64 alignment) { PRINT_FUNCTION_NAME(); + if (len == 0 || !is16KBAligned(len)) + { + LOG_TRACE_IF(log_file_memory, "sceKernelMapDirectMemory returned SCE_KERNEL_ERROR_EINVAL len invalid\n"); + return SCE_KERNEL_ERROR_EINVAL; + } + if (!is16KBAligned(directMemoryStart)) + { + LOG_TRACE_IF(log_file_memory, "sceKernelMapDirectMemory returned SCE_KERNEL_ERROR_EINVAL directMemoryStart invalid\n"); + return SCE_KERNEL_ERROR_EINVAL; + } + if (alignment != 0 || (!isPowerOfTwo(alignment) && !is16KBAligned(alignment))) + { + LOG_TRACE_IF(log_file_memory, "sceKernelMapDirectMemory returned SCE_KERNEL_ERROR_EINVAL alignment invalid\n"); + return SCE_KERNEL_ERROR_EINVAL; + } auto* physical_memory = Singleton::Instance(); + LOG_INFO_IF(log_file_memory, "len = {}\n", log_hex_full(len)); LOG_INFO_IF(log_file_memory, "prot = {}\n", log_hex_full(prot)); LOG_INFO_IF(log_file_memory, "flags = {}\n", log_hex_full(flags)); LOG_INFO_IF(log_file_memory, "directMemoryStart = {}\n", log_hex_full(directMemoryStart)); LOG_INFO_IF(log_file_memory, "alignment = {}\n", log_hex_full(alignment)); - BREAKPOINT(); + VirtualMemory::MemoryMode cpu_mode = VirtualMemory::MemoryMode::NoAccess; + GPU::GPUMemoryMode gpu_mode = GPU::GPUMemoryMode::NoAccess; + + switch (prot) { + case 0x33://SCE_KERNEL_PROT_CPU_READ|SCE_KERNEL_PROT_CPU_WRITE|SCE_KERNEL_PROT_GPU_READ|SCE_KERNEL_PROT_GPU_ALL + cpu_mode = VirtualMemory::MemoryMode::ReadWrite; + gpu_mode = GPU::GPUMemoryMode::ReadWrite; + break; + default: BREAKPOINT(); + } + + auto in_addr = reinterpret_cast(*addr); + u64 out_addr = 0; + + if (flags == 0) { + out_addr = VirtualMemory::memory_alloc_aligned(in_addr, len, cpu_mode, alignment); + } + LOG_INFO_IF(log_file_memory, "in_addr = {}\n", log_hex_full(in_addr)); + LOG_INFO_IF(log_file_memory, "out_addr = {}\n", log_hex_full(out_addr)); + + *addr = reinterpret_cast(out_addr); // return out_addr to first functions parameter + + if (out_addr == 0) { + return SCE_KERNEL_ERROR_ENOMEM; + } + + if (!physical_memory->Map(out_addr, directMemoryStart, len, prot, cpu_mode, gpu_mode)) { + BREAKPOINT(); + } + + if (gpu_mode != GPU::GPUMemoryMode::NoAccess) { + GPU::GpuMemorySetAllocArea(out_addr, len); + } + return SCE_OK; } diff --git a/src/Core/PS4/HLE/Kernel/memory_management.h b/src/Core/PS4/HLE/Kernel/memory_management.h index 0fe55024..4a872cb5 100644 --- a/src/Core/PS4/HLE/Kernel/memory_management.h +++ b/src/Core/PS4/HLE/Kernel/memory_management.h @@ -6,6 +6,8 @@ constexpr u64 SCE_KERNEL_MAIN_DMEM_SIZE = 5376_MB; // ~ 6GB +namespace HLE::Libs::LibKernel::MemoryManagement { + // memory types enum MemoryTypes : u32 { @@ -15,7 +17,6 @@ enum MemoryTypes : u32 { }; enum MemoryFlags : u32 { - NOT_SPECIFIED = 0, // not in SCE but it is a possible value (aligned memory) SCE_KERNEL_MAP_FIXED = 0x0010, // Fixed SCE_KERNEL_MAP_NO_OVERWRITE = 0x0080, SCE_KERNEL_MAP_NO_COALESCE = 0x400000 @@ -28,7 +29,6 @@ enum MemoryProtection : u32 { SCE_KERNEL_PROT_GPU_WRITE = 0x20, // Permit writes from the GPU SCE_KERNEL_PROT_GPU_RW = 0x30 // Permit reads/writes from the GPU }; -namespace HLE::Libs::LibKernel::MemoryManagement { u64 PS4_SYSV_ABI sceKernelGetDirectMemorySize(); int PS4_SYSV_ABI sceKernelAllocateDirectMemory(s64 searchStart, s64 searchEnd, u64 len, u64 alignment, int memoryType, s64* physAddrOut);