mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-07-27 04:25:12 +00:00
Merge branch 'shadps4-emu:main' into main
This commit is contained in:
commit
e1a3c4cd74
@ -597,6 +597,8 @@ set(MISC_LIBS src/core/libraries/screenshot/screenshot.cpp
|
|||||||
src/core/libraries/move/move.h
|
src/core/libraries/move/move.h
|
||||||
src/core/libraries/ulobjmgr/ulobjmgr.cpp
|
src/core/libraries/ulobjmgr/ulobjmgr.cpp
|
||||||
src/core/libraries/ulobjmgr/ulobjmgr.h
|
src/core/libraries/ulobjmgr/ulobjmgr.h
|
||||||
|
src/core/libraries/signin_dialog/signindialog.cpp
|
||||||
|
src/core/libraries/signin_dialog/signindialog.h
|
||||||
)
|
)
|
||||||
|
|
||||||
set(DEV_TOOLS src/core/devtools/layer.cpp
|
set(DEV_TOOLS src/core/devtools/layer.cpp
|
||||||
|
@ -137,6 +137,7 @@ bool ParseFilterRule(Filter& instance, Iterator begin, Iterator end) {
|
|||||||
SUB(Lib, NpParty) \
|
SUB(Lib, NpParty) \
|
||||||
SUB(Lib, Zlib) \
|
SUB(Lib, Zlib) \
|
||||||
SUB(Lib, Hmd) \
|
SUB(Lib, Hmd) \
|
||||||
|
SUB(Lib, SigninDialog) \
|
||||||
CLS(Frontend) \
|
CLS(Frontend) \
|
||||||
CLS(Render) \
|
CLS(Render) \
|
||||||
SUB(Render, Vulkan) \
|
SUB(Render, Vulkan) \
|
||||||
|
@ -104,6 +104,7 @@ enum class Class : u8 {
|
|||||||
Lib_NpParty, ///< The LibSceNpParty implementation
|
Lib_NpParty, ///< The LibSceNpParty implementation
|
||||||
Lib_Zlib, ///< The LibSceZlib implementation.
|
Lib_Zlib, ///< The LibSceZlib implementation.
|
||||||
Lib_Hmd, ///< The LibSceHmd implementation.
|
Lib_Hmd, ///< The LibSceHmd implementation.
|
||||||
|
Lib_SigninDialog, ///< The LibSigninDialog implementation.
|
||||||
Frontend, ///< Emulator UI
|
Frontend, ///< Emulator UI
|
||||||
Render, ///< Video Core
|
Render, ///< Video Core
|
||||||
Render_Vulkan, ///< Vulkan backend
|
Render_Vulkan, ///< Vulkan backend
|
||||||
|
@ -464,9 +464,8 @@ static std::pair<bool, u64> TryPatch(u8* code, PatchModule* module) {
|
|||||||
|
|
||||||
if (needs_trampoline && instruction.length < 5) {
|
if (needs_trampoline && instruction.length < 5) {
|
||||||
// Trampoline is needed but instruction is too short to patch.
|
// Trampoline is needed but instruction is too short to patch.
|
||||||
// Return false and length to fall back to the illegal instruction handler,
|
// Return false and length to signal to AOT compilation that this instruction
|
||||||
// or to signal to AOT compilation that this instruction should be skipped and
|
// should be skipped and handled at runtime.
|
||||||
// handled at runtime.
|
|
||||||
return std::make_pair(false, instruction.length);
|
return std::make_pair(false, instruction.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -512,136 +511,137 @@ static std::pair<bool, u64> TryPatch(u8* code, PatchModule* module) {
|
|||||||
|
|
||||||
#if defined(ARCH_X86_64)
|
#if defined(ARCH_X86_64)
|
||||||
|
|
||||||
|
static bool Is4ByteExtrqOrInsertq(void* code_address) {
|
||||||
|
u8* bytes = (u8*)code_address;
|
||||||
|
if (bytes[0] == 0x66 && bytes[1] == 0x0F && bytes[2] == 0x79) {
|
||||||
|
return true; // extrq
|
||||||
|
} else if (bytes[0] == 0xF2 && bytes[1] == 0x0F && bytes[2] == 0x79) {
|
||||||
|
return true; // insertq
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static bool TryExecuteIllegalInstruction(void* ctx, void* code_address) {
|
static bool TryExecuteIllegalInstruction(void* ctx, void* code_address) {
|
||||||
ZydisDecodedInstruction instruction;
|
// We need to decode the instruction to find out what it is. Normally we'd use a fully fleshed
|
||||||
ZydisDecodedOperand operands[ZYDIS_MAX_OPERAND_COUNT];
|
// out decoder like Zydis, however Zydis does a bunch of stuff that impact performance that we
|
||||||
const auto status =
|
// don't care about. We can get information about the instruction a lot faster by writing a mini
|
||||||
Common::Decoder::Instance()->decodeInstruction(instruction, operands, code_address);
|
// decoder here, since we know it is definitely an extrq or an insertq. If for some reason we
|
||||||
|
// need to interpret more instructions in the future (I don't see why we would), we can revert
|
||||||
|
// to using Zydis.
|
||||||
|
ZydisMnemonic mnemonic;
|
||||||
|
u8* bytes = (u8*)code_address;
|
||||||
|
if (bytes[0] == 0x66) {
|
||||||
|
mnemonic = ZYDIS_MNEMONIC_EXTRQ;
|
||||||
|
} else if (bytes[0] == 0xF2) {
|
||||||
|
mnemonic = ZYDIS_MNEMONIC_INSERTQ;
|
||||||
|
} else {
|
||||||
|
ZydisDecodedInstruction instruction;
|
||||||
|
ZydisDecodedOperand operands[ZYDIS_MAX_OPERAND_COUNT];
|
||||||
|
const auto status =
|
||||||
|
Common::Decoder::Instance()->decodeInstruction(instruction, operands, code_address);
|
||||||
|
LOG_ERROR(Core, "Unhandled illegal instruction at code address {}: {}",
|
||||||
|
fmt::ptr(code_address),
|
||||||
|
ZYAN_SUCCESS(status) ? ZydisMnemonicGetString(instruction.mnemonic)
|
||||||
|
: "Failed to decode");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
switch (instruction.mnemonic) {
|
ASSERT(bytes[1] == 0x0F && bytes[2] == 0x79);
|
||||||
|
|
||||||
|
// Note: It's guaranteed that there's no REX prefix in these instructions checked by
|
||||||
|
// Is4ByteExtrqOrInsertq
|
||||||
|
u8 modrm = bytes[3];
|
||||||
|
u8 rm = modrm & 0b111;
|
||||||
|
u8 reg = (modrm >> 3) & 0b111;
|
||||||
|
u8 mod = (modrm >> 6) & 0b11;
|
||||||
|
|
||||||
|
ASSERT(mod == 0b11); // Any instruction we interpret here uses reg/reg addressing only
|
||||||
|
|
||||||
|
int dstIndex = reg;
|
||||||
|
int srcIndex = rm;
|
||||||
|
|
||||||
|
switch (mnemonic) {
|
||||||
case ZYDIS_MNEMONIC_EXTRQ: {
|
case ZYDIS_MNEMONIC_EXTRQ: {
|
||||||
bool immediateForm = operands[1].type == ZYDIS_OPERAND_TYPE_IMMEDIATE &&
|
const auto dst = Common::GetXmmPointer(ctx, dstIndex);
|
||||||
operands[2].type == ZYDIS_OPERAND_TYPE_IMMEDIATE;
|
const auto src = Common::GetXmmPointer(ctx, srcIndex);
|
||||||
if (immediateForm) {
|
|
||||||
LOG_CRITICAL(Core, "EXTRQ immediate form should have been patched at code address: {}",
|
u64 lowQWordSrc;
|
||||||
fmt::ptr(code_address));
|
memcpy(&lowQWordSrc, src, sizeof(lowQWordSrc));
|
||||||
return false;
|
|
||||||
|
u64 lowQWordDst;
|
||||||
|
memcpy(&lowQWordDst, dst, sizeof(lowQWordDst));
|
||||||
|
|
||||||
|
u64 length = lowQWordSrc & 0x3F;
|
||||||
|
u64 mask;
|
||||||
|
if (length == 0) {
|
||||||
|
length = 64; // for the check below
|
||||||
|
mask = 0xFFFF'FFFF'FFFF'FFFF;
|
||||||
} else {
|
} else {
|
||||||
ASSERT_MSG(operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER &&
|
mask = (1ULL << length) - 1;
|
||||||
operands[1].type == ZYDIS_OPERAND_TYPE_REGISTER &&
|
|
||||||
operands[0].reg.value >= ZYDIS_REGISTER_XMM0 &&
|
|
||||||
operands[0].reg.value <= ZYDIS_REGISTER_XMM15 &&
|
|
||||||
operands[1].reg.value >= ZYDIS_REGISTER_XMM0 &&
|
|
||||||
operands[1].reg.value <= ZYDIS_REGISTER_XMM15,
|
|
||||||
"Unexpected operand types for EXTRQ instruction");
|
|
||||||
|
|
||||||
const auto dstIndex = operands[0].reg.value - ZYDIS_REGISTER_XMM0;
|
|
||||||
const auto srcIndex = operands[1].reg.value - ZYDIS_REGISTER_XMM0;
|
|
||||||
|
|
||||||
const auto dst = Common::GetXmmPointer(ctx, dstIndex);
|
|
||||||
const auto src = Common::GetXmmPointer(ctx, srcIndex);
|
|
||||||
|
|
||||||
u64 lowQWordSrc;
|
|
||||||
memcpy(&lowQWordSrc, src, sizeof(lowQWordSrc));
|
|
||||||
|
|
||||||
u64 lowQWordDst;
|
|
||||||
memcpy(&lowQWordDst, dst, sizeof(lowQWordDst));
|
|
||||||
|
|
||||||
u64 length = lowQWordSrc & 0x3F;
|
|
||||||
u64 mask;
|
|
||||||
if (length == 0) {
|
|
||||||
length = 64; // for the check below
|
|
||||||
mask = 0xFFFF'FFFF'FFFF'FFFF;
|
|
||||||
} else {
|
|
||||||
mask = (1ULL << length) - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
u64 index = (lowQWordSrc >> 8) & 0x3F;
|
|
||||||
if (length + index > 64) {
|
|
||||||
// Undefined behavior if length + index is bigger than 64 according to the spec,
|
|
||||||
// we'll warn and continue execution.
|
|
||||||
LOG_TRACE(Core,
|
|
||||||
"extrq at {} with length {} and index {} is bigger than 64, "
|
|
||||||
"undefined behavior",
|
|
||||||
fmt::ptr(code_address), length, index);
|
|
||||||
}
|
|
||||||
|
|
||||||
lowQWordDst >>= index;
|
|
||||||
lowQWordDst &= mask;
|
|
||||||
|
|
||||||
memcpy(dst, &lowQWordDst, sizeof(lowQWordDst));
|
|
||||||
|
|
||||||
Common::IncrementRip(ctx, instruction.length);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
|
u64 index = (lowQWordSrc >> 8) & 0x3F;
|
||||||
|
if (length + index > 64) {
|
||||||
|
// Undefined behavior if length + index is bigger than 64 according to the spec,
|
||||||
|
// we'll warn and continue execution.
|
||||||
|
LOG_TRACE(Core,
|
||||||
|
"extrq at {} with length {} and index {} is bigger than 64, "
|
||||||
|
"undefined behavior",
|
||||||
|
fmt::ptr(code_address), length, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
lowQWordDst >>= index;
|
||||||
|
lowQWordDst &= mask;
|
||||||
|
|
||||||
|
memcpy(dst, &lowQWordDst, sizeof(lowQWordDst));
|
||||||
|
|
||||||
|
Common::IncrementRip(ctx, 4);
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
case ZYDIS_MNEMONIC_INSERTQ: {
|
case ZYDIS_MNEMONIC_INSERTQ: {
|
||||||
bool immediateForm = operands[2].type == ZYDIS_OPERAND_TYPE_IMMEDIATE &&
|
const auto dst = Common::GetXmmPointer(ctx, dstIndex);
|
||||||
operands[3].type == ZYDIS_OPERAND_TYPE_IMMEDIATE;
|
const auto src = Common::GetXmmPointer(ctx, srcIndex);
|
||||||
if (immediateForm) {
|
|
||||||
LOG_CRITICAL(Core,
|
u64 lowQWordSrc, highQWordSrc;
|
||||||
"INSERTQ immediate form should have been patched at code address: {}",
|
memcpy(&lowQWordSrc, src, sizeof(lowQWordSrc));
|
||||||
fmt::ptr(code_address));
|
memcpy(&highQWordSrc, (u8*)src + 8, sizeof(highQWordSrc));
|
||||||
return false;
|
|
||||||
|
u64 lowQWordDst;
|
||||||
|
memcpy(&lowQWordDst, dst, sizeof(lowQWordDst));
|
||||||
|
|
||||||
|
u64 length = highQWordSrc & 0x3F;
|
||||||
|
u64 mask;
|
||||||
|
if (length == 0) {
|
||||||
|
length = 64; // for the check below
|
||||||
|
mask = 0xFFFF'FFFF'FFFF'FFFF;
|
||||||
} else {
|
} else {
|
||||||
ASSERT_MSG(operands[2].type == ZYDIS_OPERAND_TYPE_UNUSED &&
|
mask = (1ULL << length) - 1;
|
||||||
operands[3].type == ZYDIS_OPERAND_TYPE_UNUSED,
|
|
||||||
"operands 2 and 3 must be unused for register form.");
|
|
||||||
|
|
||||||
ASSERT_MSG(operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER &&
|
|
||||||
operands[1].type == ZYDIS_OPERAND_TYPE_REGISTER,
|
|
||||||
"operands 0 and 1 must be registers.");
|
|
||||||
|
|
||||||
const auto dstIndex = operands[0].reg.value - ZYDIS_REGISTER_XMM0;
|
|
||||||
const auto srcIndex = operands[1].reg.value - ZYDIS_REGISTER_XMM0;
|
|
||||||
|
|
||||||
const auto dst = Common::GetXmmPointer(ctx, dstIndex);
|
|
||||||
const auto src = Common::GetXmmPointer(ctx, srcIndex);
|
|
||||||
|
|
||||||
u64 lowQWordSrc, highQWordSrc;
|
|
||||||
memcpy(&lowQWordSrc, src, sizeof(lowQWordSrc));
|
|
||||||
memcpy(&highQWordSrc, (u8*)src + 8, sizeof(highQWordSrc));
|
|
||||||
|
|
||||||
u64 lowQWordDst;
|
|
||||||
memcpy(&lowQWordDst, dst, sizeof(lowQWordDst));
|
|
||||||
|
|
||||||
u64 length = highQWordSrc & 0x3F;
|
|
||||||
u64 mask;
|
|
||||||
if (length == 0) {
|
|
||||||
length = 64; // for the check below
|
|
||||||
mask = 0xFFFF'FFFF'FFFF'FFFF;
|
|
||||||
} else {
|
|
||||||
mask = (1ULL << length) - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
u64 index = (highQWordSrc >> 8) & 0x3F;
|
|
||||||
if (length + index > 64) {
|
|
||||||
// Undefined behavior if length + index is bigger than 64 according to the spec,
|
|
||||||
// we'll warn and continue execution.
|
|
||||||
LOG_TRACE(Core,
|
|
||||||
"insertq at {} with length {} and index {} is bigger than 64, "
|
|
||||||
"undefined behavior",
|
|
||||||
fmt::ptr(code_address), length, index);
|
|
||||||
}
|
|
||||||
|
|
||||||
lowQWordSrc &= mask;
|
|
||||||
lowQWordDst &= ~(mask << index);
|
|
||||||
lowQWordDst |= lowQWordSrc << index;
|
|
||||||
|
|
||||||
memcpy(dst, &lowQWordDst, sizeof(lowQWordDst));
|
|
||||||
|
|
||||||
Common::IncrementRip(ctx, instruction.length);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
|
u64 index = (highQWordSrc >> 8) & 0x3F;
|
||||||
|
if (length + index > 64) {
|
||||||
|
// Undefined behavior if length + index is bigger than 64 according to the spec,
|
||||||
|
// we'll warn and continue execution.
|
||||||
|
LOG_TRACE(Core,
|
||||||
|
"insertq at {} with length {} and index {} is bigger than 64, "
|
||||||
|
"undefined behavior",
|
||||||
|
fmt::ptr(code_address), length, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
lowQWordSrc &= mask;
|
||||||
|
lowQWordDst &= ~(mask << index);
|
||||||
|
lowQWordDst |= lowQWordSrc << index;
|
||||||
|
|
||||||
|
memcpy(dst, &lowQWordDst, sizeof(lowQWordDst));
|
||||||
|
|
||||||
|
Common::IncrementRip(ctx, 4);
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
LOG_ERROR(Core, "Unhandled illegal instruction at code address {}: {}",
|
UNREACHABLE();
|
||||||
fmt::ptr(code_address), ZydisMnemonicGetString(instruction.mnemonic));
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -695,9 +695,22 @@ static bool PatchesAccessViolationHandler(void* context, void* /* fault_address
|
|||||||
|
|
||||||
static bool PatchesIllegalInstructionHandler(void* context) {
|
static bool PatchesIllegalInstructionHandler(void* context) {
|
||||||
void* code_address = Common::GetRip(context);
|
void* code_address = Common::GetRip(context);
|
||||||
if (!TryPatchJit(code_address)) {
|
if (Is4ByteExtrqOrInsertq(code_address)) {
|
||||||
|
// The instruction is not big enough for a relative jump, don't try to patch it and pass it
|
||||||
|
// to our illegal instruction interpreter directly
|
||||||
return TryExecuteIllegalInstruction(context, code_address);
|
return TryExecuteIllegalInstruction(context, code_address);
|
||||||
|
} else {
|
||||||
|
if (!TryPatchJit(code_address)) {
|
||||||
|
ZydisDecodedInstruction instruction;
|
||||||
|
ZydisDecodedOperand operands[ZYDIS_MAX_OPERAND_COUNT];
|
||||||
|
const auto status =
|
||||||
|
Common::Decoder::Instance()->decodeInstruction(instruction, operands, code_address);
|
||||||
|
LOG_ERROR(Core, "Failed to patch address {:x} -- mnemonic: {}", (u64)code_address,
|
||||||
|
ZYAN_SUCCESS(status) ? ZydisMnemonicGetString(instruction.mnemonic)
|
||||||
|
: "Failed to decode");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -289,7 +289,12 @@ int PS4_SYSV_ABI posix_pthread_create_name_np(PthreadT* thread, const PthreadAtt
|
|||||||
/* Create thread */
|
/* Create thread */
|
||||||
new_thread->native_thr = Core::NativeThread();
|
new_thread->native_thr = Core::NativeThread();
|
||||||
int ret = new_thread->native_thr.Create(RunThread, new_thread, &new_thread->attr);
|
int ret = new_thread->native_thr.Create(RunThread, new_thread, &new_thread->attr);
|
||||||
|
|
||||||
ASSERT_MSG(ret == 0, "Failed to create thread with error {}", ret);
|
ASSERT_MSG(ret == 0, "Failed to create thread with error {}", ret);
|
||||||
|
|
||||||
|
if (attr != nullptr && *attr != nullptr && (*attr)->cpuset != nullptr) {
|
||||||
|
new_thread->SetAffinity((*attr)->cpuset);
|
||||||
|
}
|
||||||
if (ret) {
|
if (ret) {
|
||||||
*thread = nullptr;
|
*thread = nullptr;
|
||||||
}
|
}
|
||||||
@ -521,6 +526,69 @@ int PS4_SYSV_ABI posix_pthread_setcancelstate(PthreadCancelState state,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Pthread::SetAffinity(const Cpuset* cpuset) {
|
||||||
|
const auto processor_count = std::thread::hardware_concurrency();
|
||||||
|
if (processor_count < 8) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (cpuset == nullptr) {
|
||||||
|
return POSIX_EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 mask = cpuset->bits;
|
||||||
|
|
||||||
|
uintptr_t handle = native_thr.GetHandle();
|
||||||
|
if (handle == 0) {
|
||||||
|
return POSIX_ESRCH;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We don't use this currently because some games gets performance problems
|
||||||
|
// when applying affinity even on strong hardware
|
||||||
|
/*
|
||||||
|
#ifdef _WIN64
|
||||||
|
DWORD_PTR affinity_mask = static_cast<DWORD_PTR>(mask);
|
||||||
|
if (!SetThreadAffinityMask(reinterpret_cast<HANDLE>(handle), affinity_mask)) {
|
||||||
|
return POSIX_EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined(__linux__)
|
||||||
|
cpu_set_t cpu_set;
|
||||||
|
CPU_ZERO(&cpu_set);
|
||||||
|
|
||||||
|
u64 mask = cpuset->bits;
|
||||||
|
for (int cpu = 0; cpu < std::min(64, CPU_SETSIZE); ++cpu) {
|
||||||
|
if (mask & (1ULL << cpu)) {
|
||||||
|
CPU_SET(cpu, &cpu_set);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int result =
|
||||||
|
pthread_setaffinity_np(static_cast<pthread_t>(handle), sizeof(cpu_set_t), &cpu_set);
|
||||||
|
if (result != 0) {
|
||||||
|
return POSIX_EINVAL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
*/
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int PS4_SYSV_ABI posix_pthread_setaffinity_np(PthreadT thread, size_t cpusetsize,
|
||||||
|
const Cpuset* cpusetp) {
|
||||||
|
if (thread == nullptr || cpusetp == nullptr) {
|
||||||
|
return POSIX_EINVAL;
|
||||||
|
}
|
||||||
|
thread->attr.cpusetsize = 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;
|
||||||
|
}
|
||||||
|
|
||||||
void RegisterThread(Core::Loader::SymbolsResolver* sym) {
|
void RegisterThread(Core::Loader::SymbolsResolver* sym) {
|
||||||
// Posix
|
// Posix
|
||||||
LIB_FUNCTION("Z4QosVuAsA0", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_once);
|
LIB_FUNCTION("Z4QosVuAsA0", "libScePosix", 1, "libkernel", 1, 1, posix_pthread_once);
|
||||||
@ -544,6 +612,7 @@ void RegisterThread(Core::Loader::SymbolsResolver* sym) {
|
|||||||
LIB_FUNCTION("Z4QosVuAsA0", "libkernel", 1, "libkernel", 1, 1, posix_pthread_once);
|
LIB_FUNCTION("Z4QosVuAsA0", "libkernel", 1, "libkernel", 1, 1, posix_pthread_once);
|
||||||
LIB_FUNCTION("EotR8a3ASf4", "libkernel", 1, "libkernel", 1, 1, posix_pthread_self);
|
LIB_FUNCTION("EotR8a3ASf4", "libkernel", 1, "libkernel", 1, 1, posix_pthread_self);
|
||||||
LIB_FUNCTION("OxhIB8LB-PQ", "libkernel", 1, "libkernel", 1, 1, posix_pthread_create);
|
LIB_FUNCTION("OxhIB8LB-PQ", "libkernel", 1, "libkernel", 1, 1, posix_pthread_create);
|
||||||
|
LIB_FUNCTION("5KWrg7-ZqvE", "libkernel", 1, "libkernel", 1, 1, posix_pthread_setaffinity_np);
|
||||||
|
|
||||||
// Orbis
|
// Orbis
|
||||||
LIB_FUNCTION("14bOACANTBo", "libkernel", 1, "libkernel", 1, 1, ORBIS(posix_pthread_once));
|
LIB_FUNCTION("14bOACANTBo", "libkernel", 1, "libkernel", 1, 1, ORBIS(posix_pthread_once));
|
||||||
@ -566,6 +635,7 @@ void RegisterThread(Core::Loader::SymbolsResolver* sym) {
|
|||||||
LIB_FUNCTION("W0Hpm2X0uPE", "libkernel", 1, "libkernel", 1, 1, ORBIS(posix_pthread_setprio));
|
LIB_FUNCTION("W0Hpm2X0uPE", "libkernel", 1, "libkernel", 1, 1, ORBIS(posix_pthread_setprio));
|
||||||
LIB_FUNCTION("rNhWz+lvOMU", "libkernel", 1, "libkernel", 1, 1, _sceKernelSetThreadDtors);
|
LIB_FUNCTION("rNhWz+lvOMU", "libkernel", 1, "libkernel", 1, 1, _sceKernelSetThreadDtors);
|
||||||
LIB_FUNCTION("6XG4B33N09g", "libkernel", 1, "libkernel", 1, 1, sched_yield);
|
LIB_FUNCTION("6XG4B33N09g", "libkernel", 1, "libkernel", 1, 1, sched_yield);
|
||||||
|
LIB_FUNCTION("bt3CTBKmGyI", "libkernel", 1, "libkernel", 1, 1, scePthreadSetaffinity)
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Libraries::Kernel
|
} // namespace Libraries::Kernel
|
||||||
|
@ -332,6 +332,8 @@ struct Pthread {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int SetAffinity(const Cpuset* cpuset);
|
||||||
};
|
};
|
||||||
using PthreadT = Pthread*;
|
using PthreadT = Pthread*;
|
||||||
|
|
||||||
|
@ -56,7 +56,6 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include <cstdarg>
|
#include <cstdarg>
|
||||||
#include <cstdbool>
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
@ -45,6 +45,7 @@
|
|||||||
#include "core/libraries/save_data/savedata.h"
|
#include "core/libraries/save_data/savedata.h"
|
||||||
#include "core/libraries/screenshot/screenshot.h"
|
#include "core/libraries/screenshot/screenshot.h"
|
||||||
#include "core/libraries/share_play/shareplay.h"
|
#include "core/libraries/share_play/shareplay.h"
|
||||||
|
#include "core/libraries/signin_dialog/signindialog.h"
|
||||||
#include "core/libraries/system/commondialog.h"
|
#include "core/libraries/system/commondialog.h"
|
||||||
#include "core/libraries/system/msgdialog.h"
|
#include "core/libraries/system/msgdialog.h"
|
||||||
#include "core/libraries/system/posix.h"
|
#include "core/libraries/system/posix.h"
|
||||||
@ -120,6 +121,7 @@ void InitHLELibs(Core::Loader::SymbolsResolver* sym) {
|
|||||||
Libraries::Hmd::RegisterlibSceHmd(sym);
|
Libraries::Hmd::RegisterlibSceHmd(sym);
|
||||||
Libraries::DiscMap::RegisterlibSceDiscMap(sym);
|
Libraries::DiscMap::RegisterlibSceDiscMap(sym);
|
||||||
Libraries::Ulobjmgr::RegisterlibSceUlobjmgr(sym);
|
Libraries::Ulobjmgr::RegisterlibSceUlobjmgr(sym);
|
||||||
|
Libraries::SigninDialog::RegisterlibSceSigninDialog(sym);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Libraries
|
} // namespace Libraries
|
||||||
|
64
src/core/libraries/signin_dialog/signindialog.cpp
Normal file
64
src/core/libraries/signin_dialog/signindialog.cpp
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
// Generated By moduleGenerator
|
||||||
|
#include "common/logging/log.h"
|
||||||
|
#include "core/libraries/error_codes.h"
|
||||||
|
#include "core/libraries/libs.h"
|
||||||
|
#include "signindialog.h"
|
||||||
|
|
||||||
|
namespace Libraries::SigninDialog {
|
||||||
|
|
||||||
|
s32 PS4_SYSV_ABI sceSigninDialogInitialize() {
|
||||||
|
LOG_ERROR(Lib_SigninDialog, "(STUBBED) called");
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 PS4_SYSV_ABI sceSigninDialogOpen() {
|
||||||
|
LOG_ERROR(Lib_SigninDialog, "(STUBBED) called");
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status PS4_SYSV_ABI sceSigninDialogGetStatus() {
|
||||||
|
LOG_ERROR(Lib_SigninDialog, "(STUBBED) called, return 'finished' status");
|
||||||
|
return Status::FINISHED;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status PS4_SYSV_ABI sceSigninDialogUpdateStatus() {
|
||||||
|
LOG_ERROR(Lib_SigninDialog, "(STUBBED) called, return 'finished' status");
|
||||||
|
return Status::FINISHED;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 PS4_SYSV_ABI sceSigninDialogGetResult() {
|
||||||
|
LOG_ERROR(Lib_SigninDialog, "(STUBBED) called");
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 PS4_SYSV_ABI sceSigninDialogClose() {
|
||||||
|
LOG_ERROR(Lib_SigninDialog, "(STUBBED) called");
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 PS4_SYSV_ABI sceSigninDialogTerminate() {
|
||||||
|
LOG_ERROR(Lib_SigninDialog, "(STUBBED) called");
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegisterlibSceSigninDialog(Core::Loader::SymbolsResolver* sym) {
|
||||||
|
LIB_FUNCTION("mlYGfmqE3fQ", "libSceSigninDialog", 1, "libSceSigninDialog", 1, 1,
|
||||||
|
sceSigninDialogInitialize);
|
||||||
|
LIB_FUNCTION("JlpJVoRWv7U", "libSceSigninDialog", 1, "libSceSigninDialog", 1, 1,
|
||||||
|
sceSigninDialogOpen);
|
||||||
|
LIB_FUNCTION("2m077aeC+PA", "libSceSigninDialog", 1, "libSceSigninDialog", 1, 1,
|
||||||
|
sceSigninDialogGetStatus);
|
||||||
|
LIB_FUNCTION("Bw31liTFT3A", "libSceSigninDialog", 1, "libSceSigninDialog", 1, 1,
|
||||||
|
sceSigninDialogUpdateStatus);
|
||||||
|
LIB_FUNCTION("nqG7rqnYw1U", "libSceSigninDialog", 1, "libSceSigninDialog", 1, 1,
|
||||||
|
sceSigninDialogGetResult);
|
||||||
|
LIB_FUNCTION("M3OkENHcyiU", "libSceSigninDialog", 1, "libSceSigninDialog", 1, 1,
|
||||||
|
sceSigninDialogClose);
|
||||||
|
LIB_FUNCTION("LXlmS6PvJdU", "libSceSigninDialog", 1, "libSceSigninDialog", 1, 1,
|
||||||
|
sceSigninDialogTerminate);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Libraries::SigninDialog
|
29
src/core/libraries/signin_dialog/signindialog.h
Normal file
29
src/core/libraries/signin_dialog/signindialog.h
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "common/types.h"
|
||||||
|
|
||||||
|
namespace Core::Loader {
|
||||||
|
class SymbolsResolver;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class Status : u32 {
|
||||||
|
NONE = 0,
|
||||||
|
INITIALIZED = 1,
|
||||||
|
RUNNING = 2,
|
||||||
|
FINISHED = 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace Libraries::SigninDialog {
|
||||||
|
|
||||||
|
s32 PS4_SYSV_ABI sceSigninDialogInitialize();
|
||||||
|
s32 PS4_SYSV_ABI sceSigninDialogOpen();
|
||||||
|
Status PS4_SYSV_ABI sceSigninDialogGetStatus();
|
||||||
|
Status PS4_SYSV_ABI sceSigninDialogUpdateStatus();
|
||||||
|
s32 PS4_SYSV_ABI sceSigninDialogGetResult();
|
||||||
|
s32 PS4_SYSV_ABI sceSigninDialogClose();
|
||||||
|
s32 PS4_SYSV_ABI sceSigninDialogTerminate();
|
||||||
|
|
||||||
|
void RegisterlibSceSigninDialog(Core::Loader::SymbolsResolver* sym);
|
||||||
|
} // namespace Libraries::SigninDialog
|
@ -5,6 +5,8 @@
|
|||||||
|
|
||||||
#include "common/types.h"
|
#include "common/types.h"
|
||||||
|
|
||||||
|
void* memset(void* ptr, int value, size_t num);
|
||||||
|
|
||||||
namespace Xbyak {
|
namespace Xbyak {
|
||||||
class CodeGenerator;
|
class CodeGenerator;
|
||||||
}
|
}
|
||||||
@ -41,9 +43,18 @@ Tcb* GetTcbBase();
|
|||||||
/// Makes sure TLS is initialized for the thread before entering guest.
|
/// Makes sure TLS is initialized for the thread before entering guest.
|
||||||
void EnsureThreadInitialized();
|
void EnsureThreadInitialized();
|
||||||
|
|
||||||
|
template <size_t size>
|
||||||
|
__attribute__((optnone)) void ClearStack() {
|
||||||
|
volatile void* buf = alloca(size);
|
||||||
|
memset(const_cast<void*>(buf), 0, size);
|
||||||
|
buf = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
template <class ReturnType, class... FuncArgs, class... CallArgs>
|
template <class ReturnType, class... FuncArgs, class... CallArgs>
|
||||||
ReturnType ExecuteGuest(PS4_SYSV_ABI ReturnType (*func)(FuncArgs...), CallArgs&&... args) {
|
ReturnType ExecuteGuest(PS4_SYSV_ABI ReturnType (*func)(FuncArgs...), CallArgs&&... args) {
|
||||||
EnsureThreadInitialized();
|
EnsureThreadInitialized();
|
||||||
|
// clear stack to avoid trash from EnsureThreadInitialized
|
||||||
|
ClearStack<13_KB>();
|
||||||
return func(std::forward<CallArgs>(args)...);
|
return func(std::forward<CallArgs>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user