Exitspawn support renewal

Implemented _sys_process_exit2 syscall
Rewritten sys_game_process_exitspawn
Rewritten sys_game_process_exitspawn2
Implemented _sys_process_atexitspawn
Implemented _sys_process_at_Exitspawn
And some other changes
This commit is contained in:
Nekotekina 2017-09-18 19:16:36 +03:00
parent 18d472b7e1
commit 519f21db18
15 changed files with 285 additions and 198 deletions

View File

@ -179,31 +179,29 @@ s32 sceNpDrmGetTimelimit(vm::cptr<char> path, vm::ptr<u64> time_remain)
return CELL_OK;
}
s32 sceNpDrmProcessExitSpawn(vm::cptr<u8> klicensee, vm::cptr<char> path, u32 argv_addr, u32 envp_addr, u32 data_addr, u32 data_size, u32 prio, u64 flags)
s32 sceNpDrmProcessExitSpawn(ppu_thread& ppu, vm::cptr<u8> klicensee, vm::cptr<char> path, vm::cpptr<char> argv, vm::cpptr<char> envp, u32 data, u32 data_size, s32 prio, u64 flags)
{
sceNp.warning("sceNpDrmProcessExitSpawn(klicensee=*0x%x, path=%s, argv=*0x%x, envp=*0x%x, data=*0x%x, data_size=0x%x, prio=%u, flags=0x%x)",
klicensee, path, argv_addr, envp_addr, data_addr, data_size, prio, flags);
sceNp.warning("sceNpDrmProcessExitSpawn(klicensee=*0x%x, path=%s, argv=**0x%x, envp=**0x%x, data=*0x%x, data_size=0x%x, prio=%d, flags=0x%x)", klicensee, path, argv, envp, data, data_size, prio, flags);
if (s32 error = npDrmIsAvailable(klicensee, path))
{
return error;
}
sys_game_process_exitspawn(path, argv_addr, envp_addr, data_addr, data_size, prio, flags);
sys_game_process_exitspawn(ppu, path, argv, envp, data, data_size, prio, flags);
return CELL_OK;
}
s32 sceNpDrmProcessExitSpawn2(vm::cptr<u8> klicensee, vm::cptr<char> path, u32 argv_addr, u32 envp_addr, u32 data_addr, u32 data_size, u32 prio, u64 flags)
s32 sceNpDrmProcessExitSpawn2(ppu_thread& ppu, vm::cptr<u8> klicensee, vm::cptr<char> path, vm::cpptr<char> argv, vm::cpptr<char> envp, u32 data, u32 data_size, s32 prio, u64 flags)
{
sceNp.warning("sceNpDrmProcessExitSpawn2(klicensee=*0x%x, path=%s, argv=*0x%x, envp=*0x%x, data=*0x%x, data_size=0x%x, prio=%u, flags=0x%x)",
klicensee, path, argv_addr, envp_addr, data_addr, data_size, prio, flags);
sceNp.warning("sceNpDrmProcessExitSpawn2(klicensee=*0x%x, path=%s, argv=**0x%x, envp=**0x%x, data=*0x%x, data_size=0x%x, prio=%d, flags=0x%x)", klicensee, path, argv, envp, data, data_size, prio, flags);
if (s32 error = npDrmIsAvailable(klicensee, path))
{
return error;
}
sys_game_process_exitspawn2(path, argv_addr, envp_addr, data_addr, data_size, prio, flags);
sys_game_process_exitspawn2(ppu, path, argv, envp, data, data_size, prio, flags);
return CELL_OK;
}

View File

