diff --git a/src/core/libraries/kernel/memory_management.h b/src/core/libraries/kernel/memory_management.h index cab877f4..25434ecb 100644 --- a/src/core/libraries/kernel/memory_management.h +++ b/src/core/libraries/kernel/memory_management.h @@ -6,7 +6,7 @@ #include "common/bit_field.h" #include "common/types.h" -constexpr u64 SCE_KERNEL_MAIN_DMEM_SIZE = 5376_MB; // ~ 6GB +constexpr u64 SCE_KERNEL_MAIN_DMEM_SIZE = 6_GB; // ~ 6GB namespace Libraries::Kernel { diff --git a/src/core/libraries/kernel/thread_management.cpp b/src/core/libraries/kernel/thread_management.cpp index 859bd016..cbdb5e26 100644 --- a/src/core/libraries/kernel/thread_management.cpp +++ b/src/core/libraries/kernel/thread_management.cpp @@ -1364,6 +1364,11 @@ int PS4_SYSV_ABI scePthreadOnce(int* once_control, void (*init_routine)(void)) { UNREACHABLE(); } +[[noreturn]] void PS4_SYSV_ABI posix_pthread_exit(void* value_ptr) { + pthread_exit(value_ptr); + UNREACHABLE(); +} + int PS4_SYSV_ABI scePthreadGetthreadid() { return (int)(size_t)g_pthread_self; } @@ -1415,6 +1420,7 @@ void pthreadSymbolsRegister(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("4qGrR6eoP9Y", "libkernel", 1, "libkernel", 1, 1, scePthreadDetach); LIB_FUNCTION("3PtV6p3QNX4", "libkernel", 1, "libkernel", 1, 1, scePthreadEqual); LIB_FUNCTION("3kg7rT0NQIs", "libkernel", 1, "libkernel", 1, 1, scePthreadExit); + LIB_FUNCTION("FJrT5LuUBAU", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_exit); LIB_FUNCTION("7Xl257M4VNI", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_equal); LIB_FUNCTION("h9CcP3J0oVM", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_join); LIB_FUNCTION("EI-5-jlq2dE", "libkernel", 1, "libkernel", 1, 1, scePthreadGetthreadid); diff --git a/src/core/libraries/playgo/playgo.cpp b/src/core/libraries/playgo/playgo.cpp index 1a335a2a..e029413e 100644 --- a/src/core/libraries/playgo/playgo.cpp +++ b/src/core/libraries/playgo/playgo.cpp @@ -8,8 +8,6 @@ #include "playgo.h" namespace Libraries::PlayGo { -// this lib is used to play as the game is being installed. -// can be skipped by just returning and assigning the correct values. s32 PS4_SYSV_ABI sceDbgPlayGoRequestNextChunk() { LOG_ERROR(Lib_PlayGo, "(STUBBED)called"); @@ -141,4 +139,4 @@ void RegisterlibScePlayGo(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("MPe0EeBGM-E", "libScePlayGo", 1, "libScePlayGo", 1, 0, scePlayGoTerminate); }; -} // namespace Libraries::PlayGo \ No newline at end of file +} // namespace Libraries::PlayGo diff --git a/src/core/linker.cpp b/src/core/linker.cpp index 2e47d17d..e4cbe573 100644 --- a/src/core/linker.cpp +++ b/src/core/linker.cpp @@ -320,11 +320,15 @@ void Linker::InitTlsForThread(bool is_primary) { static constexpr size_t TlsAllocAlign = 0x20; const size_t total_tls_size = Common::AlignUp(static_tls_size, TlsAllocAlign) + TcbSize; + // If sceKernelMapNamedFlexibleMemory is being called from libkernel and addr = 0 + // it automatically places mappings in system reserved area instead of managed. + static constexpr VAddr KernelAllocBase = 0x880000000ULL; + // The kernel module has a few different paths for TLS allocation. // For SDK < 1.7 it allocates both main and secondary thread blocks using libc mspace/malloc. // In games compiled with newer SDK, the main thread gets mapped from flexible memory, // with addr = 0, so system managed area. Here we will only implement the latter. - void* addr_out{}; + void* addr_out{reinterpret_cast(KernelAllocBase)}; if (is_primary) { const size_t tls_aligned = Common::AlignUp(total_tls_size, 16_KB); const int ret = Libraries::Kernel::sceKernelMapNamedFlexibleMemory( diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 6934b685..c09308a7 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -234,6 +234,7 @@ void MemoryManager::UnmapMemory(VAddr virtual_addr, size_t size) { vma.type = VMAType::Free; vma.prot = MemoryProt::NoAccess; vma.phys_base = 0; + vma.disallow_merge = false; MergeAdjacent(vma_map, new_it); // Unmap the memory region. @@ -344,11 +345,23 @@ VAddr MemoryManager::SearchFree(VAddr virtual_addr, size_t size, u32 alignment) return virtual_addr; } // Search for the first free VMA that fits our mapping. - while (!it->second.IsFree() || it->second.size < size) { + const auto is_suitable = [&] { + if (!it->second.IsFree()) { + return false; + } + const auto& vma = it->second; + virtual_addr = Common::AlignUp(vma.base, alignment); + // Sometimes the alignment itself might be larger than the VMA. + if (virtual_addr > vma.base + vma.size) { + return false; + } + const size_t remaining_size = vma.base + vma.size - virtual_addr; + return remaining_size >= size; + }; + while (!is_suitable()) { it++; } - const auto& vma = it->second; - return alignment > 0 ? Common::AlignUp(vma.base, alignment) : vma.base; + return virtual_addr; } MemoryManager::VMAHandle MemoryManager::CarveVMA(VAddr virtual_addr, size_t size) { diff --git a/src/emulator.cpp b/src/emulator.cpp index 5e584eee..47ac57ac 100644 --- a/src/emulator.cpp +++ b/src/emulator.cpp @@ -150,10 +150,12 @@ void Emulator::Run(const std::filesystem::path& file) { } void Emulator::LoadSystemModules(const std::filesystem::path& file) { - constexpr std::array ModulesToLoad{ + constexpr std::array ModulesToLoad{ {{"libSceNgs2.sprx", nullptr}, {"libSceFiber.sprx", nullptr}, {"libSceUlt.sprx", nullptr}, + {"libSceJson.sprx", nullptr}, + {"libSceJson2.sprx", nullptr}, {"libSceLibcInternal.sprx", &Libraries::LibcInternal::RegisterlibSceLibcInternal}, {"libSceDiscMap.sprx", &Libraries::DiscMap::RegisterlibSceDiscMap}, {"libSceRtc.sprx", &Libraries::Rtc::RegisterlibSceRtc}, diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp index 16c10f53..9ce87add 100644 --- a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp +++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp @@ -388,6 +388,10 @@ spv::ImageFormat GetFormat(const AmdGpu::Image& image) { image.GetNumberFmt() == AmdGpu::NumberFormat::Unorm) { return spv::ImageFormat::Rgba8; } + if (image.GetDataFmt() == AmdGpu::DataFormat::Format8_8_8_8 && + image.GetNumberFmt() == AmdGpu::NumberFormat::Uint) { + return spv::ImageFormat::Rgba8ui; + } UNREACHABLE(); }