diff --git a/src/core/hle/libraries/libkernel/libkernel.cpp b/src/core/hle/libraries/libkernel/libkernel.cpp index 8435ce5d6..ee60d2766 100644 --- a/src/core/hle/libraries/libkernel/libkernel.cpp +++ b/src/core/hle/libraries/libkernel/libkernel.cpp @@ -37,6 +37,23 @@ int PS4_SYSV_ABI sceKernelMunmap(void* addr, size_t len) { return SCE_OK; } +void PS4_SYSV_ABI sceKernelUsleep(unsigned int microseconds) { + std::this_thread::sleep_for(std::chrono::microseconds(microseconds)); +} + +struct iovec { + void* iov_base; /* Base address. */ + size_t iov_len; /* Length. */ +}; + +size_t PS4_SYSV_ABI _writev(int fd, const struct iovec* iov, int iovcn) { + size_t total_written = 0; + for (int i = 0; i < iovcn; i++) { + total_written += ::fwrite(iov[i].iov_base, 1, iov[i].iov_len, stdout); + } + return total_written; +} + static thread_local int libc_error; int* PS4_SYSV_ABI __Error() { return &libc_error; } @@ -105,6 +122,8 @@ void LibKernel_Register(Loader::SymbolsResolver* sym) { LIB_FUNCTION("Ou3iL1abvng", "libkernel", 1, "libkernel", 1, 1, stack_chk_fail); LIB_FUNCTION("9BcDykPmo1I", "libkernel", 1, "libkernel", 1, 1, __Error); LIB_FUNCTION("BPE9s9vQQXo", "libkernel", 1, "libkernel", 1, 1, posix_mmap); + LIB_FUNCTION("1jfXLRVzisc", "libkernel", 1, "libkernel", 1, 1, sceKernelUsleep); + LIB_FUNCTION("YSHRBRLn2pI", "libkernel", 1, "libkernel", 1, 1, _writev); Core::Libraries::LibKernel::fileSystemSymbolsRegister(sym); Core::Libraries::LibKernel::timeSymbolsRegister(sym); diff --git a/src/core/linker.cpp b/src/core/linker.cpp index 77094b70c..813499690 100644 --- a/src/core/linker.cpp +++ b/src/core/linker.cpp @@ -7,6 +7,7 @@ #include "core/hle/libraries/libkernel/thread_management.h" #include "core/linker.h" #include "core/virtual_memory.h" +#include namespace Core { @@ -622,6 +623,31 @@ void Linker::Resolve(const std::string& name, int Symtype, Module* m, Loader::Sy } +static thread_local void* tls_block_top; + +// this assumes TLS will do mov rax|rcx, fs:[0] and +// that fs:[0] will be a nullptr in windows (seems to be so) +// and, that fs:[0] points to the top of the static TLS +static LONG CALLBACK ExceptionHandlerTLS(PEXCEPTION_POINTERS ExceptionInfo) { + static const uint8_t rax_fs0_deref[] = {0x64, 0x48, 0x8B, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00}; + + static const uint8_t rcx_fs0_deref[] = {0x64, 0x48, 0x8B, 0x0C, 0x25, 0x00, 0x00, 0x00, 0x00}; + + if (memcmp((void*)ExceptionInfo->ContextRecord->Rip, rax_fs0_deref, sizeof(rax_fs0_deref)) == 0) { + ExceptionInfo->ContextRecord->Rip += sizeof(rax_fs0_deref); + ExceptionInfo->ContextRecord->Rax = *(DWORD64*)tls_block_top; + + return EXCEPTION_CONTINUE_EXECUTION; + } else if (memcmp((void*)ExceptionInfo->ContextRecord->Rip, rcx_fs0_deref, sizeof(rcx_fs0_deref)) == 0) { + ExceptionInfo->ContextRecord->Rip += sizeof(rcx_fs0_deref); + ExceptionInfo->ContextRecord->Rcx = *(DWORD64*)tls_block_top; + + return EXCEPTION_CONTINUE_EXECUTION; + } + + return EXCEPTION_CONTINUE_SEARCH; +} + using exit_func_t = PS4_SYSV_ABI void (*)(); using entry_func_t = PS4_SYSV_ABI void (*)(EntryParams* params, exit_func_t atexit_func); @@ -632,6 +658,11 @@ static PS4_SYSV_ABI void ProgramExitFunc() { static void run_main_entry(u64 addr, EntryParams* params, exit_func_t exit_func) { //reinterpret_cast(addr)(params, exit_func); // can't be used, stack has to have a specific layout + void** tls_block = (void**)malloc(16); // this assumes 8 bytes of TLS storage, with the top of TLS pointing to itself + tls_block_top = tls_block[1] = &tls_block[1]; + + AddVectoredExceptionHandler(TRUE, ExceptionHandlerTLS); + asm volatile ( "andq $-16, %%rsp\n"// Align to 16 bytes "subq $8, %%rsp\n" // videoout_basic expects the stack to be misaligned diff --git a/src/main.cpp b/src/main.cpp index d9d56865b..7d2839917 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -16,13 +17,12 @@ #include "core/linker.h" #include "emuTimer.h" #include "emulator.h" -#include int main(int argc, char* argv[]) { - if (argc == 1) { + /* if (argc == 1) { fmt::print("Usage: {} \n", argv[0]); return -1; - } + }*/ Config::load("config.toml"); Common::Log::Init(true); Core::Libraries::LibKernel::init_pthreads(); @@ -33,7 +33,12 @@ int main(int argc, char* argv[]) { Emulator::emuTimer::start(); // Argument 1 is the path of self file to boot - const char* const path = argv[1]; + // const char* const path = argv[1]; + // const char* const path = "C:\\ps4\\homebrew\\openbor\\eboot.bin"; + // const char* const path = "C:\\ps4\\ps4sdk\\simplet-single-triangle_debug.elf"; + // const char* const path = "C:\\ps4\\ps4sdk\\videoout_cursor.elf"; + // const char* const path = "C:\\ps4\\games\\UnderTale\\eboot.bin"; + const char* const path = "C:\\ps4\\openorbis\\HelloWorld\\eboot.bin"; auto linker = Common::Singleton::Instance(); Core::Libraries::InitHLELibs(&linker->getHLESymbols());