core/libraries: Initial fiber implementation
Some checks failed
Build and Release / reuse (push) Has been cancelled
Build and Release / clang-format (push) Has been cancelled
Build and Release / get-info (push) Has been cancelled
Build and Release / windows-qt (push) Has been cancelled
Build and Release / macos-sdl (push) Has been cancelled
Build and Release / windows-sdl (push) Has been cancelled
Build and Release / macos-qt (push) Has been cancelled
Build and Release / linux-sdl (push) Has been cancelled
Build and Release / linux-qt (push) Has been cancelled
Build and Release / pre-release (push) Has been cancelled

This commit is contained in:
Daniel R 2024-10-06 00:09:06 +02:00
parent 2fd4861d3e
commit bd41050539
No known key found for this signature in database
GPG key ID: B8ADC8F57BA18DBA
8 changed files with 387 additions and 2 deletions

View file

@ -324,6 +324,10 @@ set(USBD_LIB src/core/libraries/usbd/usbd.cpp
src/core/libraries/usbd/usbd.h
)
set(FIBER_LIB src/core/libraries/fiber/fiber.cpp
src/core/libraries/fiber/fiber.h
)
set(NP_LIBS src/core/libraries/np_manager/np_manager.cpp
src/core/libraries/np_manager/np_manager.h
src/core/libraries/np_score/np_score.cpp
@ -462,6 +466,7 @@ set(CORE src/core/aerolib/stubs.cpp
${USBD_LIB}
${MISC_LIBS}
${DIALOGS_LIB}
${FIBER_LIB}
${DEV_TOOLS}
src/core/debug_state.cpp
src/core/debug_state.h

View file

@ -114,6 +114,7 @@ bool ParseFilterRule(Filter& instance, Iterator begin, Iterator end) {
SUB(Lib, AvPlayer) \
SUB(Lib, Ngs2) \
SUB(Lib, Audio3d) \
SUB(Lib, Fiber) \
CLS(Frontend) \
CLS(Render) \
SUB(Render, Vulkan) \

View file

@ -81,6 +81,7 @@ enum class Class : u8 {
Lib_AvPlayer, ///< The LibSceAvPlayer implementation.
Lib_Ngs2, ///< The LibSceNgs2 implementation.
Lib_Audio3d, ///< The LibSceAudio3d implementation.
Lib_Fiber, ///< The LibSceFiber implementation.
Frontend, ///< Emulator UI
Render, ///< Video Core
Render_Vulkan, ///< Vulkan backend

View file

@ -499,3 +499,11 @@ constexpr int ORBIS_AVPLAYER_ERROR_INFO_OTHER_ENCRY = 0x806A00BF;
constexpr int ORBIS_APP_CONTENT_ERROR_PARAMETER = 0x80D90002;
constexpr int ORBIS_APP_CONTENT_ERROR_DRM_NO_ENTITLEMENT = 0x80D90007;
constexpr int ORBIS_APP_CONTENT_ERROR_NOT_FOUND = 0x80D90005;
// Fiber library
constexpr int ORBIS_FIBER_ERROR_NULL = 0x80590001;
constexpr int ORBIS_FIBER_ERROR_ALIGNMENT = 0x80590002;
constexpr int ORBIS_FIBER_ERROR_RANGE = 0x80590003;
constexpr int ORBIS_FIBER_ERROR_INVALID = 0x80590004;
constexpr int ORBIS_FIBER_ERROR_PERMISSION = 0x80590005;
constexpr int ORBIS_FIBER_ERROR_STATE = 0x80590006;

View file

@ -0,0 +1,284 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "fiber.h"
#include "common/logging/log.h"
#include "common/singleton.h"
#include "core/libraries/error_codes.h"
#include "core/libraries/libs.h"
#include "core/linker.h"
#ifdef _WIN64
#include <windows.h>
#endif
namespace Libraries::Fiber {
constexpr static u64 kFiberSignature = 0x054ad954;
thread_local SceFiber* gCurrentFiber = nullptr;
thread_local void* gFiberThread = nullptr;
void FiberEntry(void* param) {
SceFiber* fiber = static_cast<SceFiber*>(param);
u64 argRun = 0;
u64 argRet = 0;
gCurrentFiber = fiber;
if (fiber->pArgRun != nullptr) {
argRun = *fiber->pArgRun;
}
const auto* linker = Common::Singleton<Core::Linker>::Instance();
linker->ExecuteGuest(fiber->entry, fiber->argOnInitialize, argRun);
UNREACHABLE();
}
s32 PS4_SYSV_ABI sceFiberInitialize(SceFiber* fiber, const char* name, SceFiberEntry entry,
u64 argOnInitialize, void* addrContext, u64 sizeContext,
const SceFiberOptParam* optParam) {
LOG_INFO(Lib_Fiber, "called: name = {}", name);
if (!fiber || !name || !entry) {
return ORBIS_FIBER_ERROR_NULL;
}
fiber->signature = kFiberSignature;
fiber->entry = entry;
fiber->argOnInitialize = argOnInitialize;
fiber->argRun = 0;
fiber->pArgRun = &fiber->argRun;
fiber->argReturn = 0;
fiber->pArgReturn = &fiber->argReturn;
fiber->sizeContext = sizeContext;
fiber->state = FiberState::Init;
#ifdef _WIN64
fiber->handle = CreateFiber(sizeContext, FiberEntry, fiber);
#else
UNREACHABLE_MSG("Missing implementation");
#endif
strncpy(fiber->name, name, ORBIS_FIBER_MAX_NAME_LENGTH);
return ORBIS_OK;
}
s32 PS4_SYSV_ABI sceFiberOptParamInitialize(SceFiberOptParam* optParam) {
LOG_ERROR(Lib_Fiber, "called");
if (!optParam) {
return ORBIS_FIBER_ERROR_NULL;
}
return ORBIS_OK;
}
s32 PS4_SYSV_ABI sceFiberFinalize(SceFiber* fiber) {
LOG_TRACE(Lib_Fiber, "called");
if (!fiber) {
return ORBIS_FIBER_ERROR_NULL;
}
if ((u64)fiber % 8 != 0) {
return ORBIS_FIBER_ERROR_ALIGNMENT;
}
if (fiber->signature != kFiberSignature) {
return ORBIS_FIBER_ERROR_INVALID;
}
if (fiber->state != FiberState::Run) {
return ORBIS_FIBER_ERROR_STATE;
}
fiber->signature = 0;
fiber->state = FiberState::None;
#ifdef _WIN64
DeleteFiber(fiber->handle);
#else
UNREACHABLE_MSG("Missing implementation");
#endif
return ORBIS_OK;
}
s32 PS4_SYSV_ABI sceFiberRun(SceFiber* fiber, u64 argOnRunTo, u64* argOnReturn) {
LOG_TRACE(Lib_Fiber, "called");
if (!fiber) {
return ORBIS_FIBER_ERROR_NULL;
}
if ((u64)fiber % 8 != 0) {
return ORBIS_FIBER_ERROR_ALIGNMENT;
}
if (fiber->signature != kFiberSignature) {
return ORBIS_FIBER_ERROR_INVALID;
}
if (fiber->state == FiberState::Run) {
return ORBIS_FIBER_ERROR_STATE;
}
if (gFiberThread == nullptr) {
#ifdef _WIN64
gFiberThread = ConvertThreadToFiber(nullptr);
#else
UNREACHABLE_MSG("Missing implementation");
#endif
}
gCurrentFiber = fiber;
if (fiber->pArgRun != nullptr) {
*fiber->pArgRun = argOnRunTo;
}
fiber->pArgReturn = argOnReturn;
fiber->state = FiberState::Run;
#ifdef _WIN64
SwitchToFiber(fiber->handle);
#else
UNREACHABLE_MSG("Missing implementation");
#endif
return ORBIS_OK;
}
s32 PS4_SYSV_ABI sceFiberSwitch(SceFiber* fiber, u64 argOnRunTo, u64* argOnRun) {
LOG_TRACE(Lib_Fiber, "called");
if (!fiber) {
return ORBIS_FIBER_ERROR_NULL;
}
if ((u64)fiber % 8 != 0) {
return ORBIS_FIBER_ERROR_ALIGNMENT;
}
if (fiber->signature != kFiberSignature) {
return ORBIS_FIBER_ERROR_INVALID;
}
if (gCurrentFiber == nullptr) {
return ORBIS_FIBER_ERROR_PERMISSION;
}
if (fiber->state == FiberState::Run) {
return ORBIS_FIBER_ERROR_STATE;
}
gCurrentFiber->state = FiberState::Suspend;
// TODO: argOnRun
*fiber->pArgRun = argOnRunTo;
fiber->state = FiberState::Run;
gCurrentFiber = fiber;
#ifdef _WIN64
SwitchToFiber(fiber->handle);
#else
UNREACHABLE_MSG("Missing implementation");
#endif
return ORBIS_OK;
}
s32 PS4_SYSV_ABI sceFiberGetSelf(SceFiber** fiber) {
LOG_TRACE(Lib_Fiber, "called");
if (!fiber || !gCurrentFiber) {
return ORBIS_FIBER_ERROR_NULL;
}
if (gCurrentFiber->signature != kFiberSignature) {
return ORBIS_FIBER_ERROR_PERMISSION;
}
*fiber = gCurrentFiber;
return ORBIS_OK;
}
s32 PS4_SYSV_ABI sceFiberReturnToThread(u64 argOnReturn, u64* argOnRun) {
LOG_TRACE(Lib_Fiber, "called");
if (gCurrentFiber->signature != kFiberSignature) {
return ORBIS_FIBER_ERROR_PERMISSION;
}
if (gCurrentFiber->pArgReturn != nullptr) {
*gCurrentFiber->pArgReturn = argOnReturn;
}
// TODO: argOnRun
gCurrentFiber->state = FiberState::Suspend;
gCurrentFiber = nullptr;
#ifdef _WIN64
SwitchToFiber(gFiberThread);
#else
UNREACHABLE_MSG("Missing implementation");
#endif
return ORBIS_OK;
}
s32 PS4_SYSV_ABI sceFiberGetInfo(SceFiber* fiber, SceFiberInfo* fiberInfo) {
LOG_INFO(Lib_Fiber, "called");
if (!fiber || !fiberInfo) {
return ORBIS_FIBER_ERROR_NULL;
}
fiberInfo->entry = fiber->entry;
fiberInfo->argOnInitialize = fiber->argOnInitialize;
fiberInfo->addrContext = nullptr;
fiberInfo->sizeContext = fiber->sizeContext;
fiberInfo->sizeContextMargin = 0;
strncpy(fiberInfo->name, fiber->name, ORBIS_FIBER_MAX_NAME_LENGTH);
return ORBIS_OK;
}
s32 PS4_SYSV_ABI sceFiberStartContextSizeCheck(u32 flags) {
LOG_ERROR(Lib_Fiber, "called");
if (flags != 0) {
return ORBIS_FIBER_ERROR_INVALID;
}
return ORBIS_OK;
}
s32 PS4_SYSV_ABI sceFiberStopContextSizeCheck() {
LOG_ERROR(Lib_Fiber, "called");
return ORBIS_OK;
}
s32 PS4_SYSV_ABI sceFiberRename(SceFiber* fiber, const char* name) {
LOG_INFO(Lib_Fiber, "called, name = {}", name);
if (!fiber || !name) {
return ORBIS_FIBER_ERROR_NULL;
}
if ((u64)fiber % 8 != 0) {
return ORBIS_FIBER_ERROR_ALIGNMENT;
}
strncpy(fiber->name, name, ORBIS_FIBER_MAX_NAME_LENGTH);
return ORBIS_OK;
}
void RegisterlibSceFiber(Core::Loader::SymbolsResolver* sym) {
LIB_FUNCTION("hVYD7Ou2pCQ", "libSceFiber", 1, "libSceFiber", 1, 1, sceFiberInitialize);
LIB_FUNCTION("asjUJJ+aa8s", "libSceFiber", 1, "libSceFiber", 1, 1, sceFiberOptParamInitialize);
LIB_FUNCTION("JeNX5F-NzQU", "libSceFiber", 1, "libSceFiber", 1, 1, sceFiberFinalize);
LIB_FUNCTION("a0LLrZWac0M", "libSceFiber", 1, "libSceFiber", 1, 1, sceFiberRun);
LIB_FUNCTION("PFT2S-tJ7Uk", "libSceFiber", 1, "libSceFiber", 1, 1, sceFiberSwitch);
LIB_FUNCTION("p+zLIOg27zU", "libSceFiber", 1, "libSceFiber", 1, 1, sceFiberGetSelf);
LIB_FUNCTION("B0ZX2hx9DMw", "libSceFiber", 1, "libSceFiber", 1, 1, sceFiberReturnToThread);
LIB_FUNCTION("uq2Y5BFz0PE", "libSceFiber", 1, "libSceFiber", 1, 1, sceFiberGetInfo);
LIB_FUNCTION("Lcqty+QNWFc", "libSceFiber", 1, "libSceFiber", 1, 1,
sceFiberStartContextSizeCheck);
LIB_FUNCTION("Kj4nXMpnM8Y", "libSceFiber", 1, "libSceFiber", 1, 1,
sceFiberStopContextSizeCheck);
LIB_FUNCTION("JzyT91ucGDc", "libSceFiber", 1, "libSceFiber", 1, 1, sceFiberRename);
}
} // namespace Libraries::Fiber

View file

@ -0,0 +1,83 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "common/assert.h"
#include "common/types.h"
namespace Core::Loader {
class SymbolsResolver;
}
namespace Libraries::Fiber {
#define ORBIS_FIBER_MAX_NAME_LENGTH (31)
typedef void PS4_SYSV_ABI (*SceFiberEntry)(u64 argOnInitialize, u64 argOnRun);
enum FiberState : u32 {
None = 0u,
Init = 1u,
Run = 2u,
Suspend = 3u,
};
struct SceFiber {
u64 signature;
FiberState state;
SceFiberEntry entry;
u64 argOnInitialize;
u64 argRun;
u64* pArgRun;
u64 argReturn;
u64* pArgReturn;
u64 sizeContext;
char name[ORBIS_FIBER_MAX_NAME_LENGTH];
void* handle;
};
static_assert(sizeof(SceFiber) <= 256);
struct SceFiberInfo {
u64 size;
SceFiberEntry entry;
u64 argOnInitialize;
void* addrContext;
u64 sizeContext;
char name[ORBIS_FIBER_MAX_NAME_LENGTH + 1];
u64 sizeContextMargin;
};
static_assert(sizeof(SceFiberInfo) <= 128);
typedef void* SceFiberOptParam;
s32 PS4_SYSV_ABI sceFiberInitialize(SceFiber* fiber, const char* name, SceFiberEntry entry,
u64 argOnInitialize, void* addrContext, u64 sizeContext,
const SceFiberOptParam* optParam);
s32 PS4_SYSV_ABI sceFiberOptParamInitialize(SceFiberOptParam* optParam);
s32 PS4_SYSV_ABI sceFiberFinalize(SceFiber* fiber);
s32 PS4_SYSV_ABI sceFiberRun(SceFiber* fiber, u64 argOnRunTo, u64* argOnReturn);
s32 PS4_SYSV_ABI sceFiberSwitch(SceFiber* fiber, u64 argOnRunTo, u64* argOnRun);
s32 PS4_SYSV_ABI sceFiberGetSelf(SceFiber** fiber);
s32 PS4_SYSV_ABI sceFiberReturnToThread(u64 argOnReturn, u64* argOnRun);
s32 PS4_SYSV_ABI sceFiberGetInfo(SceFiber* fiber, SceFiberInfo* fiberInfo);
s32 PS4_SYSV_ABI sceFiberStartContextSizeCheck(u32 flags);
s32 PS4_SYSV_ABI sceFiberStopContextSizeCheck(void);
s32 PS4_SYSV_ABI sceFiberRename(SceFiber* fiber, const char* name);
void RegisterlibSceFiber(Core::Loader::SymbolsResolver* sym);
} // namespace Libraries::Fiber

View file

@ -11,6 +11,7 @@
#include "core/libraries/dialogs/error_dialog.h"
#include "core/libraries/dialogs/ime_dialog.h"
#include "core/libraries/disc_map/disc_map.h"
#include "core/libraries/fiber/fiber.h"
#include "core/libraries/gnmdriver/gnmdriver.h"
#include "core/libraries/kernel/libkernel.h"
#include "core/libraries/libc_internal/libc_internal.h"
@ -77,6 +78,7 @@ void InitHLELibs(Core::Loader::SymbolsResolver* sym) {
Libraries::ImeDialog::RegisterlibSceImeDialog(sym);
Libraries::AvPlayer::RegisterlibSceAvPlayer(sym);
Libraries::Audio3d::RegisterlibSceAudio3d(sym);
Libraries::Fiber::RegisterlibSceFiber(sym);
}
} // namespace Libraries

View file

@ -24,6 +24,7 @@
#include "core/file_format/trp.h"
#include "core/file_sys/fs.h"
#include "core/libraries/disc_map/disc_map.h"
#include "core/libraries/fiber/fiber.h"
#include "core/libraries/kernel/thread_management.h"
#include "core/libraries/libc_internal/libc_internal.h"
#include "core/libraries/libs.h"
@ -223,7 +224,7 @@ void Emulator::Run(const std::filesystem::path& file) {
void Emulator::LoadSystemModules(const std::filesystem::path& file) {
constexpr std::array<SysModules, 13> ModulesToLoad{
{{"libSceNgs2.sprx", &Libraries::Ngs2::RegisterlibSceNgs2},
{"libSceFiber.sprx", nullptr},
{"libSceFiber.sprx", &Libraries::Fiber::RegisterlibSceFiber},
{"libSceUlt.sprx", nullptr},
{"libSceJson.sprx", nullptr},
{"libSceJson2.sprx", nullptr},