mirror of
https://github.com/RPCSX/rpcsx.git
synced 2025-12-31 13:50:46 +01:00
[rpcsx-os] simulate environment objects without vsh
This commit is contained in:
parent
0a957b8785
commit
f3643aabf8
|
|
@ -97,9 +97,34 @@ struct IpmiCreateServerConfig {
|
|||
|
||||
static_assert(sizeof(IpmiCreateServerConfig) == 0x38);
|
||||
|
||||
ErrorCode ipmiCreateClient(Thread *thread, void *clientImpl, const char *name,
|
||||
struct IpmiBufferInfo {
|
||||
ptr<void> data;
|
||||
uint64_t size;
|
||||
};
|
||||
|
||||
static_assert(sizeof(IpmiBufferInfo) == 0x10);
|
||||
|
||||
struct IpmiDataInfo {
|
||||
ptr<void> data;
|
||||
uint64_t size;
|
||||
uint64_t capacity; //?
|
||||
};
|
||||
|
||||
static_assert(sizeof(IpmiDataInfo) == 0x18);
|
||||
|
||||
struct IpmiSyncMessageHeader {
|
||||
orbis::ptr<void> sessionImpl;
|
||||
orbis::uint pid;
|
||||
orbis::uint methodId;
|
||||
orbis::uint numInData;
|
||||
orbis::uint numOutData;
|
||||
};
|
||||
|
||||
static_assert(sizeof(IpmiSyncMessageHeader) == 0x18);
|
||||
|
||||
ErrorCode ipmiCreateClient(Process *proc, void *clientImpl, const char *name,
|
||||
void *config, Ref<IpmiClient> &result);
|
||||
ErrorCode ipmiCreateServer(Thread *thread, void *serverImpl, const char *name,
|
||||
ErrorCode ipmiCreateServer(Process *proc, void *serverImpl, const char *name,
|
||||
const IpmiCreateServerConfig &config,
|
||||
Ref<IpmiServer> &result);
|
||||
ErrorCode ipmiCreateSession(Thread *thread, void *sessionImpl,
|
||||
|
|
|
|||
|
|
@ -3,24 +3,7 @@
|
|||
#include "thread/Process.hpp"
|
||||
#include "utils/Logs.hpp"
|
||||
|
||||
namespace orbis {
|
||||
struct IpmiBufferInfo {
|
||||
ptr<void> data;
|
||||
uint64_t size;
|
||||
};
|
||||
|
||||
static_assert(sizeof(IpmiBufferInfo) == 0x10);
|
||||
|
||||
struct IpmiDataInfo {
|
||||
ptr<void> data;
|
||||
uint64_t size;
|
||||
uint64_t capacity; //?
|
||||
};
|
||||
|
||||
static_assert(sizeof(IpmiDataInfo) == 0x18);
|
||||
} // namespace orbis
|
||||
|
||||
orbis::ErrorCode orbis::ipmiCreateClient(Thread *thread, void *clientImpl,
|
||||
orbis::ErrorCode orbis::ipmiCreateClient(Process *proc, void *clientImpl,
|
||||
const char *name, void *config,
|
||||
Ref<IpmiClient> &result) {
|
||||
auto client = knew<IpmiClient>(name);
|
||||
|
|
@ -30,12 +13,12 @@ orbis::ErrorCode orbis::ipmiCreateClient(Thread *thread, void *clientImpl,
|
|||
|
||||
client->clientImpl = clientImpl;
|
||||
client->name = name;
|
||||
client->pid = thread->tproc->pid;
|
||||
client->pid = proc->pid;
|
||||
result = client;
|
||||
return {};
|
||||
}
|
||||
|
||||
orbis::ErrorCode orbis::ipmiCreateServer(Thread *thread, void *serverImpl,
|
||||
orbis::ErrorCode orbis::ipmiCreateServer(Process *proc, void *serverImpl,
|
||||
const char *name,
|
||||
const IpmiCreateServerConfig &config,
|
||||
Ref<IpmiServer> &result) {
|
||||
|
|
@ -45,7 +28,7 @@ orbis::ErrorCode orbis::ipmiCreateServer(Thread *thread, void *serverImpl,
|
|||
server->serverImpl = serverImpl;
|
||||
server->userData = config.userData;
|
||||
server->eventHandler = config.eventHandler;
|
||||
server->pid = thread->tproc->pid;
|
||||
server->pid = proc->pid;
|
||||
result = server;
|
||||
return {};
|
||||
}
|
||||
|
|
@ -116,7 +99,7 @@ orbis::SysResult orbis::sysIpmiCreateClient(Thread *thread, ptr<uint> result,
|
|||
ORBIS_RET_ON_ERROR(uread(_params, ptr<IpmiCreateClientParams>(params)));
|
||||
ORBIS_RET_ON_ERROR(ureadString(_name, sizeof(_name), _params.name));
|
||||
ORBIS_RET_ON_ERROR(
|
||||
ipmiCreateClient(thread, _params.clientImpl, _name, nullptr, client));
|
||||
ipmiCreateClient(thread->tproc, _params.clientImpl, _name, nullptr, client));
|
||||
|
||||
auto kid = thread->tproc->ipmiMap.insert(std::move(client));
|
||||
|
||||
|
|
@ -152,7 +135,7 @@ orbis::SysResult orbis::sysIpmiCreateServer(Thread *thread, ptr<uint> result,
|
|||
ORBIS_RET_ON_ERROR(uread(_config, _params.config));
|
||||
ORBIS_RET_ON_ERROR(ureadString(_name, sizeof(_name), _params.name));
|
||||
ORBIS_RET_ON_ERROR(
|
||||
ipmiCreateServer(thread, _params.serverImpl, _name, _config, server));
|
||||
ipmiCreateServer(thread->tproc, _params.serverImpl, _name, _config, server));
|
||||
auto kid = thread->tproc->ipmiMap.insert(std::move(server));
|
||||
|
||||
if (kid == -1) {
|
||||
|
|
@ -396,16 +379,6 @@ orbis::sysIpmiClientInvokeSyncMethod(Thread *thread, ptr<uint> result, uint kid,
|
|||
|
||||
static_assert(sizeof(IpmiSyncCallParams) == 0x30);
|
||||
|
||||
struct MessageHeader {
|
||||
ptr<void> sessionImpl;
|
||||
uint pid;
|
||||
uint methodId;
|
||||
uint numInData;
|
||||
uint numOutData;
|
||||
};
|
||||
|
||||
static_assert(sizeof(MessageHeader) == 0x18);
|
||||
|
||||
if (paramsSz != sizeof(IpmiSyncCallParams)) {
|
||||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
|
@ -463,12 +436,12 @@ orbis::sysIpmiClientInvokeSyncMethod(Thread *thread, ptr<uint> result, uint kid,
|
|||
outSize += data.size;
|
||||
}
|
||||
|
||||
auto size = sizeof(MessageHeader) + inSize + outSize +
|
||||
auto size = sizeof(IpmiSyncMessageHeader) + inSize + outSize +
|
||||
_params.numInData * sizeof(uint32_t) +
|
||||
_params.numOutData * sizeof(uint32_t);
|
||||
|
||||
kvector<std::byte> message(size);
|
||||
auto msg = new (message.data()) MessageHeader;
|
||||
auto msg = new (message.data()) IpmiSyncMessageHeader;
|
||||
msg->sessionImpl = session->sessionImpl;
|
||||
msg->pid = thread->tproc->pid;
|
||||
msg->methodId = _params.method;
|
||||
|
|
|
|||
|
|
@ -11,9 +11,7 @@
|
|||
#include "vm.hpp"
|
||||
#include <rx/Version.hpp>
|
||||
|
||||
#include <atomic>
|
||||
#include <elf.h>
|
||||
#include <filesystem>
|
||||
#include <linux/prctl.h>
|
||||
#include <orbis/KernelContext.hpp>
|
||||
#include <orbis/module.hpp>
|
||||
|
|
@ -30,9 +28,13 @@
|
|||
#include <sys/prctl.h>
|
||||
#include <ucontext.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <csignal>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <filesystem>
|
||||
#include <functional>
|
||||
#include <sstream>
|
||||
|
||||
static int g_gpuPid;
|
||||
|
||||
|
|
@ -610,6 +612,268 @@ static void runRpsxGpu() {
|
|||
}
|
||||
}
|
||||
|
||||
static orbis::Semaphore *createSemaphore(std::string_view name, uint32_t attrs,
|
||||
uint64_t initCount,
|
||||
uint64_t maxCount) {
|
||||
return orbis::g_context
|
||||
.createSemaphore(orbis::kstring(name), attrs, initCount, maxCount)
|
||||
.first;
|
||||
}
|
||||
|
||||
static orbis::EventFlag *createEventFlag(std::string_view name, uint32_t attrs,
|
||||
uint64_t initPattern) {
|
||||
return orbis::g_context
|
||||
.createEventFlag(orbis::kstring(name), attrs, initPattern)
|
||||
.first;
|
||||
}
|
||||
|
||||
static void createShm(const char *name, uint32_t flags, uint32_t mode,
|
||||
uint64_t size) {
|
||||
orbis::Ref<orbis::File> shm;
|
||||
auto shmDevice = orbis::g_context.shmDevice.staticCast<IoDevice>();
|
||||
shmDevice->open(&shm, "/SceAvSetting", flags, mode, nullptr);
|
||||
shm->ops->truncate(shm.get(), 4096, nullptr);
|
||||
}
|
||||
|
||||
static orbis::Ref<orbis::IpmiServer> createIpmiServer(
|
||||
orbis::Process *process, const char *name,
|
||||
std::function<void(orbis::IpmiSession *, orbis::IpmiSyncMessageHeader *)>
|
||||
packetHandler) {
|
||||
orbis::IpmiCreateServerConfig config{};
|
||||
orbis::Ref<orbis::IpmiServer> server;
|
||||
orbis::ipmiCreateServer(process, nullptr, name, config, server);
|
||||
std::thread{[server, packetHandler = std::move(packetHandler)] {
|
||||
while (true) {
|
||||
orbis::IpmiServer::Packet packet;
|
||||
{
|
||||
std::lock_guard lock(server->mutex);
|
||||
|
||||
while (server->packets.empty()) {
|
||||
server->receiveCv.wait(server->mutex);
|
||||
}
|
||||
|
||||
packet = std::move(server->packets.front());
|
||||
server->packets.pop_front();
|
||||
}
|
||||
|
||||
if (packet.info.type == 1) {
|
||||
std::lock_guard serverLock(server->mutex);
|
||||
|
||||
for (auto it = server->connectionRequests.begin();
|
||||
it != server->connectionRequests.end(); ++it) {
|
||||
auto &conReq = *it;
|
||||
std::lock_guard clientLock(conReq.client->mutex);
|
||||
if (conReq.client->session != nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto session = orbis::knew<orbis::IpmiSession>();
|
||||
if (session == nullptr) {
|
||||
break;
|
||||
}
|
||||
|
||||
session->client = conReq.client;
|
||||
session->server = server;
|
||||
conReq.client->session = session;
|
||||
conReq.client->sessionCv.notify_all(conReq.client->mutex);
|
||||
// server->connectionRequests.erase(it);
|
||||
break;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((packet.info.type & ~0x8010) == 0x41) {
|
||||
auto msgHeader = std::bit_cast<orbis::IpmiSyncMessageHeader *>(
|
||||
packet.message.data());
|
||||
auto process = orbis::g_context.findProcessById(msgHeader->pid);
|
||||
if (process == nullptr) {
|
||||
continue;
|
||||
}
|
||||
auto client = process->ipmiMap.get(packet.info.clientKid)
|
||||
.cast<orbis::IpmiClient>();
|
||||
if (client == nullptr) {
|
||||
continue;
|
||||
}
|
||||
auto session = client->session;
|
||||
if (session == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
packetHandler(client->session.get(), msgHeader);
|
||||
continue;
|
||||
}
|
||||
|
||||
std::fprintf(stderr, "IPMI: Unhandled packet %s::%u\n",
|
||||
server->name.c_str(), packet.info.type);
|
||||
}
|
||||
}}.detach();
|
||||
return server;
|
||||
}
|
||||
|
||||
static std::uint32_t
|
||||
unimplementedIpmiServer(orbis::IpmiSession *session,
|
||||
orbis::IpmiSyncMessageHeader *message) {
|
||||
std::fprintf(
|
||||
stderr,
|
||||
"Unimplemented sync method %s::%x(inBufCount=%x, outBufCount=%x)\n",
|
||||
session->server->name.c_str(), message->methodId, message->numInData,
|
||||
message->numOutData);
|
||||
|
||||
std::size_t inBufferOffset = 0;
|
||||
auto bufLoc = std::bit_cast<char *>(message + 1);
|
||||
for (unsigned i = 0; i < message->numInData; ++i) {
|
||||
bufLoc += *std::bit_cast<orbis::uint *>(bufLoc) + sizeof(orbis::uint);
|
||||
}
|
||||
|
||||
auto outSize = *std::bit_cast<orbis::uint *>(bufLoc);
|
||||
orbis::kvector<std::byte> output(outSize);
|
||||
|
||||
std::lock_guard lock(session->mutex);
|
||||
|
||||
session->messageResponses.push_front({
|
||||
.errorCode = 0,
|
||||
.data = std::move(output),
|
||||
});
|
||||
|
||||
session->responseCv.notify_one(session->mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void createSysAvControlObjects(orbis::Process *process) {
|
||||
createIpmiServer(process, "SceAvSettingIpc", unimplementedIpmiServer);
|
||||
|
||||
createEventFlag("SceAvSettingEvf", 0x121, 0xffff00000000);
|
||||
|
||||
createShm("/SceAvSetting", 0xa02, 0x1a4, 4096);
|
||||
}
|
||||
|
||||
static void createSysCoreObjects(orbis::Process *process) {
|
||||
createIpmiServer(process, "SceMbusIpc", unimplementedIpmiServer);
|
||||
createIpmiServer(process, "SceSysCoreApp", unimplementedIpmiServer);
|
||||
createIpmiServer(process, "SceSysCoreApp2", unimplementedIpmiServer);
|
||||
createIpmiServer(process, "SceMDBG0SRV", unimplementedIpmiServer);
|
||||
|
||||
createSemaphore("SceSysCoreProcSpawnSema", 0x101, 0, 1);
|
||||
createSemaphore("SceTraceMemorySem", 0x100, 1, 1);
|
||||
createSemaphore("SceSysCoreEventSemaphore", 0x101, 0, 0x2d2);
|
||||
createSemaphore("SceSysCoreProcSema", 0x101, 0, 1);
|
||||
createSemaphore("AppmgrCoredumpHandlingEventSema", 0x101, 0, 4);
|
||||
|
||||
createEventFlag("SceMdbgVrTriggerDump", 0x121, 0);
|
||||
}
|
||||
|
||||
static void createGnmCompositorObjects(orbis::Process *process) {
|
||||
createEventFlag("SceCompositorCrashEventFlags", 0x122, 0);
|
||||
createEventFlag("SceCompositorEventflag", 0x122, 0);
|
||||
createEventFlag("SceCompositorResetStatusEVF", 0x122, 0);
|
||||
|
||||
createShm("/tmp/SceHmd/Vr2d_shm_pass", 0xa02, 0x1b6, 16384);
|
||||
}
|
||||
|
||||
static void createShellCoreObjects(orbis::Process *process) {
|
||||
|
||||
// FIXME: replace with fmt library
|
||||
auto fmtHex = [](auto value, bool upperCase = false) {
|
||||
std::stringstream ss;
|
||||
ss << std::hex << std::setw(8) << std::setfill('0');
|
||||
if (upperCase) {
|
||||
ss << std::uppercase;
|
||||
}
|
||||
ss << value;
|
||||
return std::move(ss).str();
|
||||
};
|
||||
|
||||
createIpmiServer(process, "SceSystemLoggerService", unimplementedIpmiServer);
|
||||
createIpmiServer(process, "SceLoginMgrServer", unimplementedIpmiServer);
|
||||
createIpmiServer(process, "SceLncService", unimplementedIpmiServer);
|
||||
createIpmiServer(process, "SceAppMessaging", unimplementedIpmiServer);
|
||||
createIpmiServer(process, "SceShellCoreUtil", unimplementedIpmiServer);
|
||||
createIpmiServer(process, "SceNetCtl", unimplementedIpmiServer);
|
||||
createIpmiServer(process, "SceNpMgrIpc", unimplementedIpmiServer);
|
||||
createIpmiServer(process, "SceNpService", unimplementedIpmiServer);
|
||||
createIpmiServer(process, "SceNpTrophyIpc", unimplementedIpmiServer);
|
||||
createIpmiServer(process, "SceNpUdsIpc", unimplementedIpmiServer);
|
||||
createIpmiServer(process, "SceLibNpRifMgrIpc", unimplementedIpmiServer);
|
||||
createIpmiServer(process, "SceNpPartner001", unimplementedIpmiServer);
|
||||
createIpmiServer(process, "SceNpPartnerSubs", unimplementedIpmiServer);
|
||||
createIpmiServer(process, "SceNpGameIntent", unimplementedIpmiServer);
|
||||
createIpmiServer(process, "SceBgft", unimplementedIpmiServer);
|
||||
createIpmiServer(process, "SceCntMgrService", unimplementedIpmiServer);
|
||||
createIpmiServer(process, "ScePlayGo", unimplementedIpmiServer);
|
||||
createIpmiServer(process, "SceCompAppProxyUtil", unimplementedIpmiServer);
|
||||
createIpmiServer(process, "SceShareSpIpcService", unimplementedIpmiServer);
|
||||
createIpmiServer(process, "SceRnpsAppMgr", unimplementedIpmiServer);
|
||||
createIpmiServer(process, "SceUpdateService", unimplementedIpmiServer);
|
||||
createIpmiServer(process, "ScePatchChecker", unimplementedIpmiServer);
|
||||
createIpmiServer(process, "SceMorpheusUpdService", unimplementedIpmiServer);
|
||||
createIpmiServer(process, "ScePsmSharedDmem", unimplementedIpmiServer);
|
||||
createIpmiServer(process, "SceSaveData", unimplementedIpmiServer);
|
||||
createIpmiServer(process, "SceStickerCoreServer", unimplementedIpmiServer);
|
||||
createIpmiServer(process, "SceDbRecoveryShellCore", unimplementedIpmiServer);
|
||||
createIpmiServer(process, "SceUserService", unimplementedIpmiServer);
|
||||
createIpmiServer(process, "SceDbPreparationServer", unimplementedIpmiServer);
|
||||
createIpmiServer(process, "SceScreenShot", unimplementedIpmiServer);
|
||||
createIpmiServer(process, "SceAppDbIpc", unimplementedIpmiServer);
|
||||
createIpmiServer(process, "SceAppInst", unimplementedIpmiServer);
|
||||
createIpmiServer(process, "SceAppContent", unimplementedIpmiServer);
|
||||
createIpmiServer(process, "SceNpEntAccess", unimplementedIpmiServer);
|
||||
createIpmiServer(process, "SceMwIPMIServer", unimplementedIpmiServer);
|
||||
createIpmiServer(process, "SceAutoMounterIpc", unimplementedIpmiServer);
|
||||
createIpmiServer(process, "SceBackupRestoreUtil", unimplementedIpmiServer);
|
||||
createIpmiServer(process, "SceDataTransfer", unimplementedIpmiServer);
|
||||
createIpmiServer(process, "SceEventService", unimplementedIpmiServer);
|
||||
createIpmiServer(process, "SceShareFactoryUtil", unimplementedIpmiServer);
|
||||
createIpmiServer(process, "SceCloudConnectManager", unimplementedIpmiServer);
|
||||
createIpmiServer(process, "SceHubAppUtil", unimplementedIpmiServer);
|
||||
createIpmiServer(process, "SceTcIPMIServer", unimplementedIpmiServer);
|
||||
|
||||
createSemaphore("SceLncSuspendBlock00000001", 0x101, 1, 1);
|
||||
createSemaphore("SceAppMessaging00000001", 0x100, 0, 0x7fffffff);
|
||||
|
||||
createEventFlag("SceAutoMountUsbMass", 0x120, 0);
|
||||
createEventFlag("SceLoginMgrUtilityEventFlag", 0x112, 0);
|
||||
createEventFlag("SceLoginMgrSharePlayEventFlag", 0x112, 0);
|
||||
createEventFlag("SceLoginMgrServerHmdConnect", 0x112, 0);
|
||||
createEventFlag("SceLoginMgrServerDialogRequest", 0x112, 0);
|
||||
createEventFlag("SceLoginMgrServerDialogResponse", 0x112, 0);
|
||||
createEventFlag("SceGameLiveStreamingSpectator", 0x120, 0x8000000000000000);
|
||||
createEventFlag("SceGameLiveStreamingUserId", 0x120, 0x8000000000000000);
|
||||
createEventFlag("SceGameLiveStreamingMsgCount", 0x120, 0x8000000000000000);
|
||||
createEventFlag("SceGameLiveStreamingBCCtrl", 0x120, 0);
|
||||
createEventFlag("SceGameLiveStreamingEvntArg", 0x120, 0);
|
||||
createEventFlag("SceLncUtilSystemStatus", 0x120, 0);
|
||||
createEventFlag("SceShellCoreUtilRunLevel", 0x100, 0);
|
||||
createEventFlag("SceSystemStateMgrInfo", 0x120, 0x10000000a);
|
||||
createEventFlag("SceSystemStateMgrStatus", 0x120, 0);
|
||||
createEventFlag("SceAppInstallerEventFlag", 0x120, 0);
|
||||
createEventFlag("SceShellCoreUtilPowerControl", 0x120, 0xffff);
|
||||
createEventFlag("SceShellCoreUtilAppFocus", 0x120, -1);
|
||||
createEventFlag("SceShellCoreUtilCtrlFocus", 0x120, -1);
|
||||
createEventFlag("SceShellCoreUtilUIStatus", 0x120, 0x20001);
|
||||
createEventFlag("SceShellCoreUtilDevIdxBehavior", 0x120, 0);
|
||||
createEventFlag("SceNpMgrVshReq", 0x121, 0);
|
||||
createEventFlag("SceNpIdMapperVshReq", 0x121, 0);
|
||||
createEventFlag("SceRtcUtilTzdataUpdateFlag", 0x120, 0);
|
||||
createEventFlag("SceDataTransfer", 0x120, 0);
|
||||
createEventFlag("SceShellCoreUtilffffffff", 0x120, 0x3f8c);
|
||||
|
||||
createEventFlag("SceSysLogPullEvt_" + fmtHex(process->pid, true), 0x110, 0);
|
||||
createEventFlag("SceNpIdMapperEvf00" + fmtHex(process->pid), 0x121, 0);
|
||||
createEventFlag("SceNpBasicPreseEvf00" + fmtHex(process->pid), 0x121, 0);
|
||||
createEventFlag("SceNpPresenceEvf00" + fmtHex(process->pid), 0x121, 0);
|
||||
createEventFlag("SceNpInGameMsgEvf00" + fmtHex(process->pid), 0x121, 0);
|
||||
createEventFlag("SceNpPush2Evf00" + fmtHex(process->pid), 0x121, 0);
|
||||
createEventFlag("SceUserServiceGetEvent_" + fmtHex(process->pid), 0x110, 0);
|
||||
|
||||
createEventFlag("SceLncUtilAppStatus00000001", 0x100, 0);
|
||||
createEventFlag("SceAppMessaging00000001", 0x120, 0);
|
||||
|
||||
createShm("SceGlsSharedMemory", 0x202, 0x1a4, 262144);
|
||||
createShm("SceShellCoreUtil", 0x202, 0x1a4, 16384);
|
||||
createShm("SceNpTpip", 0x202, 0x1ff, 43008);
|
||||
}
|
||||
|
||||
int main(int argc, const char *argv[]) {
|
||||
if (argc == 2) {
|
||||
if (std::strcmp(argv[1], "-h") == 0 ||
|
||||
|
|
@ -860,6 +1124,14 @@ int main(int argc, const char *argv[]) {
|
|||
executableModule->type == rx::linker::kElfTypeExec) {
|
||||
ps4InitDev();
|
||||
ps4InitFd(mainThread);
|
||||
|
||||
if (!isSystem) {
|
||||
createSysAvControlObjects(initProcess);
|
||||
createSysCoreObjects(initProcess);
|
||||
createGnmCompositorObjects(initProcess);
|
||||
createShellCoreObjects(initProcess);
|
||||
}
|
||||
|
||||
std::vector<std::string> ps4Argv(argv + argIndex,
|
||||
argv + argIndex + argc - argIndex);
|
||||
status = ps4Exec(mainThread, std::move(executableModule), ps4Argv, {});
|
||||
|
|
|
|||
Loading…
Reference in a new issue