mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-04-20 19:44:46 +00:00
Improve linux support
This commit is contained in:
parent
b031ba0719
commit
5834b82efb
25 changed files with 193 additions and 126 deletions
|
@ -224,8 +224,6 @@ set(COMMON src/common/logging/backend.cpp
|
|||
src/common/debug.h
|
||||
src/common/disassembler.cpp
|
||||
src/common/disassembler.h
|
||||
src/common/discord.cpp
|
||||
src/common/discord.h
|
||||
src/common/endian.h
|
||||
src/common/enum.h
|
||||
src/common/io_file.cpp
|
||||
|
@ -509,7 +507,7 @@ endif()
|
|||
create_target_directory_groups(shadps4)
|
||||
|
||||
target_link_libraries(shadps4 PRIVATE magic_enum::magic_enum fmt::fmt toml11::toml11 tsl::robin_map xbyak Tracy::TracyClient)
|
||||
target_link_libraries(shadps4 PRIVATE discord-rpc boost vma sirit vulkan-headers xxhash Zydis SPIRV glslang SDL3-shared)
|
||||
target_link_libraries(shadps4 PRIVATE boost vma sirit vulkan-headers xxhash Zydis SPIRV glslang SDL3-shared)
|
||||
|
||||
if (NOT ENABLE_QT_GUI)
|
||||
target_link_libraries(shadps4 PRIVATE SDL3-shared)
|
||||
|
|
|
@ -216,17 +216,20 @@ void IOFile::Close() {
|
|||
#endif
|
||||
}
|
||||
|
||||
void* IOFile::GetFileMapping() {
|
||||
#ifdef _WIN64
|
||||
uintptr_t IOFile::GetFileMapping() {
|
||||
if (file_mapping) {
|
||||
return file_mapping;
|
||||
}
|
||||
#ifdef _WIN64
|
||||
const int fd = fileno(file);
|
||||
HANDLE hfile = reinterpret_cast<HANDLE>(_get_osfhandle(fd));
|
||||
file_mapping =
|
||||
CreateFileMapping2(hfile, NULL, FILE_MAP_READ, PAGE_READONLY, SEC_COMMIT, 0, NULL, NULL, 0);
|
||||
ASSERT_MSG(file_mapping, "{}", Common::GetLastErrorMsg());
|
||||
return file_mapping;
|
||||
#else
|
||||
file_mapping = fileno(file);
|
||||
return file_mapping;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -100,7 +100,7 @@ public:
|
|||
return file != nullptr;
|
||||
}
|
||||
|
||||
void* GetFileMapping();
|
||||
uintptr_t GetFileMapping();
|
||||
|
||||
void Open(const std::filesystem::path& path, FileAccessMode mode,
|
||||
FileType type = FileType::BinaryFile,
|
||||
|
@ -214,7 +214,7 @@ private:
|
|||
FileType file_type{};
|
||||
|
||||
std::FILE* file = nullptr;
|
||||
void* file_mapping = nullptr;
|
||||
uintptr_t file_mapping = 0;
|
||||
};
|
||||
|
||||
} // namespace Common::FS
|
||||
|
|
|
@ -255,13 +255,14 @@ struct AddressSpace::Impl {
|
|||
m_free_regions.insert({start_addr, start_addr + virtual_size});
|
||||
}
|
||||
|
||||
void* Map(VAddr virtual_addr, PAddr phys_addr, size_t size, PosixPageProtection prot) {
|
||||
void* Map(VAddr virtual_addr, PAddr phys_addr, size_t size, PosixPageProtection prot,
|
||||
int fd = -1) {
|
||||
m_free_regions.subtract({virtual_addr, virtual_addr + size});
|
||||
const int fd = phys_addr != -1 ? backing_fd : -1;
|
||||
const int host_offset = phys_addr != -1 ? phys_addr : 0;
|
||||
const int handle = phys_addr != -1 ? (fd == -1 ? backing_fd : fd) : -1;
|
||||
const off_t host_offset = phys_addr != -1 ? phys_addr : 0;
|
||||
const int flag = phys_addr != -1 ? MAP_SHARED : (MAP_ANONYMOUS | MAP_PRIVATE);
|
||||
void* ret = mmap(reinterpret_cast<void*>(virtual_addr), size, prot, MAP_FIXED | flag, fd,
|
||||
host_offset);
|
||||
void* ret = mmap(reinterpret_cast<void*>(virtual_addr), size, prot, MAP_FIXED | flag,
|
||||
handle, host_offset);
|
||||
ASSERT_MSG(ret != MAP_FAILED, "mmap failed: {}", strerror(errno));
|
||||
return ret;
|
||||
}
|
||||
|
@ -324,7 +325,7 @@ void* AddressSpace::Map(VAddr virtual_addr, size_t size, u64 alignment, PAddr ph
|
|||
is_exec ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE);
|
||||
}
|
||||
|
||||
void* AddressSpace::MapFile(VAddr virtual_addr, size_t size, size_t offset, void* fd) {
|
||||
void* AddressSpace::MapFile(VAddr virtual_addr, size_t size, size_t offset, uintptr_t fd) {
|
||||
return impl->Map(virtual_addr, offset, size, fd ? PAGE_READONLY : PAGE_READWRITE, fd);
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ DECLARE_ENUM_FLAG_OPERATORS(MemoryPermission)
|
|||
|
||||
constexpr VAddr SYSTEM_RESERVED = 0x800000000ULL;
|
||||
constexpr VAddr CODE_BASE_OFFSET = 0x100000000ULL;
|
||||
constexpr VAddr SYSTEM_MANAGED_MIN = 0x0000040000ULL;
|
||||
constexpr VAddr SYSTEM_MANAGED_MIN = 0x00000400000ULL;
|
||||
constexpr VAddr SYSTEM_MANAGED_MAX = 0x07FFFFBFFFULL;
|
||||
constexpr VAddr USER_MIN = 0x1000000000ULL;
|
||||
constexpr VAddr USER_MAX = 0xFBFFFFFFFFULL;
|
||||
|
@ -63,7 +63,7 @@ public:
|
|||
bool exec = false);
|
||||
|
||||
/// Memory maps a specified file descriptor.
|
||||
void* MapFile(VAddr virtual_addr, size_t size, size_t offset, void* fd);
|
||||
void* MapFile(VAddr virtual_addr, size_t size, size_t offset, uintptr_t fd);
|
||||
|
||||
/// Unmaps specified virtual memory area.
|
||||
void Unmap(VAddr virtual_addr, size_t size, bool has_backing);
|
||||
|
|
|
@ -989,7 +989,7 @@ s32 PS4_SYSV_ABI sceGnmSetEmbeddedVsShader(u32* cmdbuf, u32 size, u32 shader_id,
|
|||
// a check for zero in the upper part of shader address. In our case, the address is a
|
||||
// pointer to a stack memory, so the check will likely fail. To workaround it we will
|
||||
// repeat set shader functionality here as it is trivial.
|
||||
cmdbuf = PM4CmdSetData::SetShReg(cmdbuf, 0x48u, vs_regs[0], 0u); // SPI_SHADER_PGM_LO_VS
|
||||
cmdbuf = PM4CmdSetData::SetShReg(cmdbuf, 0x48u, vs_regs[0], vs_regs[1]); // SPI_SHADER_PGM_LO_VS
|
||||
cmdbuf =
|
||||
PM4CmdSetData::SetShReg(cmdbuf, 0x4au, vs_regs[2], vs_regs[3]); // SPI_SHADER_PGM_RSRC1_VS
|
||||
cmdbuf = PM4CmdSetData::SetContextReg(cmdbuf, 0x207u, vs_regs[6]); // PA_CL_VS_OUT_CNTL
|
||||
|
|
|
@ -31,6 +31,10 @@ int PS4_SYSV_ABI sceKernelOpen(const char* path, int flags, u16 mode) {
|
|||
bool direct = (flags & ORBIS_KERNEL_O_DIRECT) != 0;
|
||||
bool directory = (flags & ORBIS_KERNEL_O_DIRECTORY) != 0;
|
||||
|
||||
if (std::string_view{path} == "/dev/console" || std::string_view{path} == "/dev/deci_tty6") {
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
if (directory) {
|
||||
LOG_ERROR(Kernel_Fs, "called on directory");
|
||||
} else {
|
||||
|
|
|
@ -73,17 +73,16 @@ int PS4_SYSV_ABI sceKernelMmap(void* addr, u64 len, int prot, int flags, int fd,
|
|||
fmt::ptr(addr), len, prot, flags, fd, offset);
|
||||
auto* h = Common::Singleton<Core::FileSys::HandleTable>::Instance();
|
||||
auto* memory = Core::Memory::Instance();
|
||||
void* handle = NULL;
|
||||
if (fd == -1) {
|
||||
handle =
|
||||
CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, len + offset, NULL);
|
||||
} else {
|
||||
handle = h->GetFile(fd)->f.GetFileMapping();
|
||||
}
|
||||
const auto mem_prot = static_cast<Core::MemoryProt>(prot);
|
||||
const auto mem_flags = static_cast<Core::MemoryMapFlags>(flags);
|
||||
return memory->MapFile(res, std::bit_cast<VAddr>(addr), len, mem_prot, mem_flags, handle,
|
||||
offset);
|
||||
if (fd == -1) {
|
||||
return memory->MapMemory(res, std::bit_cast<VAddr>(addr), len, mem_prot, mem_flags,
|
||||
Core::VMAType::Flexible);
|
||||
} else {
|
||||
const uintptr_t handle = h->GetFile(fd)->f.GetFileMapping();
|
||||
return memory->MapFile(res, std::bit_cast<VAddr>(addr), len, mem_prot, mem_flags, handle,
|
||||
offset);
|
||||
}
|
||||
}
|
||||
|
||||
void* PS4_SYSV_ABI posix_mmap(void* addr, u64 len, int prot, int flags, int fd, u64 offset) {
|
||||
|
@ -248,6 +247,15 @@ s32 PS4_SYSV_ABI sceKernelGetModuleInfoForUnwind(VAddr addr, int flags,
|
|||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceKernelGetModuleInfoFromAddr(VAddr addr, int flags,
|
||||
Core::OrbisKernelModuleInfoEx* info) {
|
||||
LOG_INFO(Lib_Kernel, "called addr = {:#x}, flags = {:#x}", addr, flags);
|
||||
auto* linker = Common::Singleton<Core::Linker>::Instance();
|
||||
auto* module = linker->FindByAddress(addr);
|
||||
*info = module->GetModuleInfoEx();
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI sceKernelDebugRaiseException() {
|
||||
UNREACHABLE();
|
||||
return 0;
|
||||
|
@ -267,6 +275,10 @@ int PS4_SYSV_ABI sceKernelGetCpumode() {
|
|||
return 5;
|
||||
}
|
||||
|
||||
void PS4_SYSV_ABI sched_yield() {
|
||||
return std::this_thread::yield();
|
||||
}
|
||||
|
||||
void LibKernel_Register(Core::Loader::SymbolsResolver* sym) {
|
||||
// obj
|
||||
LIB_OBJ("f7uOxY9mM1U", "libkernel", 1, "libkernel", 1, 1, &g_stack_chk_guard);
|
||||
|
@ -292,6 +304,7 @@ void LibKernel_Register(Core::Loader::SymbolsResolver* sym) {
|
|||
LIB_FUNCTION("wzvqT4UqKX8", "libkernel", 1, "libkernel", 1, 1, sceKernelLoadStartModule);
|
||||
LIB_FUNCTION("LwG8g3niqwA", "libkernel", 1, "libkernel", 1, 1, sceKernelDlsym);
|
||||
LIB_FUNCTION("RpQJJVKTiFM", "libkernel", 1, "libkernel", 1, 1, sceKernelGetModuleInfoForUnwind);
|
||||
LIB_FUNCTION("f7KBOafysXo", "libkernel", 1, "libkernel", 1, 1, sceKernelGetModuleInfoFromAddr);
|
||||
LIB_FUNCTION("VOx8NGmHXTs", "libkernel", 1, "libkernel", 1, 1, sceKernelGetCpumode);
|
||||
|
||||
// equeue
|
||||
|
@ -326,6 +339,7 @@ void LibKernel_Register(Core::Loader::SymbolsResolver* sym) {
|
|||
LIB_FUNCTION("NWtTN10cJzE", "libSceLibcInternalExt", 1, "libSceLibcInternal", 1, 1,
|
||||
sceLibcHeapGetTraceInfo);
|
||||
LIB_FUNCTION("FxVZqBAA7ks", "libkernel", 1, "libkernel", 1, 1, ps4__write);
|
||||
LIB_FUNCTION("6XG4B33N09g", "libScePosix", 1, "libkernel", 1, 1, sched_yield);
|
||||
}
|
||||
|
||||
} // namespace Libraries::Kernel
|
||||
|
|
|
@ -90,10 +90,10 @@ s32 PS4_SYSV_ABI sceKernelVirtualQuery(const void* addr, int flags, OrbisVirtual
|
|||
int PS4_SYSV_ABI sceKernelMapNamedDirectMemory(void** addr, u64 len, int prot, int flags,
|
||||
s64 directMemoryStart, u64 alignment,
|
||||
const char* name) {
|
||||
LOG_INFO(
|
||||
Kernel_Vmm,
|
||||
"len = {:#x}, prot = {:#x}, flags = {:#x}, directMemoryStart = {:#x}, alignment = {:#x}",
|
||||
len, prot, flags, directMemoryStart, alignment);
|
||||
LOG_INFO(Kernel_Vmm,
|
||||
"addr = {}, len = {:#x}, prot = {:#x}, flags = {:#x}, directMemoryStart = {:#x}, "
|
||||
"alignment = {:#x}",
|
||||
fmt::ptr(*addr), len, prot, flags, directMemoryStart, alignment);
|
||||
|
||||
if (len == 0 || !Common::Is16KBAligned(len)) {
|
||||
LOG_ERROR(Kernel_Vmm, "Map size is either zero or not 16KB aligned!");
|
||||
|
@ -120,11 +120,7 @@ int PS4_SYSV_ABI sceKernelMapNamedDirectMemory(void** addr, u64 len, int prot, i
|
|||
|
||||
int PS4_SYSV_ABI sceKernelMapDirectMemory(void** addr, u64 len, int prot, int flags,
|
||||
s64 directMemoryStart, u64 alignment) {
|
||||
LOG_INFO(Kernel_Vmm,
|
||||
"redirected to sceKernelMapNamedDirectMemory: "
|
||||
"len = {:#x}, prot = {:#x}, flags = {:#x}, directMemoryStart = {:#x}, alignment = "
|
||||
"{:#x}",
|
||||
len, prot, flags, directMemoryStart, alignment);
|
||||
LOG_INFO(Kernel_Vmm, "called, redirected to sceKernelMapNamedDirectMemory");
|
||||
return sceKernelMapNamedDirectMemory(addr, len, prot, flags, directMemoryStart, alignment, "");
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include <thread>
|
||||
#include <semaphore.h>
|
||||
#include "common/assert.h"
|
||||
#include "common/error.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "common/singleton.h"
|
||||
#include "common/thread.h"
|
||||
|
@ -138,9 +139,8 @@ int PS4_SYSV_ABI scePthreadAttrGetdetachstate(const ScePthreadAttr* attr, int* s
|
|||
return SCE_KERNEL_ERROR_EINVAL;
|
||||
}
|
||||
|
||||
// int result = pthread_attr_getdetachstate(&(*attr)->p, state);
|
||||
// int result = pthread_attr_getdetachstate(&(*attr)->pth_attr, state);
|
||||
int result = 0;
|
||||
|
||||
*state = ((*attr)->detached ? PTHREAD_CREATE_DETACHED : PTHREAD_CREATE_JOINABLE);
|
||||
|
||||
switch (*state) {
|
||||
|
@ -174,12 +174,9 @@ int PS4_SYSV_ABI scePthreadAttrSetdetachstate(ScePthreadAttr* attr, int detachst
|
|||
UNREACHABLE_MSG("Invalid detachstate: {}", detachstate);
|
||||
}
|
||||
|
||||
// int result = pthread_attr_setdetachstate(&(*attr)->pth_attr, pstate); doesn't seem to work
|
||||
// correctly
|
||||
// int result = pthread_attr_setdetachstate(&(*attr)->pth_attr, pstate);
|
||||
int result = 0;
|
||||
|
||||
(*attr)->detached = (pstate == PTHREAD_CREATE_DETACHED);
|
||||
|
||||
return result == 0 ? SCE_OK : SCE_KERNEL_ERROR_EINVAL;
|
||||
}
|
||||
|
||||
|
@ -246,7 +243,6 @@ int PS4_SYSV_ABI scePthreadAttrSetschedparam(ScePthreadAttr* attr,
|
|||
}
|
||||
|
||||
int PS4_SYSV_ABI scePthreadAttrGetschedpolicy(const ScePthreadAttr* attr, int* policy) {
|
||||
|
||||
if (policy == nullptr || attr == nullptr || *attr == nullptr) {
|
||||
return SCE_KERNEL_ERROR_EINVAL;
|
||||
}
|
||||
|
@ -275,16 +271,26 @@ int PS4_SYSV_ABI scePthreadAttrSetschedpolicy(ScePthreadAttr* attr, int policy)
|
|||
return SCE_KERNEL_ERROR_EINVAL;
|
||||
}
|
||||
|
||||
int ppolicy = SCHED_OTHER; // winpthreads only supports SCHED_OTHER
|
||||
if (policy != SCHED_OTHER) {
|
||||
LOG_ERROR(Kernel_Pthread, "policy={} not supported by winpthreads\n", policy);
|
||||
int ppolicy = SCHED_OTHER;
|
||||
switch (policy) {
|
||||
case 0:
|
||||
ppolicy = SCHED_OTHER;
|
||||
break;
|
||||
case 1:
|
||||
ppolicy = SCHED_FIFO;
|
||||
break;
|
||||
case 3:
|
||||
ppolicy = SCHED_OTHER;
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
(*attr)->policy = policy;
|
||||
|
||||
int result = pthread_attr_setschedpolicy(&(*attr)->pth_attr, ppolicy);
|
||||
|
||||
return result == 0 ? SCE_OK : SCE_KERNEL_ERROR_EINVAL;
|
||||
}
|
||||
|
||||
ScePthread PS4_SYSV_ABI scePthreadSelf() {
|
||||
return g_pthread_self;
|
||||
}
|
||||
|
@ -298,7 +304,6 @@ int PS4_SYSV_ABI scePthreadAttrSetaffinity(ScePthreadAttr* pattr,
|
|||
}
|
||||
|
||||
(*pattr)->affinity = mask;
|
||||
|
||||
return SCE_OK;
|
||||
}
|
||||
|
||||
|
@ -391,16 +396,18 @@ int PS4_SYSV_ABI scePthreadSetaffinity(ScePthread thread, const /*SceKernelCpuma
|
|||
return result;
|
||||
}
|
||||
|
||||
void* createMutex(void* addr) {
|
||||
if (addr == nullptr || *static_cast<ScePthreadMutex*>(addr) != nullptr) {
|
||||
ScePthreadMutex* createMutex(ScePthreadMutex* addr) {
|
||||
if (addr == nullptr || *addr != nullptr) {
|
||||
return addr;
|
||||
}
|
||||
static std::mutex mutex;
|
||||
std::scoped_lock lk{mutex};
|
||||
auto vaddr = reinterpret_cast<u64>(addr);
|
||||
|
||||
if (*addr != nullptr) {
|
||||
return addr;
|
||||
}
|
||||
const VAddr vaddr = reinterpret_cast<VAddr>(addr);
|
||||
std::string name = fmt::format("mutex{:#x}", vaddr);
|
||||
scePthreadMutexInit(static_cast<ScePthreadMutex*>(addr), nullptr, name.c_str());
|
||||
scePthreadMutexInit(addr, nullptr, name.c_str());
|
||||
return addr;
|
||||
}
|
||||
|
||||
|
@ -468,7 +475,7 @@ int PS4_SYSV_ABI scePthreadMutexattrInit(ScePthreadMutexattr* attr) {
|
|||
|
||||
int result = pthread_mutexattr_init(&(*attr)->pth_mutex_attr);
|
||||
|
||||
result = (result == 0 ? scePthreadMutexattrSettype(attr, 2) : result);
|
||||
result = (result == 0 ? scePthreadMutexattrSettype(attr, 1) : result);
|
||||
result = (result == 0 ? scePthreadMutexattrSetprotocol(attr, 0) : result);
|
||||
|
||||
switch (result) {
|
||||
|
@ -519,22 +526,20 @@ int PS4_SYSV_ABI scePthreadMutexattrSetprotocol(ScePthreadMutexattr* attr, int p
|
|||
UNREACHABLE_MSG("Invalid protocol: {}", protocol);
|
||||
}
|
||||
|
||||
int result = 0; // pthread_mutexattr_setprotocol(&(*attr)->p, pprotocol); //it appears that
|
||||
// pprotocol has issues in winpthreads
|
||||
int result = pthread_mutexattr_setprotocol(&(*attr)->pth_mutex_attr, pprotocol);
|
||||
(*attr)->pprotocol = pprotocol;
|
||||
|
||||
return result == 0 ? SCE_OK : SCE_KERNEL_ERROR_EINVAL;
|
||||
}
|
||||
int PS4_SYSV_ABI scePthreadMutexLock(ScePthreadMutex* mutex) {
|
||||
mutex = static_cast<ScePthreadMutex*>(createMutex(mutex));
|
||||
|
||||
int PS4_SYSV_ABI scePthreadMutexLock(ScePthreadMutex* mutex) {
|
||||
mutex = createMutex(mutex);
|
||||
if (mutex == nullptr) {
|
||||
return SCE_KERNEL_ERROR_EINVAL;
|
||||
}
|
||||
|
||||
int result = pthread_mutex_lock(&(*mutex)->pth_mutex);
|
||||
if (result != 0) {
|
||||
LOG_TRACE(Kernel_Pthread, "name={}, result={}", (*mutex)->name, result);
|
||||
LOG_TRACE(Kernel_Pthread, "Locked name={}, result={}", (*mutex)->name, result);
|
||||
}
|
||||
switch (result) {
|
||||
case 0:
|
||||
|
@ -549,20 +554,20 @@ int PS4_SYSV_ABI scePthreadMutexLock(ScePthreadMutex* mutex) {
|
|||
return SCE_KERNEL_ERROR_EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI scePthreadMutexUnlock(ScePthreadMutex* mutex) {
|
||||
mutex = static_cast<ScePthreadMutex*>(createMutex(mutex));
|
||||
mutex = createMutex(mutex);
|
||||
if (mutex == nullptr) {
|
||||
return SCE_KERNEL_ERROR_EINVAL;
|
||||
}
|
||||
|
||||
int result = pthread_mutex_unlock(&(*mutex)->pth_mutex);
|
||||
if (result != 0) {
|
||||
LOG_TRACE(Kernel_Pthread, "name={}, result={}", (*mutex)->name, result);
|
||||
LOG_TRACE(Kernel_Pthread, "Unlocking name={}, result={}", (*mutex)->name, result);
|
||||
}
|
||||
switch (result) {
|
||||
case 0:
|
||||
return SCE_OK;
|
||||
|
||||
case EINVAL:
|
||||
return SCE_KERNEL_ERROR_EINVAL;
|
||||
case EPERM:
|
||||
|
@ -573,7 +578,6 @@ int PS4_SYSV_ABI scePthreadMutexUnlock(ScePthreadMutex* mutex) {
|
|||
}
|
||||
|
||||
int PS4_SYSV_ABI scePthreadMutexattrDestroy(ScePthreadMutexattr* attr) {
|
||||
|
||||
int result = pthread_mutexattr_destroy(&(*attr)->pth_mutex_attr);
|
||||
|
||||
delete *attr;
|
||||
|
@ -589,12 +593,16 @@ int PS4_SYSV_ABI scePthreadMutexattrDestroy(ScePthreadMutexattr* attr) {
|
|||
}
|
||||
}
|
||||
|
||||
void* createCond(void* addr) {
|
||||
if (addr == nullptr || *static_cast<ScePthreadCond*>(addr) != nullptr) {
|
||||
ScePthreadCond* createCond(ScePthreadCond* addr) {
|
||||
if (addr == nullptr || *addr != nullptr) {
|
||||
return addr;
|
||||
}
|
||||
auto vaddr = reinterpret_cast<u64>(addr);
|
||||
|
||||
static std::mutex mutex;
|
||||
std::scoped_lock lk{mutex};
|
||||
if (*addr != nullptr) {
|
||||
return addr;
|
||||
}
|
||||
const VAddr vaddr = reinterpret_cast<VAddr>(addr);
|
||||
std::string name = fmt::format("cond{:#x}", vaddr);
|
||||
scePthreadCondInit(static_cast<ScePthreadCond*>(addr), nullptr, name.c_str());
|
||||
return addr;
|
||||
|
@ -654,8 +662,7 @@ int PS4_SYSV_ABI scePthreadCondattrInit(ScePthreadCondattr* attr) {
|
|||
}
|
||||
|
||||
int PS4_SYSV_ABI scePthreadCondBroadcast(ScePthreadCond* cond) {
|
||||
cond = static_cast<ScePthreadCond*>(createCond(cond));
|
||||
|
||||
cond = createCond(cond);
|
||||
if (cond == nullptr) {
|
||||
return SCE_KERNEL_ERROR_EINVAL;
|
||||
}
|
||||
|
@ -668,7 +675,7 @@ int PS4_SYSV_ABI scePthreadCondBroadcast(ScePthreadCond* cond) {
|
|||
}
|
||||
|
||||
int PS4_SYSV_ABI scePthreadCondTimedwait(ScePthreadCond* cond, ScePthreadMutex* mutex, u64 usec) {
|
||||
cond = static_cast<ScePthreadCond*>(createCond(cond));
|
||||
cond = createCond(cond);
|
||||
if (cond == nullptr) {
|
||||
return SCE_KERNEL_ERROR_EINVAL;
|
||||
}
|
||||
|
@ -1032,9 +1039,9 @@ int PS4_SYSV_ABI scePthreadCondSignal(ScePthreadCond* cond) {
|
|||
}
|
||||
|
||||
int PS4_SYSV_ABI scePthreadCondWait(ScePthreadCond* cond, ScePthreadMutex* mutex) {
|
||||
if (cond == nullptr || *cond == nullptr) {
|
||||
// return SCE_KERNEL_ERROR_EINVAL;
|
||||
cond = static_cast<ScePthreadCond*>(createCond(cond)); // check this. Kero Blaster.
|
||||
cond = createCond(cond);
|
||||
if (cond == nullptr) {
|
||||
return SCE_KERNEL_ERROR_EINVAL;
|
||||
}
|
||||
if (mutex == nullptr || *mutex == nullptr) {
|
||||
return SCE_KERNEL_ERROR_EINVAL;
|
||||
|
@ -1074,7 +1081,7 @@ int PS4_SYSV_ABI scePthreadCondattrDestroy(ScePthreadCondattr* attr) {
|
|||
}
|
||||
|
||||
int PS4_SYSV_ABI scePthreadMutexTrylock(ScePthreadMutex* mutex) {
|
||||
mutex = reinterpret_cast<ScePthreadMutex*>(createMutex(mutex));
|
||||
mutex = createMutex(mutex);
|
||||
if (mutex == nullptr) {
|
||||
return ORBIS_KERNEL_ERROR_EINVAL;
|
||||
}
|
||||
|
@ -1250,7 +1257,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("7Xl257M4VNI", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_equal);
|
||||
LIB_FUNCTION("7Xl257M4VNI", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_join);
|
||||
LIB_FUNCTION("h9CcP3J0oVM", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_join);
|
||||
|
||||
LIB_FUNCTION("aI+OeCz8xrQ", "libkernel", 1, "libkernel", 1, 1, scePthreadSelf);
|
||||
LIB_FUNCTION("EotR8a3ASf4", "libkernel", 1, "libkernel", 1, 1, posix_pthread_self);
|
||||
|
@ -1331,6 +1338,4 @@ void pthreadSymbolsRegister(Core::Loader::SymbolsResolver* sym) {
|
|||
SemaphoreSymbolsRegister(sym);
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace Libraries::Kernel
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
#include <pthread.h>
|
||||
#include <sched.h>
|
||||
#include "common/types.h"
|
||||
#include <mutex>
|
||||
|
||||
namespace Core::Loader {
|
||||
class SymbolsResolver;
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <thread>
|
||||
#include "common/logging/log.h"
|
||||
#include "core/libraries/error_codes.h"
|
||||
#include "core/libraries/kernel/threads/threads.h"
|
||||
#include "core/libraries/libs.h"
|
||||
#include "threads.h"
|
||||
|
||||
namespace Libraries::Kernel {
|
||||
|
||||
|
@ -25,6 +26,7 @@ bool PthreadKeys::CreateKey(int* key, PthreadKeyDestructor destructor) {
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PthreadKeys::GetKey(int key, int thread_id, void** data) {
|
||||
std::scoped_lock lk{m_mutex};
|
||||
|
||||
|
@ -88,7 +90,6 @@ void* PS4_SYSV_ABI scePthreadGetspecific(OrbisPthreadKey key) {
|
|||
}
|
||||
|
||||
int PS4_SYSV_ABI scePthreadSetspecific(OrbisPthreadKey key, /* const*/ void* value) {
|
||||
|
||||
auto id = std::this_thread::get_id();
|
||||
int thread_id = *(unsigned*)&id;
|
||||
|
||||
|
@ -99,4 +100,4 @@ int PS4_SYSV_ABI scePthreadSetspecific(OrbisPthreadKey key, /* const*/ void* val
|
|||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
} // namespace Libraries::Kernel
|
||||
} // namespace Libraries::Kernel
|
||||
|
|
|
@ -34,10 +34,23 @@ int PS4_SYSV_ABI posix_pthread_rwlock_init(OrbisPthreadRwlock* rwlock,
|
|||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI posix_pthread_rwlock_rdlock(OrbisPthreadRwlock* rwlock) {
|
||||
if (*rwlock == nullptr) {
|
||||
posix_pthread_rwlock_init(rwlock, nullptr, nullptr);
|
||||
OrbisPthreadRwlock* createRwlock(OrbisPthreadRwlock* rwlock) {
|
||||
if (rwlock == nullptr || *rwlock != nullptr) {
|
||||
return rwlock;
|
||||
}
|
||||
static std::mutex mutex;
|
||||
std::scoped_lock lk{mutex};
|
||||
if (*rwlock != nullptr) {
|
||||
return rwlock;
|
||||
}
|
||||
const VAddr addr = std::bit_cast<VAddr>(rwlock);
|
||||
const auto name = fmt::format("rwlock{:#x}", addr);
|
||||
posix_pthread_rwlock_init(rwlock, nullptr, name.c_str());
|
||||
return rwlock;
|
||||
}
|
||||
|
||||
int PS4_SYSV_ABI posix_pthread_rwlock_rdlock(OrbisPthreadRwlock* rwlock) {
|
||||
rwlock = createRwlock(rwlock);
|
||||
int result = pthread_rwlock_rdlock(&(*rwlock)->pth_rwlock);
|
||||
if (result != 0) {
|
||||
LOG_ERROR(Kernel_Pthread, "posix_pthread_rwlock_rdlock: error = {}", result);
|
||||
|
@ -72,6 +85,10 @@ int PS4_SYSV_ABI posix_pthread_rwlock_timedwrlock() {
|
|||
}
|
||||
|
||||
int PS4_SYSV_ABI posix_pthread_rwlock_tryrdlock(OrbisPthreadRwlock* rwlock) {
|
||||
rwlock = createRwlock(rwlock);
|
||||
if (rwlock == nullptr) {
|
||||
return ORBIS_KERNEL_ERROR_EINVAL;
|
||||
}
|
||||
int result = pthread_rwlock_tryrdlock(&(*rwlock)->pth_rwlock);
|
||||
if (result != 0) {
|
||||
LOG_ERROR(Kernel_Pthread, "posix_pthread_rwlock_tryrdlock: error = {}", result);
|
||||
|
@ -80,6 +97,10 @@ int PS4_SYSV_ABI posix_pthread_rwlock_tryrdlock(OrbisPthreadRwlock* rwlock) {
|
|||
}
|
||||
|
||||
int PS4_SYSV_ABI posix_pthread_rwlock_trywrlock(OrbisPthreadRwlock* rwlock) {
|
||||
rwlock = createRwlock(rwlock);
|
||||
if (rwlock == nullptr) {
|
||||
return ORBIS_KERNEL_ERROR_EINVAL;
|
||||
}
|
||||
int result = pthread_rwlock_trywrlock(&(*rwlock)->pth_rwlock);
|
||||
if (result != 0) {
|
||||
LOG_ERROR(Kernel_Pthread, "posix_pthread_rwlock_trywrlock: error = {}", result);
|
||||
|
@ -88,6 +109,10 @@ int PS4_SYSV_ABI posix_pthread_rwlock_trywrlock(OrbisPthreadRwlock* rwlock) {
|
|||
}
|
||||
|
||||
int PS4_SYSV_ABI posix_pthread_rwlock_unlock(OrbisPthreadRwlock* rwlock) {
|
||||
rwlock = createRwlock(rwlock);
|
||||
if (rwlock == nullptr) {
|
||||
return ORBIS_KERNEL_ERROR_EINVAL;
|
||||
}
|
||||
int result = pthread_rwlock_unlock(&(*rwlock)->pth_rwlock);
|
||||
if (result != 0) {
|
||||
LOG_ERROR(Kernel_Pthread, "posix_pthread_rwlock_unlock: error = {}", result);
|
||||
|
@ -96,6 +121,10 @@ int PS4_SYSV_ABI posix_pthread_rwlock_unlock(OrbisPthreadRwlock* rwlock) {
|
|||
}
|
||||
|
||||
int PS4_SYSV_ABI posix_pthread_rwlock_wrlock(OrbisPthreadRwlock* rwlock) {
|
||||
rwlock = createRwlock(rwlock);
|
||||
if (rwlock == nullptr) {
|
||||
return ORBIS_KERNEL_ERROR_EINVAL;
|
||||
}
|
||||
int result = pthread_rwlock_wrlock(&(*rwlock)->pth_rwlock);
|
||||
if (result != 0) {
|
||||
LOG_ERROR(Kernel_Pthread, "posix_pthread_rwlock_wrlock: error = {}", result);
|
||||
|
@ -274,9 +303,7 @@ int PS4_SYSV_ABI scePthreadRwlockUnlock(OrbisPthreadRwlock* rwlock) {
|
|||
}
|
||||
|
||||
int PS4_SYSV_ABI scePthreadRwlockWrlock(OrbisPthreadRwlock* rwlock) {
|
||||
if (rwlock == nullptr || *rwlock == nullptr) {
|
||||
return ORBIS_KERNEL_ERROR_EINVAL;
|
||||
}
|
||||
rwlock = createRwlock(rwlock);
|
||||
int result = pthread_rwlock_wrlock(&(*rwlock)->pth_rwlock);
|
||||
if (result != 0) {
|
||||
LOG_ERROR(Kernel_Pthread, "scePthreadRwlockWrlock: error = {}", result);
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <condition_variable>
|
||||
#include <mutex>
|
||||
#include <boost/intrusive/list.hpp>
|
||||
#include <pthread.h>
|
||||
#include "common/assert.h"
|
||||
|
@ -17,8 +18,8 @@ using ListBaseHook =
|
|||
|
||||
class Semaphore {
|
||||
public:
|
||||
Semaphore(s32 init_count, s32 max_count, bool is_fifo)
|
||||
: token_count{init_count}, max_count{max_count}, is_fifo{is_fifo} {}
|
||||
Semaphore(s32 init_count, s32 max_count, const char* name, bool is_fifo)
|
||||
: name{name}, token_count{init_count}, max_count{max_count}, is_fifo{is_fifo} {}
|
||||
|
||||
bool Wait(bool can_block, s32 need_count, u64* timeout) {
|
||||
if (HasAvailableTokens(need_count)) {
|
||||
|
@ -131,6 +132,7 @@ private:
|
|||
boost::intrusive::list<WaitingThread, boost::intrusive::base_hook<ListBaseHook>,
|
||||
boost::intrusive::constant_time_size<false>>;
|
||||
WaitingThreads wait_list;
|
||||
std::string name;
|
||||
std::atomic<s32> token_count;
|
||||
std::mutex mutex;
|
||||
s32 max_count;
|
||||
|
@ -145,7 +147,7 @@ s32 PS4_SYSV_ABI sceKernelCreateSema(OrbisKernelSema* sem, const char* pName, u3
|
|||
LOG_ERROR(Lib_Kernel, "Semaphore creation parameters are invalid!");
|
||||
return ORBIS_KERNEL_ERROR_EINVAL;
|
||||
}
|
||||
*sem = new Semaphore(initCount, maxCount, attr == 1);
|
||||
*sem = new Semaphore(initCount, maxCount, pName, attr == 1);
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -63,9 +63,13 @@ int PS4_SYSV_ABI sceKernelUsleep(u32 microseconds) {
|
|||
}
|
||||
|
||||
int PS4_SYSV_ABI posix_usleep(u32 microseconds) {
|
||||
ASSERT(microseconds >= 1000);
|
||||
#ifdef _WIN64
|
||||
ASSERT(microseconds >= 1000 || microseconds == 0);
|
||||
std::this_thread::sleep_for(std::chrono::microseconds(microseconds));
|
||||
return 0;
|
||||
#else
|
||||
return usleep(microseconds);
|
||||
#endif
|
||||
}
|
||||
|
||||
u32 PS4_SYSV_ABI sceKernelSleep(u32 seconds) {
|
||||
|
@ -152,6 +156,7 @@ int PS4_SYSV_ABI gettimeofday(OrbisKernelTimeval* tp, OrbisKernelTimezone* tz) {
|
|||
}
|
||||
|
||||
s32 PS4_SYSV_ABI sceKernelGettimezone(OrbisKernelTimezone* tz) {
|
||||
#ifdef _WIN64
|
||||
ASSERT(tz);
|
||||
static int tzflag = 0;
|
||||
if (!tzflag) {
|
||||
|
@ -160,6 +165,13 @@ s32 PS4_SYSV_ABI sceKernelGettimezone(OrbisKernelTimezone* tz) {
|
|||
}
|
||||
tz->tz_minuteswest = _timezone / 60;
|
||||
tz->tz_dsttime = _daylight;
|
||||
#else
|
||||
struct timezone tzz;
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, &tzz);
|
||||
tz->tz_dsttime = tzz.tz_dsttime;
|
||||
tz->tz_minuteswest = tzz.tz_minuteswest;
|
||||
#endif
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
|
@ -176,6 +188,7 @@ void timeSymbolsRegister(Core::Loader::SymbolsResolver* sym) {
|
|||
LIB_FUNCTION("n88vx3C5nW8", "libkernel", 1, "libkernel", 1, 1, gettimeofday);
|
||||
LIB_FUNCTION("n88vx3C5nW8", "libScePosix", 1, "libkernel", 1, 1, gettimeofday);
|
||||
LIB_FUNCTION("1jfXLRVzisc", "libkernel", 1, "libkernel", 1, 1, sceKernelUsleep);
|
||||
LIB_FUNCTION("QcteRwbsnV0", "libkernel", 1, "libkernel", 1, 1, posix_usleep);
|
||||
LIB_FUNCTION("QcteRwbsnV0", "libScePosix", 1, "libkernel", 1, 1, posix_usleep);
|
||||
LIB_FUNCTION("-ZR+hG7aDHw", "libkernel", 1, "libkernel", 1, 1, sceKernelSleep);
|
||||
LIB_FUNCTION("0wu33hunNdE", "libScePosix", 1, "libkernel", 1, 1, sceKernelSleep);
|
||||
|
|
|
@ -24,15 +24,13 @@ template <StringLiteral name, class R, class... Args, PS4_SYSV_ABI R (*f)(Args..
|
|||
struct wrapper_impl<name, PS4_SYSV_ABI R (*)(Args...), f> {
|
||||
static R PS4_SYSV_ABI wrap(Args... args) {
|
||||
if (std::string_view(name.value) != "scePthreadEqual" &&
|
||||
std::string_view(name.value) != "sceUserServiceGetEvent" &&
|
||||
!std::string_view(name.value).contains("mutex") &&
|
||||
!std::string_view(name.value).contains("Mutex")) {
|
||||
// LOG_WARNING(Core_Linker, "Function {} called", name.value);
|
||||
std::string_view(name.value) != "sceUserServiceGetEvent") {
|
||||
LOG_WARNING(Core_Linker, "Function {} called", name.value);
|
||||
}
|
||||
if constexpr (std::is_same_v<R, s32> || std::is_same_v<R, u32>) {
|
||||
const int ret = f(args...);
|
||||
const u32 ret = f(args...);
|
||||
if (ret != 0 && std::string_view(name.value) != "scePthreadEqual") {
|
||||
LOG_WARNING(Core_Linker, "Function {} returned {}", name.value, ret);
|
||||
LOG_WARNING(Core_Linker, "Function {} returned {:#x}", name.value, ret);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -44,7 +42,7 @@ struct wrapper_impl<name, PS4_SYSV_ABI R (*)(Args...), f> {
|
|||
template <StringLiteral name, class F, F f>
|
||||
constexpr auto wrapper = wrapper_impl<name, F, f>::wrap;
|
||||
|
||||
//#define W(foo) wrapper<#foo, decltype(&foo), foo>
|
||||
// #define W(foo) wrapper<#foo, decltype(&foo), foo>
|
||||
#define W(foo) foo
|
||||
|
||||
#define LIB_FUNCTION(nid, lib, libversion, mod, moduleVersionMajor, moduleVersionMinor, function) \
|
||||
|
|
|
@ -733,4 +733,4 @@ void RegisterlibSceSaveData(Core::Loader::SymbolsResolver* sym) {
|
|||
LIB_FUNCTION("AuTE0gFxZCI", "libSceSaveData", 1, "libSceSaveData", 1, 1, Func_02E4C4D201716422);
|
||||
};
|
||||
|
||||
} // namespace Libraries::SaveData
|
||||
} // namespace Libraries::SaveData
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
#include "core/module.h"
|
||||
|
|
|
@ -91,6 +91,7 @@ int MemoryManager::MapMemory(void** out_addr, VAddr virtual_addr, size_t size, M
|
|||
// 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.VirtualBase() : virtual_addr;
|
||||
alignment = alignment > 0 ? alignment : 16_KB;
|
||||
|
||||
VAddr mapped_addr = alignment > 0 ? Common::AlignUp(virtual_addr, alignment) : virtual_addr;
|
||||
SCOPE_EXIT {
|
||||
|
@ -141,7 +142,7 @@ int MemoryManager::MapMemory(void** out_addr, VAddr virtual_addr, size_t size, M
|
|||
}
|
||||
|
||||
int MemoryManager::MapFile(void** out_addr, VAddr virtual_addr, size_t size, MemoryProt prot,
|
||||
MemoryMapFlags flags, void* fd, size_t offset) {
|
||||
MemoryMapFlags flags, uintptr_t fd, size_t offset) {
|
||||
ASSERT(virtual_addr == 0);
|
||||
virtual_addr = impl.VirtualBase();
|
||||
const size_t size_aligned = Common::AlignUp(size, 16_KB);
|
||||
|
@ -155,7 +156,7 @@ int MemoryManager::MapFile(void** out_addr, VAddr virtual_addr, size_t size, Mem
|
|||
|
||||
// Map the file.
|
||||
const VAddr mapped_addr = it->second.base;
|
||||
impl.MapFile(mapped_addr, Common::AlignDown(size, 4_KB), offset, fd);
|
||||
impl.MapFile(mapped_addr, size, offset, fd);
|
||||
|
||||
// Add virtual memory area
|
||||
auto& new_vma = AddMapping(mapped_addr, size_aligned);
|
||||
|
|
|
@ -86,7 +86,7 @@ struct VirtualMemoryArea {
|
|||
MemoryProt prot = MemoryProt::NoAccess;
|
||||
bool disallow_merge = false;
|
||||
std::string name = "";
|
||||
void* fd = nullptr;
|
||||
uintptr_t fd = 0;
|
||||
|
||||
bool Contains(VAddr addr, size_t size) const {
|
||||
return addr >= base && (addr + size) < (base + this->size);
|
||||
|
@ -134,7 +134,7 @@ public:
|
|||
bool is_exec = false, PAddr phys_addr = -1, u64 alignment = 0);
|
||||
|
||||
int MapFile(void** out_addr, VAddr virtual_addr, size_t size, MemoryProt prot,
|
||||
MemoryMapFlags flags, void* fd, size_t offset);
|
||||
MemoryMapFlags flags, uintptr_t fd, size_t offset);
|
||||
|
||||
void UnmapMemory(VAddr virtual_addr, size_t size);
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ static constexpr size_t SCE_DBG_NUM_FINGERPRINT = 20;
|
|||
|
||||
struct OrbisKernelModuleSegmentInfo {
|
||||
VAddr address;
|
||||
u64 size;
|
||||
u32 size;
|
||||
s32 prot;
|
||||
};
|
||||
|
||||
|
|
|
@ -125,7 +125,8 @@ static void PatchFsAccess(u8* code, const TLSPattern& tls_pattern, Xbyak::CodeGe
|
|||
const auto target_reg = Xbyak::Reg64(tls_pattern.target_reg);
|
||||
c.putSeg(fs);
|
||||
c.mov(target_reg, qword[SelfInTcbheadOffset]); // Load self member pointer of tcbhead_t.
|
||||
c.add(target_reg, SpecificFirstBlockOffset + sizeof(uintptr_t) + slot * PthreadKeyDataSize);
|
||||
c.add(target_reg, SpecificFirstBlockOffset + sizeof(uintptr_t) * 2 + slot * PthreadKeyDataSize);
|
||||
c.mov(target_reg, qword[target_reg]);
|
||||
c.jmp(code + total_size); // Return to the instruction right after the mov.
|
||||
}
|
||||
|
||||
|
|
|
@ -94,11 +94,11 @@ void Emulator::Run(const std::filesystem::path& file) {
|
|||
if (std::filesystem::is_directory(sce_module_folder)) {
|
||||
for (const auto& entry : std::filesystem::directory_iterator(sce_module_folder)) {
|
||||
if (entry.path().filename() == "libc.prx" ||
|
||||
entry.path().filename() == "libSceFios2.prx" /*||
|
||||
entry.path().filename() == "libSceFios2.prx" ||
|
||||
entry.path().filename() == "libSceAudioLatencyEstimation.prx" ||
|
||||
entry.path().filename() == "libSceJobManager.prx" ||
|
||||
entry.path().filename() == "libSceNpToolkit2.prx" ||
|
||||
entry.path().filename() == "libSceS3DConversion.prx"*/) {
|
||||
entry.path().filename() == "libSceS3DConversion.prx") {
|
||||
found = true;
|
||||
LOG_INFO(Loader, "Loading {}", entry.path().string().c_str());
|
||||
linker->LoadModule(entry.path());
|
||||
|
@ -115,15 +115,10 @@ void Emulator::Run(const std::filesystem::path& file) {
|
|||
std::jthread([this](std::stop_token stop_token) { linker->Execute(); });
|
||||
|
||||
// Begin main window loop until the application exits
|
||||
<<<<<<< HEAD
|
||||
static constexpr std::chrono::milliseconds FlipPeriod{16};
|
||||
=======
|
||||
static constexpr std::chrono::microseconds FlipPeriod{10};
|
||||
>>>>>>> 31bd502764f1ac975fc55bd2a788a7e08a9f34ec
|
||||
|
||||
while (window.isOpen()) {
|
||||
window.waitEvent();
|
||||
std::this_thread::sleep_for(FlipPeriod);
|
||||
Libraries::VideoOut::Flip(FlipPeriod);
|
||||
Libraries::VideoOut::Vblank();
|
||||
FRAME_END;
|
||||
|
@ -135,7 +130,8 @@ void Emulator::Run(const std::filesystem::path& file) {
|
|||
void Emulator::LoadSystemModules(const std::filesystem::path& file) {
|
||||
const auto& sys_module_path = Common::FS::GetUserPath(Common::FS::PathType::SysModuleDir);
|
||||
for (const auto& entry : std::filesystem::directory_iterator(sys_module_path)) {
|
||||
if (entry.path().filename() == "libSceNgs2.sprx") {
|
||||
if (entry.path().filename() == "libSceNgs2.sprx" ||
|
||||
entry.path().filename() == "libSceLibcInternal.sprx") {
|
||||
LOG_INFO(Loader, "Loading {}", entry.path().string().c_str());
|
||||
linker->LoadModule(entry.path());
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <sys/mman.h>
|
||||
#include "common/assert.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/thread.h"
|
||||
|
@ -22,8 +23,6 @@ Liverpool::Liverpool() {
|
|||
|
||||
Liverpool::~Liverpool() {
|
||||
process_thread.request_stop();
|
||||
num_submits = -1;
|
||||
num_submits.notify_one();
|
||||
process_thread.join();
|
||||
}
|
||||
|
||||
|
@ -31,8 +30,10 @@ void Liverpool::Process(std::stop_token stoken) {
|
|||
Common::SetCurrentThreadName("GPU_CommandProcessor");
|
||||
|
||||
while (!stoken.stop_requested()) {
|
||||
num_submits.wait(0);
|
||||
|
||||
{
|
||||
std::unique_lock lk{submit_mutex};
|
||||
submit_cv.wait(lk, stoken, [this] { return num_submits != 0; });
|
||||
}
|
||||
if (stoken.stop_requested()) {
|
||||
break;
|
||||
}
|
||||
|
@ -67,7 +68,8 @@ void Liverpool::Process(std::stop_token stoken) {
|
|||
}
|
||||
|
||||
if (submit_done) {
|
||||
num_submits.notify_all();
|
||||
std::scoped_lock lk{submit_mutex};
|
||||
submit_cv.notify_all();
|
||||
submit_done = false;
|
||||
}
|
||||
}
|
||||
|
@ -76,9 +78,8 @@ void Liverpool::Process(std::stop_token stoken) {
|
|||
void Liverpool::WaitGpuIdle() {
|
||||
RENDERER_TRACE;
|
||||
|
||||
while (const auto old = num_submits.load()) {
|
||||
num_submits.wait(old);
|
||||
}
|
||||
std::unique_lock lk{submit_mutex};
|
||||
submit_cv.wait(lk, [this] { return num_submits == 0; });
|
||||
}
|
||||
|
||||
Liverpool::Task Liverpool::ProcessCeUpdate(std::span<const u32> ccb) {
|
||||
|
@ -369,7 +370,6 @@ Liverpool::Task Liverpool::ProcessGraphics(std::span<const u32> dcb, std::span<c
|
|||
UNREACHABLE_MSG("Unknown PM4 type 3 opcode {:#x} with count {}",
|
||||
static_cast<u32>(opcode), count);
|
||||
}
|
||||
|
||||
dcb = dcb.subspan(header->type3.NumWords() + 1);
|
||||
}
|
||||
|
||||
|
@ -415,8 +415,9 @@ void Liverpool::SubmitGfx(std::span<const u32> dcb, std::span<const u32> ccb) {
|
|||
queue.submits.emplace(task.handle);
|
||||
}
|
||||
|
||||
std::scoped_lock lk{submit_mutex};
|
||||
++num_submits;
|
||||
num_submits.notify_one();
|
||||
submit_cv.notify_one();
|
||||
}
|
||||
|
||||
void Liverpool::SubmitAsc(u32 vqid, std::span<const u32> acb) {
|
||||
|
@ -429,8 +430,9 @@ void Liverpool::SubmitAsc(u32 vqid, std::span<const u32> acb) {
|
|||
queue.submits.emplace(task.handle);
|
||||
}
|
||||
|
||||
std::scoped_lock lk{submit_mutex};
|
||||
++num_submits;
|
||||
num_submits.notify_one();
|
||||
submit_cv.notify_one();
|
||||
}
|
||||
|
||||
} // namespace AmdGpu
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "video_core/amdgpu/pixel_format.h"
|
||||
|
||||
#include <array>
|
||||
#include <condition_variable>
|
||||
#include <coroutine>
|
||||
#include <mutex>
|
||||
#include <span>
|
||||
|
@ -865,13 +866,15 @@ public:
|
|||
void SubmitAsc(u32 vqid, std::span<const u32> acb);
|
||||
|
||||
void WaitGpuIdle();
|
||||
|
||||
bool IsGpuIdle() const {
|
||||
return num_submits == 0;
|
||||
}
|
||||
|
||||
void NotifySubmitDone() {
|
||||
std::scoped_lock lk{submit_mutex};
|
||||
submit_done = true;
|
||||
num_submits.notify_all();
|
||||
submit_cv.notify_all();
|
||||
}
|
||||
|
||||
void BindRasterizer(Vulkan::Rasterizer* rasterizer_) {
|
||||
|
@ -939,7 +942,9 @@ private:
|
|||
|
||||
Vulkan::Rasterizer* rasterizer{};
|
||||
std::jthread process_thread{};
|
||||
std::atomic<u32> num_submits{};
|
||||
u32 num_submits{};
|
||||
std::mutex submit_mutex;
|
||||
std::condition_variable_any submit_cv;
|
||||
std::atomic<bool> submit_done{};
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue