diff --git a/.gitignore b/.gitignore index 163a277f..80a62d22 100644 --- a/.gitignore +++ b/.gitignore @@ -31,6 +31,7 @@ bld/ [Oo]bj/ [Ll]og/ [Ll]ogs/ +[Bb]uild/ # Visual Studio 2015/2017 cache/options directory .vs/ diff --git a/.gitmodules b/.gitmodules index 6d4a8197..532659db 100644 --- a/.gitmodules +++ b/.gitmodules @@ -22,3 +22,7 @@ path = third-party/zydis url = https://github.com/zyantific/zydis.git shallow = true +[submodule "third-party/winpthread"] + path = third-party/winpthread + url = https://github.com/shadps4/winpthread.git + branch = main diff --git a/CMakeLists.txt b/CMakeLists.txt index 33ae2b02..d6acb9db 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,8 +15,8 @@ include_directories(third-party/sdl/) include_directories(third-party/fmt/include) include_directories(third-party/magic_enum/include) include_directories(third-party/zydis/include/Zydis) +include_directories(third-party/winpthread/include) add_subdirectory("third-party") - #=================== EXAMPLE =================== add_executable(shadps4 @@ -34,13 +34,15 @@ add_executable(shadps4 src/Core/Memory.h src/Core/PS4/Linker.cpp src/Core/PS4/Linker.h - "src/Util/Singleton.h" "src/Util/Disassembler.cpp" "src/Util/Disassembler.h" "src/Util/StringUtil.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/Util/Singleton.h" "src/Util/Disassembler.cpp" "src/Util/Disassembler.h" "src/Util/StringUtil.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") find_package(OpenGL REQUIRED) - target_link_libraries(shadps4 PUBLIC fmt spdlog IMGUI SDL3-shared ${OPENGL_LIBRARY}) add_custom_command(TARGET shadps4 POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different $ $) +add_custom_command(TARGET shadps4 POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different + "${PROJECT_SOURCE_DIR}/third-party/winpthread/bin/libwinpthread-1.dll" $) diff --git a/src/Core/PS4/HLE/ErrorCodes.h b/src/Core/PS4/HLE/ErrorCodes.h new file mode 100644 index 00000000..5ff20660 --- /dev/null +++ b/src/Core/PS4/HLE/ErrorCodes.h @@ -0,0 +1,5 @@ +#pragma once +constexpr int SCE_OK = 0; + +constexpr int SCE_KERNEL_ERROR_ENOMEM = 0x8002000c;//Insufficient memory +constexpr int SCE_KERNEL_ERROR_EINVAL = 0x80020016;//null or invalid states diff --git a/src/Core/PS4/HLE/Kernel/ThreadManagement.cpp b/src/Core/PS4/HLE/Kernel/ThreadManagement.cpp new file mode 100644 index 00000000..31a380da --- /dev/null +++ b/src/Core/PS4/HLE/Kernel/ThreadManagement.cpp @@ -0,0 +1,131 @@ +#include "ThreadManagement.h" +#include "../ErrorCodes.h" + +namespace HLE::Libs::LibKernel::ThreadManagement +{ + +thread_local PthreadInternal* g_pthread_self = nullptr; +PThreadCxt* g_pthread_cxt = nullptr; + + +void Pthread_Init_Self_MainThread() { + g_pthread_self = new PthreadInternal{}; + scePthreadAttrInit(&g_pthread_self->attr); + g_pthread_self->pth = pthread_self(); + g_pthread_self->name = "Main_Thread"; +} + +int scePthreadAttrInit(ScePthreadAttr* attr) { + + *attr = new PthreadAttrInternal{}; + + int result = pthread_attr_init(&(*attr)->pth_attr); + + (*attr)->affinity = 0x7f; + (*attr)->guard_size = 0x1000; + + SceKernelSchedParam param{}; + param.sched_priority = 700; + + result = (result == 0 ? scePthreadAttrSetinheritsched(attr, 4) : result); + result = (result == 0 ? scePthreadAttrSetschedparam(attr, ¶m) : result); + result = (result == 0 ? scePthreadAttrSetschedpolicy(attr, SCHED_OTHER) : result); + result = (result == 0 ? scePthreadAttrSetdetachstate(attr, PTHREAD_CREATE_JOINABLE) : result); + + switch (result) { + case 0: return SCE_OK; + case ENOMEM: return SCE_KERNEL_ERROR_ENOMEM; + default: return SCE_KERNEL_ERROR_EINVAL; + } +} + +int scePthreadAttrSetdetachstate(ScePthreadAttr* attr, int detachstate) { + + if (attr == nullptr || *attr == nullptr) { + return SCE_KERNEL_ERROR_EINVAL; + } + + int pstate = PTHREAD_CREATE_JOINABLE; + switch (detachstate) { + case 0: pstate = PTHREAD_CREATE_JOINABLE; break; + case 1: pstate = PTHREAD_CREATE_DETACHED; break; + default: + __debugbreak(); //unknown state + } + + int result = pthread_attr_setdetachstate(&(*attr)->pth_attr, pstate); + + (*attr)->detached = (pstate == PTHREAD_CREATE_DETACHED); + + if (result == 0) { + return SCE_OK; + } + return SCE_KERNEL_ERROR_EINVAL; +} + +int scePthreadAttrSetinheritsched(ScePthreadAttr* attr, int inheritSched) { + + if (attr == nullptr || *attr == nullptr) { + return SCE_KERNEL_ERROR_EINVAL; + } + + int pinherit_sched = PTHREAD_INHERIT_SCHED; + switch (inheritSched) { + case 0: pinherit_sched = PTHREAD_EXPLICIT_SCHED; break; + case 4: pinherit_sched = PTHREAD_INHERIT_SCHED; break; + default: __debugbreak(); // unknown inheritSched + } + + int result = pthread_attr_setinheritsched(&(*attr)->pth_attr, pinherit_sched); + + if (result == 0) { + return SCE_OK; + } + return SCE_KERNEL_ERROR_EINVAL; +} + +int scePthreadAttrSetschedparam(ScePthreadAttr* attr, const SceKernelSchedParam* param) { + + if (param == nullptr || attr == nullptr || *attr == nullptr) { + return SCE_KERNEL_ERROR_EINVAL; + } + + SceKernelSchedParam pparam{}; + if (param->sched_priority <= 478) { + pparam.sched_priority = +2; + } else if (param->sched_priority >= 733) { + pparam.sched_priority = -2; + } else { + pparam.sched_priority = 0; + } + + int result = pthread_attr_setschedparam(&(*attr)->pth_attr, &pparam); + + if (result == 0) { + return SCE_OK; + } + return SCE_KERNEL_ERROR_EINVAL; +} + +int scePthreadAttrSetschedpolicy(ScePthreadAttr* attr, int policy) { + + if (attr == nullptr || *attr == nullptr) { + return SCE_KERNEL_ERROR_EINVAL; + } + + if (policy!= SCHED_OTHER) + { + __debugbreak();//invest if policy is other and if winpthreadlibrary support it + } + + (*attr)->policy = policy; + + int result = pthread_attr_setschedpolicy(&(*attr)->pth_attr, policy); + + if (result == 0) { + return SCE_OK; + } + return SCE_KERNEL_ERROR_EINVAL; +} + +}; \ No newline at end of file diff --git a/src/Core/PS4/HLE/Kernel/ThreadManagement.h b/src/Core/PS4/HLE/Kernel/ThreadManagement.h new file mode 100644 index 00000000..bda43cf3 --- /dev/null +++ b/src/Core/PS4/HLE/Kernel/ThreadManagement.h @@ -0,0 +1,42 @@ +#pragma once +#define _TIMESPEC_DEFINED + +#include +#include +#include "../../../../types.h" +#include + +namespace HLE::Libs::LibKernel::ThreadManagement { + +struct PthreadAttrInternal; + +using SceKernelSchedParam = ::sched_param; +using ScePthreadAttr = PthreadAttrInternal*; + +struct PthreadInternal { + u08 reserved[4096]; + std::string name; + pthread_t pth; + ScePthreadAttr attr; +}; +struct PthreadAttrInternal { + u08 reserved[64]; + u64 affinity; + size_t guard_size; + int policy; + bool detached; + pthread_attr_t pth_attr; +}; + +class PThreadCxt {}; + +void Pthread_Init_Self_MainThread(); + + //HLE FUNCTIONS +int scePthreadAttrInit(ScePthreadAttr* attr); +int scePthreadAttrSetdetachstate(ScePthreadAttr* attr, int detachstate); +int scePthreadAttrSetinheritsched(ScePthreadAttr* attr, int inheritSched); +int scePthreadAttrSetschedparam(ScePthreadAttr* attr, const SceKernelSchedParam* param); +int scePthreadAttrSetschedpolicy(ScePthreadAttr* attr, int policy); + +} // namespace HLE::Libs::LibKernel::ThreadManagement \ No newline at end of file diff --git a/src/Core/PS4/HLE/LibC.cpp b/src/Core/PS4/HLE/LibC.cpp index db58b9df..43d27c69 100644 --- a/src/Core/PS4/HLE/LibC.cpp +++ b/src/Core/PS4/HLE/LibC.cpp @@ -8,10 +8,7 @@ namespace HLE::Libs::LibC { static void init_env() //every game/demo should probably { - for(;;) { - printf("__debugbreak\n"); - } - //__debugbreak();//if we reach here it will be a great progress :D + //dummy no need atm } int __cxa_guard_acquire(u64* guard_object) @@ -39,7 +36,11 @@ namespace HLE::Libs::LibC { } static int atexit(void (*func)()) - { return 0; + { + for (;;) { + printf("we reached here too!\n"); + } + return 0; } void LibC_Register(SymbolsResolver* sym) diff --git a/src/Core/PS4/Linker.cpp b/src/Core/PS4/Linker.cpp index e7461690..f9f27fff 100644 --- a/src/Core/PS4/Linker.cpp +++ b/src/Core/PS4/Linker.cpp @@ -5,6 +5,7 @@ #include "../../Util/StringUtil.h" #include "Util/aerolib.h" #include "Loader/SymbolsResolver.h" +#include "HLE/Kernel/ThreadManagement.h" constexpr bool debug_loader = true; @@ -628,4 +629,27 @@ void Linker::Resolve(const std::string& name, int Symtype, Module* m, SymbolReco __debugbreak();//oute edo mallon } +} + +using exit_func_t = void (*)(); +using entry_func_t = void (*)(EntryParams* params, exit_func_t atexit_func); + +static void ProgramExitFunc() { + + printf("exit function called\n"); +} + +static void run_main_entry(u64 addr, EntryParams* params, exit_func_t exit_func) { + reinterpret_cast(addr)(params, exit_func); +} + +void Linker::Execute() +{ + HLE::Libs::LibKernel::ThreadManagement::Pthread_Init_Self_MainThread(); + EntryParams p{}; + p.argc = 1; + p.argv[0] = "eboot.bin"; //hmm should be ok? + + run_main_entry(m_modules.at(0)->elf->GetElfEntry()+m_modules.at(0)->base_virtual_addr, &p, ProgramExitFunc); + } \ No newline at end of file diff --git a/src/Core/PS4/Linker.h b/src/Core/PS4/Linker.h index e2e33019..13f45acf 100644 --- a/src/Core/PS4/Linker.h +++ b/src/Core/PS4/Linker.h @@ -7,6 +7,12 @@ struct DynamicModuleInfo; class Linker; +struct EntryParams { + int argc; + u32 padding; + const char* argv[3]; +}; + /*this struct keeps neccesary info about loaded modules.Main executeable is included too as well*/ struct Module { @@ -115,8 +121,9 @@ public: SymbolsResolver* getHLESymbols() { return m_HLEsymbols; } void Relocate(Module* m); void Resolve(const std::string& name, int Symtype, Module* m, SymbolRecord* return_info); + void Execute(); -private: + private: const ModuleInfo* FindModule(const Module& m, const std::string& id); const LibraryInfo* FindLibrary(const Module& program, const std::string& id); diff --git a/src/main.cpp b/src/main.cpp index e4d8e493..4d715777 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -33,17 +33,18 @@ // Main code int main(int argc, char* argv[]) { - if (argc == 1) { + /* if (argc == 1) { printf("Usage: %s \n", argv[0]); return -1; - } + }*/ logging::init(true);//init logging - const char* const path = argv[1]; //argument 1 is the path of self file to boot + const char* const path = argv[1]; // argument 1 is the path of self file to boot auto* linker = Singleton::Instance(); HLE::Libs::Init_HLE_Libs(linker->getHLESymbols()); auto *module =linker->LoadModule(path);//load main executable - + + linker->Execute(); #if 0 // Setup SDL if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMEPAD) != 0) diff --git a/third-party/CMakeLists.txt b/third-party/CMakeLists.txt index 7272a238..048fae86 100644 --- a/third-party/CMakeLists.txt +++ b/third-party/CMakeLists.txt @@ -27,6 +27,8 @@ option(ZYDIS_BUILD_EXAMPLES "" OFF) set(zydis_DIR ${CMAKE_CURRENT_SOURCE_DIR}/zydis) add_subdirectory(${zydis_DIR}) +#========== winpthreads ====================== +add_subdirectory(winpthread) #=================== IMGUI =================== set(IMGUI_DIR ${CMAKE_CURRENT_SOURCE_DIR}/imgui) @@ -56,6 +58,6 @@ find_package(OpenGL REQUIRED) target_link_libraries(IMGUI PUBLIC ${OPENGL_LIBRARIES}) -target_link_libraries(IMGUI PUBLIC SDL3-shared ${CMAKE_DL_LIBS} Zydis) +target_link_libraries(IMGUI PUBLIC SDL3-shared ${CMAKE_DL_LIBS} Zydis winpthread) diff --git a/third-party/SDL b/third-party/SDL index 125e7420..27556e09 160000 --- a/third-party/SDL +++ b/third-party/SDL @@ -1 +1 @@ -Subproject commit 125e7420ecd2b0d1847aef804f53e614fbc68253 +Subproject commit 27556e098ecce54014ed1fc11c1e974ffdf4bc93 diff --git a/third-party/fmt b/third-party/fmt index de0757b5..661b23ed 160000 --- a/third-party/fmt +++ b/third-party/fmt @@ -1 +1 @@ -Subproject commit de0757b578244e0bf7ac50007fb5e25fcc899c7c +Subproject commit 661b23edeb52d400cf5812e7330f14f05c072fab diff --git a/third-party/imgui b/third-party/imgui index 4fab72b4..52125a54 160000 --- a/third-party/imgui +++ b/third-party/imgui @@ -1 +1 @@ -Subproject commit 4fab72b40e2972f5d56fc884ed5797446238844e +Subproject commit 52125a54a57a458e89bc61502010e964add3cdd5 diff --git a/third-party/magic_enum b/third-party/magic_enum index 5018ef96..4904822d 160000 --- a/third-party/magic_enum +++ b/third-party/magic_enum @@ -1 +1 @@ -Subproject commit 5018ef9677521983bfedb127901284432d1a05a2 +Subproject commit 4904822db8770d04444add00a9e155568d3e8bd1 diff --git a/third-party/spdlog b/third-party/spdlog index 5a6b6caf..76dfc7e7 160000 --- a/third-party/spdlog +++ b/third-party/spdlog @@ -1 +1 @@ -Subproject commit 5a6b6cafa8d4aee3e6d0dd16a2cae9169141c831 +Subproject commit 76dfc7e7c0d3c69d3cdaa3399b63545235ccbb02 diff --git a/third-party/winpthread b/third-party/winpthread new file mode 160000 index 00000000..918de958 --- /dev/null +++ b/third-party/winpthread @@ -0,0 +1 @@ +Subproject commit 918de958b720c3ba7bc47f4988609c0109a0f75b diff --git a/third-party/zydis b/third-party/zydis index d4c37ae7..a6d0c713 160000 --- a/third-party/zydis +++ b/third-party/zydis @@ -1 +1 @@ -Subproject commit d4c37ae7a9db989495eb66636a65d8d4ff69eb35 +Subproject commit a6d0c713b71b5009634868389f0ff551871273d6