@ -2,6 +2,7 @@
#include "Emu/System.h"
#include "Emu/Cell/PPUModule.h"
#include "Emu/Cell/lv2/sys_mutex.h"
#include "Emu/Cell/lv2/sys_interrupt.h"
#include "Emu/Cell/lv2/sys_process.h"
#include "sysPrxForUser.h"
@ -13,6 +14,9 @@ extern u64 get_system_time();
extern fs::file g_tty;
vm::gvar<s32> sys_prx_version; // ???
vm::gvar<vm::ptr<void()>> g_ppu_atexitspawn;
vm::gvar<vm::ptr<void()>> g_ppu_at_Exitspawn;
extern vm::gvar<u32> g_ppu_exit_mutex;
s64 sys_time_get_system_time()
{
@ -21,33 +25,34 @@ s64 sys_time_get_system_time()
return get_system_time();
}
s32 sys_process_exit(ppu_thread& ppu, s32 status)
void sys_process_exit(ppu_thread& ppu, s32 status)
{
vm::temporary_unlock(ppu);
sysPrxForUser.warning("sys_process_exit(status=%d)", status);
Emu.CallAfter([]()
sys_mutex_lock(ppu, *g_ppu_exit_mutex, 0);
// TODO (process atexit)
return _sys_process_exit(ppu, status, 0, 0);
}
void _sys_process_atexitspawn(vm::ptr<void()> func)
{
sysPrxForUser.warning("_sys_process_atexitspawn(0x%x)", func);
if (!*g_ppu_atexitspawn)
{
sysPrxForUser.success("Process finished");
Emu.Stop();
});
thread_ctrl::eternalize();
return CELL_OK;
*g_ppu_atexitspawn = func;
}
}
s64 _sys_process_atexitspawn()
void _sys_process_at_Exitspawn(vm::ptr<void()> func)
{
sysPrxForUser.todo("_sys_process_atexitspawn()");
return CELL_OK;
}
sysPrxForUser.warning("_sys_process_at_Exitspawn(0x%x)", func);
s64 _sys_process_at_Exitspawn()
{
sysPrxForUser.todo("_sys_process_at_Exitspawn");
return CELL_OK;
if (!*g_ppu_at_Exitspawn)
{
*g_ppu_at_Exitspawn = func;
}
}
s32 sys_process_is_stack(u32 p)
@ -244,6 +249,8 @@ DECLARE(ppu_module_manager::sysPrxForUser)("sysPrxForUser", []()
sysPrxForUser_sys_rsxaudio_init();
REG_VAR(sysPrxForUser, sys_prx_version); // 0x7df066cf
REG_VAR(sysPrxForUser, g_ppu_atexitspawn).flag(MFF_HIDDEN);
REG_VAR(sysPrxForUser, g_ppu_at_Exitspawn).flag(MFF_HIDDEN);
REG_FUNC(sysPrxForUser, sys_time_get_system_time);

View File

@ -53,5 +53,5 @@ error_code sys_lwcond_signal_to(ppu_thread& CPU, vm::ptr<sys_lwcond_t> lwcond, u
error_code sys_lwcond_wait(ppu_thread& CPU, vm::ptr<sys_lwcond_t> lwcond, u64 timeout);
void sys_ppu_thread_exit(ppu_thread& CPU, u64 val);
void sys_game_process_exitspawn(vm::cptr<char> path, u32 argv_addr, u32 envp_addr, u32 data_addr, u32 data_size, u32 prio, u64 flags);
void sys_game_process_exitspawn2(vm::cptr<char> path, u32 argv_addr, u32 envp_addr, u32 data_addr, u32 data_size, u32 prio, u64 flags);
void sys_game_process_exitspawn(ppu_thread& ppu, vm::cptr<char> path, vm::cpptr<char> argv, vm::cpptr<char> envp, u32 data, u32 data_size, s32 prio, u64 flags);
void sys_game_process_exitspawn2(ppu_thread& ppu, vm::cptr<char> path, vm::cpptr<char> argv, vm::cpptr<char> envp, u32 data, u32 data_size, s32 prio, u64 flags);

View File

@ -2,148 +2,153 @@
#include "Emu/System.h"
#include "Emu/Cell/PPUModule.h"
#include "Emu/Cell/lv2/sys_mutex.h"
#include "Emu/Cell/lv2/sys_process.h"
#include "sysPrxForUser.h"
extern logs::channel sysPrxForUser;
extern vm::gvar<u32> g_ppu_exit_mutex;
extern vm::gvar<vm::ptr<void()>> g_ppu_atexitspawn;
extern vm::gvar<vm::ptr<void()>> g_ppu_at_Exitspawn;
void sys_game_process_exitspawn(vm::cptr<char> path, u32 argv_addr, u32 envp_addr, u32 data_addr, u32 data_size, u32 prio, u64 flags)
static u32 get_string_array_size(vm::cpptr<char> list, u32& out_count)
{
std::string _path = path.get_ptr();
const std::string& from = "//";
const std::string& to = "/";
//out_count = 0;
u32 result = 8;
size_t start_pos = 0;
while ((start_pos = _path.find(from, start_pos)) != std::string::npos) {
_path.replace(start_pos, from.length(), to);
start_pos += to.length();
for (u32 i = 0; list; i++)
{
if (const vm::cptr<char> str = list[i])
{
out_count++;
result += (((u32)std::strlen(str.get_ptr()) + 0x10) & -0x10) + 8;
continue;
}
break;
}
sysPrxForUser.todo("sys_game_process_exitspawn()");
sysPrxForUser.warning("path: %s", _path.c_str());
sysPrxForUser.warning("argv: 0x%x", argv_addr);
sysPrxForUser.warning("envp: 0x%x", envp_addr);
sysPrxForUser.warning("data: 0x%x", data_addr);
sysPrxForUser.warning("data_size: 0x%x", data_size);
sysPrxForUser.warning("prio: %d", prio);
sysPrxForUser.warning("flags: %d", flags);
std::vector<std::string> argv;
std::vector<std::string> env;
if (argv_addr)
{
auto argvp = vm::cpptr<char>::make(argv_addr);
while (argvp && *argvp)
{
argv.push_back(argvp[0].get_ptr());
argvp++;
}
for (auto &arg : argv)
{
sysPrxForUser.trace("argument: %s", arg.c_str());
}
}
if (envp_addr)
{
auto envp = vm::cpptr<char>::make(envp_addr);
while (envp && *envp)
{
env.push_back(envp[0].get_ptr());
envp++;
}
for (auto &en : env)
{
sysPrxForUser.trace("env_argument: %s", en.c_str());
}
}
// TODO: execute the file in <path> with the args in argv
// and the environment parameters in envp and copy the data
// from data_addr into the adress space of the new process
// then kill the current process
Emu.Pause();
sysPrxForUser.success("Process finished");
Emu.CallAfter([=, path = vfs::get(_path)]()
{
Emu.Stop();
Emu.BootGame(path, true);
});
return result;
}
void sys_game_process_exitspawn2(vm::cptr<char> path, u32 argv_addr, u32 envp_addr, u32 data_addr, u32 data_size, u32 prio, u64 flags)
static u32 get_exitspawn_size(vm::cptr<char> path, vm::cpptr<char> argv, vm::cpptr<char> envp, u32& arg_count, u32& env_count)
{
std::string _path = path.get_ptr();
const std::string& from = "//";
const std::string& to = "/";
arg_count = 1;
env_count = 0;
size_t start_pos = 0;
while ((start_pos = _path.find(from, start_pos)) != std::string::npos) {
_path.replace(start_pos, from.length(), to);
start_pos += to.length();
u32 result = (((u32)std::strlen(path.get_ptr()) + 0x10) & -0x10) + 8;
result += get_string_array_size(argv, arg_count);
result += get_string_array_size(envp, env_count);
if ((arg_count + env_count) % 2)
{
result += 8;
}
sysPrxForUser.warning("sys_game_process_exitspawn2()");
sysPrxForUser.warning("path: %s", _path.c_str());
sysPrxForUser.warning("argv: 0x%x", argv_addr);
sysPrxForUser.warning("envp: 0x%x", envp_addr);
sysPrxForUser.warning("data: 0x%x", data_addr);
sysPrxForUser.warning("data_size: 0x%x", data_size);
sysPrxForUser.warning("prio: %d", prio);
sysPrxForUser.warning("flags: %d", flags);
return result;
}
std::vector<std::string> argv;
std::vector<std::string> env;
if (argv_addr)
static void put_string_array(vm::pptr<char, u32, u64> pstr, vm::ptr<char>& str, u32 count, vm::cpptr<char> list)
{
for (u32 i = 0; i < count; i++)
{
auto argvp = vm::cpptr<char>::make(argv_addr);
while (argvp && *argvp)
{
argv.push_back(argvp[0].get_ptr());
argvp++;
}
for (auto &arg : argv)
{
sysPrxForUser.trace("argument: %s", arg.c_str());
}
const u32 len = (u32)std::strlen(list[i].get_ptr());
std::memcpy(str.get_ptr(), list[i].get_ptr(), len + 1);
pstr[i] = str;
str += (len + 0x10) & -0x10;
}
if (envp_addr)
{
auto envp = vm::cpptr<char>::make(envp_addr);
while (envp && *envp)
{
env.push_back(envp[0].get_ptr());
envp++;
}
pstr[count] = vm::null;
}
for (auto &en : env)
{
sysPrxForUser.trace("env_argument: %s", en.c_str());
}
static void put_exitspawn(vm::ptr<void> out, vm::cptr<char> path, u32 argc, vm::cpptr<char> argv, u32 envc, vm::cpptr<char> envp)
{
vm::pptr<char, u32, u64> pstr = vm::cast(out.addr());
vm::ptr<char> str = vm::static_ptr_cast<char>(out) + (argc + envc + (argc + envc) % 2) * 8 + 0x10;
const u32 len = (u32)std::strlen(path.get_ptr());
std::memcpy(str.get_ptr(), path.get_ptr(), len + 1);
*pstr++ = str;
str += (len + 0x10) & -0x10;
put_string_array(pstr, str, argc - 1, argv);
put_string_array(pstr + argc, str, envc, envp);
}
static void exitspawn(ppu_thread& ppu, vm::cptr<char> path, vm::cpptr<char> argv, vm::cpptr<char> envp, u32 data, u32 data_size, s32 prio, u64 _flags)
{
sys_mutex_lock(ppu, *g_ppu_exit_mutex, 0);
u32 arg_count = 0;
u32 env_count = 0;
u32 alloc_size = get_exitspawn_size(path, argv, envp, arg_count, env_count);
if (alloc_size > 0x1000)
{
argv = vm::null;
envp = vm::null;
arg_count = 0;
env_count = 0;
alloc_size = get_exitspawn_size(path, vm::null, vm::null, arg_count, env_count);
}
// TODO: execute the file in <path> with the args in argv
// and the environment parameters in envp and copy the data
// from data_addr into the adress space of the new process
// then kill the current process
alloc_size += 0x30;
Emu.Pause();
sysPrxForUser.success("Process finished");
Emu.CallAfter([=, path = vfs::get(_path)]()
if (data_size > 0)
{
Emu.Stop();
Emu.BootGame(path, true);
});
alloc_size += 0x1030;
}
return;
u32 alloc_addr = vm::alloc(alloc_size, vm::main);
if (!alloc_addr)
{
// TODO (process atexit)
return _sys_process_exit(ppu, CELL_ENOMEM, 0, 0);
}
put_exitspawn(vm::cast(alloc_addr + 0x30), path, arg_count, argv, env_count, envp);
if (data_size)
{
std::memcpy(vm::base(alloc_addr + alloc_size - 0x1000), vm::base(data), std::min<u32>(data_size, 0x1000));
}
vm::ptr<sys_exit2_param> arg = vm::cast(alloc_addr);
arg->x0 = 0x85;
arg->this_size = 0x30;
arg->next_size = alloc_size - 0x30;
arg->prio = prio;
arg->flags = _flags;
arg->args = vm::cast(alloc_addr + 0x30);
if ((_flags >> 62) == 0 && *g_ppu_atexitspawn)
{
// Execute atexitspawn
g_ppu_atexitspawn->operator()(ppu);
}
if ((_flags >> 62) == 1 && *g_ppu_at_Exitspawn)
{
// Execute at_Exitspawn
g_ppu_at_Exitspawn->operator()(ppu);
}
// TODO (process atexit)
return _sys_process_exit2(ppu, 0, arg, alloc_size, 0x10000000);
}
void sys_game_process_exitspawn(ppu_thread& ppu, vm::cptr<char> path, vm::cpptr<char> argv, vm::cpptr<char> envp, u32 data, u32 data_size, s32 prio, u64 flags)
{
sysPrxForUser.warning("sys_game_process_exitspawn(path=%s, argv=**0x%x, envp=**0x%x, data=*0x%x, data_size=0x%x, prio=%d, flags=0x%x)", path, argv, envp, data, data_size, prio, flags);
return exitspawn(ppu, path, argv, envp, data, data_size, prio, (flags & 0xf0) | (1ull << 63));
}
void sys_game_process_exitspawn2(ppu_thread& ppu, vm::cptr<char> path, vm::cpptr<char> argv, vm::cpptr<char> envp, u32 data, u32 data_size, s32 prio, u64 flags)
{
sysPrxForUser.warning("sys_game_process_exitspawn2(path=%s, argv=**0x%x, envp=**0x%x, data=*0x%x, data_size=0x%x, prio=%d, flags=0x%x)", path, argv, envp, data, data_size, prio, flags);
return exitspawn(ppu, path, argv, envp, data, data_size, prio, (flags >> 62) >= 2 ? flags & 0xf0 : flags & 0xc0000000000000f0ull);
}
s32 sys_game_board_storage_read()

View File

@ -13,6 +13,7 @@ extern logs::channel sysPrxForUser;
vm::gvar<sys_lwmutex_t> g_ppu_atexit_lwm;
vm::gvar<vm::ptr<void()>[8]> g_ppu_atexit;
vm::gvar<u32> g_ppu_exit_mutex; // sys_process_exit2 mutex
vm::gvar<u32> g_ppu_once_mutex;
vm::gvar<sys_lwmutex_t> g_ppu_prx_lwm;
@ -112,6 +113,10 @@ void sys_initialize_tls(ppu_thread& ppu, u64 main_thread_id, u32 tls_seg_addr, u
attr->name_u64 = "_lv2ppu\0"_u64;
sys_mutex_create(g_ppu_once_mutex, attr);
attr->recursive = SYS_SYNC_RECURSIVE;
attr->name_u64 = "_lv2tls\0"_u64;
sys_mutex_create(g_ppu_exit_mutex, attr);
lwa->protocol = SYS_SYNC_PRIORITY;
lwa->recursive = SYS_SYNC_RECURSIVE;
lwa->name_u64 = "_lv2prx\0"_u64;
@ -270,6 +275,7 @@ void sysPrxForUser_sys_ppu_thread_init()
REG_VAR(sysPrxForUser, g_ppu_once_mutex).flag(MFF_HIDDEN);
REG_VAR(sysPrxForUser, g_ppu_atexit).flag(MFF_HIDDEN);
REG_VAR(sysPrxForUser, g_ppu_prx_lwm).flag(MFF_HIDDEN);
REG_VAR(sysPrxForUser, g_ppu_exit_mutex).flag(MFF_HIDDEN);
REG_FUNC(sysPrxForUser, sys_initialize_tls).args = {"main_thread_id", "tls_seg_addr", "tls_seg_size", "tls_mem_size"}; // Test
REG_FUNC(sysPrxForUser, sys_ppu_thread_create);

View File

@ -1360,7 +1360,7 @@ void ppu_load_exec(const ppu_exec_object& elf)
// Set path (TODO)
_main->name = "";
_main->path = vfs::get(Emu.GetPath());
_main->path = vfs::get(Emu.argv[0]);
// Analyse executable (TODO)
_main->analyse(0, static_cast<u32>(elf.header.e_entry));
@ -1372,27 +1372,42 @@ void ppu_load_exec(const ppu_exec_object& elf)
g_ps3_sdk_version = sdk_version;
// Initialize process arguments
std::initializer_list<std::string> args = { Emu.GetPath()/*, "-emu"s*/ };
auto args = vm::ptr<u64>::make(vm::alloc(SIZE_32(u64) * (::size32(Emu.argv) + ::size32(Emu.envp) + 2), vm::main));
auto argv = args;
auto argv = vm::ptr<u64>::make(vm::alloc(SIZE_32(u64) * ::size32(args), vm::main));
auto envp = vm::ptr<u64>::make(vm::alloc(::align(SIZE_32(u64), 0x10), vm::main));
*envp = 0;
for (const auto& arg : args)
for (const auto& arg : Emu.argv)
{
const u32 arg_size = ::align(::size32(arg) + 1, 0x10);
const u32 arg_addr = vm::alloc(arg_size, vm::main);
std::memcpy(vm::base(arg_addr), arg.data(), arg_size);
*argv++ = arg_addr;
*args++ = arg_addr;
}
argv -= ::size32(args);
*args++ = 0;
auto envp = args;
for (const auto& arg : Emu.envp)
{
const u32 arg_size = ::align(::size32(arg) + 1, 0x10);
const u32 arg_addr = vm::alloc(arg_size, vm::main);
std::memcpy(vm::base(arg_addr), arg.data(), arg_size);
*args++ = arg_addr;
}
// Initialize main thread
auto ppu = idm::make_ptr<ppu_thread>("main_thread", primary_prio, primary_stacksize);
// Write initial data (exitspawn)
if (Emu.data.size())
{
std::memcpy(vm::base(ppu->stack_addr + ppu->stack_size - ::size32(Emu.data)), Emu.data.data(), Emu.data.size());
ppu->gpr[1] -= Emu.data.size();
}
ppu->cmd_push({ppu_cmd::initialize, 0});
// TODO: adjust for liblv2 loading option
@ -1434,7 +1449,7 @@ void ppu_load_exec(const ppu_exec_object& elf)
// Set command line arguments, run entry function
ppu->cmd_list
({
{ ppu_cmd::set_args, 8 }, u64{args.size()}, u64{argv.addr()}, u64{envp.addr()}, u64{0}, u64{ppu->id}, u64{tls_vaddr}, u64{tls_fsize}, u64{tls_vsize},
{ ppu_cmd::set_args, 8 }, u64{Emu.argv.size()}, u64{argv.addr()}, u64{envp.addr()}, u64{0}, u64{ppu->id}, u64{tls_vaddr}, u64{tls_fsize}, u64{tls_vsize},
{ ppu_cmd::set_gpr, 11 }, u64{elf.header.e_entry},
{ ppu_cmd::set_gpr, 12 }, u64{malloc_pagesize},
{ ppu_cmd::lle_call, entry },

View File

@ -233,7 +233,7 @@ s32 sys_process_detach_child(u64 unk)
return CELL_OK;
}
s32 _sys_process_exit(ppu_thread& ppu, s32 status, u32 arg2, u32 arg3)
void _sys_process_exit(ppu_thread& ppu, s32 status, u32 arg2, u32 arg3)
{
vm::temporary_unlock(ppu);
@ -248,7 +248,60 @@ s32 _sys_process_exit(ppu_thread& ppu, s32 status, u32 arg2, u32 arg3)
thread_ctrl::eternalize();
}
s32 _sys_process_exit2(ppu_thread& ppu, s32 status, u32 arg2, u32 arg3, u32 arg4)
void _sys_process_exit2(ppu_thread& ppu, s32 status, vm::ptr<sys_exit2_param> arg, u32 arg_size, u32 arg4)
{
fmt::throw_exception("_sys_process_exit2");
sys_process.warning("_sys_process_exit2(status=%d, arg=*0x%x, arg_size=0x%x, arg4=0x%x)", status, arg, arg_size, arg4);
auto pstr = +arg->args;
std::vector<std::string> argv;
std::vector<std::string> envp;
while (auto ptr = *pstr++)
{
argv.emplace_back(ptr.get_ptr());
sys_process.notice(" *** arg: %s", ptr);
}
while (auto ptr = *pstr++)
{
envp.emplace_back(ptr.get_ptr());
sys_process.notice(" *** env: %s", ptr);
}
std::vector<u8> data;
if (arg_size > 0x1030)
{
data.resize(0x1000);
std::memcpy(data.data(), vm::base(arg.addr() + arg_size - 0x1000), 0x1000);
}
if (argv.empty())
{
return _sys_process_exit(ppu, status, 0, 0);
}
// TODO: set prio, flags
std::string path = vfs::get(argv[0]);
vm::temporary_unlock(ppu);
Emu.CallAfter([path = std::move(path), argv = std::move(argv), envp = std::move(envp), data = std::move(data)]()
{
sys_process.success("Process finished -> %s", argv[0]);
Emu.Stop();
Emu.argv = std::move(argv);
Emu.envp = std::move(envp);
Emu.data = std::move(data);
Emu.BootGame(path, true);
if (Emu.IsReady() && !g_cfg.misc.autostart)
{
Emu.Run();
}
});
thread_ctrl::eternalize();
}

View File

@ -23,6 +23,16 @@ enum : u32
SYS_EVENT_FLAG_OBJECT = 0x98,
};
struct sys_exit2_param
{
be_t<u64> x0; // 0x85
be_t<u64> this_size; // 0x30
be_t<u64> next_size;
be_t<s64> prio;
be_t<u64> flags;
vm::ps3::bpptr<char, u64, u64> args;
};
// Auxiliary functions
s32 process_getpid();
s32 process_get_sdk_version(u32 pid, s32& ver);
@ -41,5 +51,5 @@ s32 sys_process_kill(u32 pid);
s32 sys_process_wait_for_child(u32 pid, vm::ps3::ptr<u32> status, u64 unk);
s32 sys_process_wait_for_child2(u64 unk1, u64 unk2, u64 unk3, u64 unk4, u64 unk5, u64 unk6);
s32 sys_process_detach_child(u64 unk);
s32 _sys_process_exit(ppu_thread& ppu, s32 status, u32 arg2, u32 arg3);
s32 _sys_process_exit2(ppu_thread& ppu, s32 status, u32 arg2, u32 arg3, u32 arg4);
void _sys_process_exit(ppu_thread& ppu, s32 status, u32 arg2, u32 arg3);
void _sys_process_exit2(ppu_thread& ppu, s32 status, vm::ps3::ptr<sys_exit2_param> arg, u32 arg_size, u32 arg4);

View File

@ -587,7 +587,7 @@ void arm_load_exec(const arm_exec_object& elf)
// Initialize args
std::vector<char> argv_data;
for (const auto& arg : { Emu.GetPath(), "-emu"s })
for (const auto& arg : Emu.argv)
{
argv_data.insert(argv_data.end(), arg.begin(), arg.end());
argv_data.insert(argv_data.end(), '\0');

View File

@ -228,12 +228,6 @@ void Emulator::Init()
fxm::make_always<patch_engine>()->append(fs::get_config_dir() + "/patch.yml");
}
void Emulator::SetPath(const std::string& path, const std::string& elf_path)
{
m_path = path;
m_elf_path = elf_path;
}
bool Emulator::BootGame(const std::string& path, bool direct, bool add_only)
{
static const char* boot_list[] =
@ -246,7 +240,7 @@ bool Emulator::BootGame(const std::string& path, bool direct, bool add_only)
if (direct && fs::is_file(path))
{
SetPath(path);
m_path = path;
Load(add_only);
return true;
@ -258,7 +252,7 @@ bool Emulator::BootGame(const std::string& path, bool direct, bool add_only)
if (fs::is_file(elf))
{
SetPath(elf);
m_path = elf;
Load(add_only);
return true;
@ -380,7 +374,7 @@ void Emulator::Load(bool add_only)
if (fs::rename(elf_dir + "/../../", hdd0_disc + elf_dir.substr(hdd0_game.size()) + "/../../", false))
{
LOG_SUCCESS(LOADER, "Disc game %s moved to special location /dev_hdd0/disc/", m_title_id);
return SetPath(hdd0_disc + m_path.substr(hdd0_game.size())), Load();
return m_path = hdd0_disc + m_path.substr(hdd0_game.size()), Load();
}
else
{
@ -460,7 +454,7 @@ void Emulator::Load(bool add_only)
{
// Booting game update
LOG_SUCCESS(LOADER, "Updates found at /dev_hdd0/game/%s/!", m_title_id);
return SetPath(hdd0_boot), Load();
return m_path = hdd0_boot, Load();
}
// Mount /host_root/ if necessary
@ -528,25 +522,25 @@ void Emulator::Load(bool add_only)
vm::ps3::init();
if (m_elf_path.empty())
if (argv.empty())
{
if (m_path.find(hdd0_game) != -1)
{
m_elf_path = "/dev_hdd0/game/" + m_path.substr(hdd0_game.size());
argv.emplace_back("/dev_hdd0/game/" + m_path.substr(hdd0_game.size()));
}
else if (!bdvd_dir.empty() && fs::is_dir(bdvd_dir))
{
//Disc games are on /dev_bdvd/
size_t pos = m_path.rfind("PS3_GAME");
m_elf_path = "/dev_bdvd/" + m_path.substr(pos);
// Disc games are on /dev_bdvd/
const std::size_t pos = m_path.rfind("PS3_GAME");
argv.emplace_back("/dev_bdvd/" + m_path.substr(pos));
}
else
{
//For homebrew
m_elf_path = "/host_root/" + m_path;
// For homebrew
argv.emplace_back("/host_root/" + m_path);
}
LOG_NOTICE(LOADER, "Elf path: %s", m_elf_path);
LOG_NOTICE(LOADER, "Elf path: %s", argv[0]);
}
ppu_load_exec(ppu_exec);
@ -579,10 +573,10 @@ void Emulator::Load(bool add_only)
GetCallbacks().on_ready();
vm::psv::init();
if (m_elf_path.empty())
if (argv.empty())
{
m_elf_path = "host_root:" + m_path;
LOG_NOTICE(LOADER, "Elf path: %s", m_elf_path);
argv.emplace_back("host_root:" + m_path);
LOG_NOTICE(LOADER, "Elf path: %s", argv[0]);
}
arm_load_exec(arm_exec);
@ -794,6 +788,10 @@ void Emulator::Stop()
extern void jit_finalize();
jit_finalize();
#endif
argv.clear();
envp.clear();
data.clear();
}
s32 error_code::error_report(const fmt_type_info* sup, u64 arg, const fmt_type_info* sup2, u64 arg2)

View File

@ -177,7 +177,6 @@ class Emulator final
atomic_t<u64> m_pause_amend_time; // increased when resumed
std::string m_path;
std::string m_elf_path;
std::string m_cache_path;
std::string m_title_id;
std::string m_title;
@ -210,12 +209,10 @@ public:
}
void Init();
void SetPath(const std::string& path, const std::string& elf_path = {});
const std::string& GetPath() const
{
return m_elf_path;
}
std::vector<std::string> argv;
std::vector<std::string> envp;
std::vector<u8> data;
const std::string& GetBoot() const
{

View File

@ -60,8 +60,7 @@ int main(int argc, char** argv)
// Ugly workaround
QTimer::singleShot(2, [path = sstr(QFileInfo(parser.positionalArguments().at(0)).canonicalFilePath())]
{
Emu.SetPath(path);
Emu.Load();
Emu.BootGame(path, true);
Emu.Run();
});
}

View File

@ -140,8 +140,7 @@ UTILS_DLL_C_EXPORT ps3emu_api_error_code ps3emu_api_load_elf(const char *path)
return ps3emu_api_not_found;
}
Emu.SetPath(path);
Emu.Load();
Emu.BootGame(path, true);
return ps3emu_api_ok;
}

View File

@ -84,7 +84,7 @@ void gs_frame::keyPressEvent(QKeyEvent *keyEvent)
if (keyEvent->modifiers() == Qt::ControlModifier && (!Emu.IsStopped())) { Emu.Stop(); return; }
break;
case Qt::Key_R:
if (keyEvent->modifiers() == Qt::ControlModifier && (!Emu.GetPath().empty())) { Emu.Stop(); Emu.Load(); return; }
if (keyEvent->modifiers() == Qt::ControlModifier && (!Emu.GetBoot().empty())) { Emu.Stop(); Emu.Load(); return; }
break;
case Qt::Key_E:
if (keyEvent->modifiers() == Qt::ControlModifier)

View File

@ -61,7 +61,7 @@ auto Pause = []()
if (Emu.IsReady()) Emu.Run();
else if (Emu.IsPaused()) Emu.Resume();
else if (Emu.IsRunning()) Emu.Pause();
else if (!Emu.GetPath().empty()) Emu.Load();
else if (!Emu.GetBoot().empty()) Emu.Load();
};
/* An init method is used so that RPCS3App can create the necessary connects before calling init (specifically the stylesheet connect).
@ -745,7 +745,7 @@ void main_window::RepaintToolBarIcons()
{
ui->toolbar_start->setIcon(m_icon_pause);
}
else if (Emu.IsStopped() && !Emu.GetPath().empty())
else if (Emu.IsStopped() && !Emu.GetBoot().empty())
{
ui->toolbar_start->setIcon(m_icon_restart);
}
@ -817,7 +817,7 @@ void main_window::OnEmuStop()
m_thumb_playPause->setIcon(m_icon_thumb_play);
#endif
EnableMenus(false);
if (!Emu.GetPath().empty())
if (!Emu.GetBoot().empty())
{
ui->toolbar_start->setEnabled(true);
ui->toolbar_start->setIcon(m_icon_restart);
@ -1564,7 +1564,7 @@ void main_window::keyPressEvent(QKeyEvent *keyEvent)
case Qt::Key_E: if (Emu.IsPaused()) Emu.Resume(); else if (Emu.IsReady()) Emu.Run(); return;
case Qt::Key_P: if (Emu.IsRunning()) Emu.Pause(); return;
case Qt::Key_S: if (!Emu.IsStopped()) Emu.Stop(); return;
case Qt::Key_R: if (!Emu.GetPath().empty()) { Emu.Stop(); Emu.Run(); } return;
case Qt::Key_R: if (!Emu.GetBoot().empty()) { Emu.Stop(); Emu.Run(); } return;
}
}
}