rpcsx/rpcs3/Emu/Cell/lv2/sys_prx.cpp
Ani e57caefd09 libad: Enable LLE load
Removes libad from ignore list.

It will only affect games that call for it, making them progress further with the Recompiler instead of dying in Unregistered Function, as there's no HLE implementation of libad.

Tested with Guitar Hero 5 [BLES00576]
2017-09-01 21:10:50 +01:00

375 lines
12 KiB
C++

#include "stdafx.h"
#include "Emu/Memory/Memory.h"
#include "Emu/System.h"
#include "Emu/IdManager.h"
#include "Crypto/unself.h"
#include "Loader/ELF.h"
#include "Emu/Cell/ErrorCodes.h"
#include "Crypto/unedat.h"
#include "sys_prx.h"
namespace vm { using namespace ps3; }
extern std::shared_ptr<lv2_prx> ppu_load_prx(const ppu_prx_object&, const std::string&);
extern void ppu_unload_prx(const lv2_prx& prx);
extern void ppu_initialize(const ppu_module&);
logs::channel sys_prx("sys_prx");
static const std::unordered_map<std::string, int> s_prx_ignore
{
{ "/dev_flash/sys/external/libaudio.sprx", 0 },
{ "/dev_flash/sys/external/libbeisobmf.sprx", 0 },
{ "/dev_flash/sys/external/libcamera.sprx", 0 },
{ "/dev_flash/sys/external/libgem.sprx", 0 },
{ "/dev_flash/sys/external/libhttp.sprx", 0 },
{ "/dev_flash/sys/external/libio.sprx", 0 },
{ "/dev_flash/sys/external/libmedi.sprx", 0 },
{ "/dev_flash/sys/external/libmic.sprx", 0 },
{ "/dev_flash/sys/external/libnet.sprx", 0 },
{ "/dev_flash/sys/external/libnetctl.sprx", 0 },
{ "/dev_flash/sys/external/librudp.sprx", 0 },
{ "/dev_flash/sys/external/libssl.sprx", 0 },
{ "/dev_flash/sys/external/libsysutil.sprx", 0 },
{ "/dev_flash/sys/external/libsysutil_ap.sprx", 0 },
{ "/dev_flash/sys/external/libsysutil_authdialog.sprx", 0 },
{ "/dev_flash/sys/external/libsysutil_avc_ext.sprx", 0 },
{ "/dev_flash/sys/external/libsysutil_avc2.sprx", 0 },
{ "/dev_flash/sys/external/libsysutil_avconf_ext.sprx", 0 },
{ "/dev_flash/sys/external/libsysutil_bgdl.sprx", 0 },
{ "/dev_flash/sys/external/libsysutil_cross_controller.sprx", 0 },
{ "/dev_flash/sys/external/libsysutil_dec_psnvideo.sprx", 0 },
{ "/dev_flash/sys/external/libsysutil_dtcp_ip.sprx", 0 },
{ "/dev_flash/sys/external/libsysutil_game.sprx", 0 },
{ "/dev_flash/sys/external/libsysutil_game_exec.sprx", 0 },
{ "/dev_flash/sys/external/libsysutil_imejp.sprx", 0 },
{ "/dev_flash/sys/external/libsysutil_misc.sprx", 0 },
{ "/dev_flash/sys/external/libsysutil_music.sprx", 0 },
{ "/dev_flash/sys/external/libsysutil_music_decode.sprx", 0 },
{ "/dev_flash/sys/external/libsysutil_music_export.sprx", 0 },
{ "/dev_flash/sys/external/libsysutil_np.sprx", 0 },
{ "/dev_flash/sys/external/libsysutil_np_clans.sprx", 0 },
{ "/dev_flash/sys/external/libsysutil_np_commerce2.sprx", 0 },
{ "/dev_flash/sys/external/libsysutil_np_eula.sprx", 0 },
{ "/dev_flash/sys/external/libsysutil_np_installer.sprx", 0 },
{ "/dev_flash/sys/external/libsysutil_np_sns.sprx", 0 },
{ "/dev_flash/sys/external/libsysutil_np_trophy.sprx", 0 },
{ "/dev_flash/sys/external/libsysutil_np_tus.sprx", 0 },
{ "/dev_flash/sys/external/libsysutil_np_util.sprx", 0 },
{ "/dev_flash/sys/external/libsysutil_np2.sprx", 0 },
{ "/dev_flash/sys/external/libsysutil_oskdialog_ext.sprx", 0 },
{ "/dev_flash/sys/external/libsysutil_pesm.sprx", 0 },
{ "/dev_flash/sys/external/libsysutil_photo_decode.sprx", 0 },
{ "/dev_flash/sys/external/libsysutil_photo_export.sprx", 0 },
{ "/dev_flash/sys/external/libsysutil_photo_export2.sprx", 0 },
{ "/dev_flash/sys/external/libsysutil_photo_import.sprx", 0 },
{ "/dev_flash/sys/external/libsysutil_photo_network_sharing.sprx", 0 },
{ "/dev_flash/sys/external/libsysutil_print.sprx", 0 },
{ "/dev_flash/sys/external/libsysutil_rec.sprx", 0 },
{ "/dev_flash/sys/external/libsysutil_remoteplay.sprx", 0 },
{ "/dev_flash/sys/external/libsysutil_rtcalarm.sprx", 0 },
{ "/dev_flash/sys/external/libsysutil_savedata.sprx", 0 },
{ "/dev_flash/sys/external/libsysutil_savedata_psp.sprx", 0 },
{ "/dev_flash/sys/external/libsysutil_screenshot.sprx", 0 },
{ "/dev_flash/sys/external/libsysutil_search.sprx", 0 },
{ "/dev_flash/sys/external/libsysutil_storagedata.sprx", 0 },
{ "/dev_flash/sys/external/libsysutil_subdisplay.sprx", 0 },
{ "/dev_flash/sys/external/libsysutil_syschat.sprx", 0 },
{ "/dev_flash/sys/external/libsysutil_sysconf_ext.sprx", 0 },
{ "/dev_flash/sys/external/libsysutil_userinfo.sprx", 0 },
{ "/dev_flash/sys/external/libsysutil_video_export.sprx", 0 },
{ "/dev_flash/sys/external/libsysutil_video_player.sprx", 0 },
{ "/dev_flash/sys/external/libsysutil_video_upload.sprx", 0 },
{ "/dev_flash/sys/external/libusbd.sprx", 0 },
{ "/dev_flash/sys/external/libusbpspcm.sprx", 0 },
{ "/dev_flash/sys/external/libvdec.sprx", 0 },
{ "/dev_flash/sys/external/libvoice.sprx", 0 },
};
error_code prx_load_module(std::string path, u64 flags, vm::ptr<sys_prx_load_module_option_t> pOpt)
{
const auto name = path.substr(path.find_last_of('/') + 1);
const auto existing = idm::select<lv2_obj, lv2_prx>([&](u32, lv2_prx& prx)
{
if (prx.name == name && prx.path == path)
{
return true;
}
return false;
});
if (existing)
{
return CELL_PRX_ERROR_LIBRARY_FOUND;
}
if (s_prx_ignore.count(path))
{
sys_prx.warning("Ignored module: %s", path);
const auto prx = idm::make_ptr<lv2_obj, lv2_prx>();
prx->name = name;
prx->path = path;
return not_an_error(idm::last_id());
}
const ppu_prx_object obj = decrypt_self(fs::file(vfs::get(path)), fxm::get_always<LoadedNpdrmKeys_t>()->devKlic.data());
if (obj != elf_error::ok)
{
return CELL_PRX_ERROR_ILLEGAL_LIBRARY;
}
const auto prx = ppu_load_prx(obj, vfs::get(path));
if (!prx)
{
return CELL_PRX_ERROR_ILLEGAL_LIBRARY;
}
ppu_initialize(*prx);
sys_prx.success("Loaded module: %s", path);
return not_an_error(idm::last_id());
}
error_code sys_prx_get_ppu_guid()
{
sys_prx.todo("sys_prx_get_ppu_guid()");
return CELL_OK;
}
error_code _sys_prx_load_module_by_fd(s32 fd, u64 offset, u64 flags, vm::ptr<sys_prx_load_module_option_t> pOpt)
{
sys_prx.todo("_sys_prx_load_module_by_fd(fd=%d, offset=0x%x, flags=0x%x, pOpt=*0x%x)", fd, offset, flags, pOpt);
return CELL_OK;
}
error_code _sys_prx_load_module_on_memcontainer_by_fd(s32 fd, u64 offset, u32 mem_ct, u64 flags, vm::ptr<sys_prx_load_module_option_t> pOpt)
{
sys_prx.todo("_sys_prx_load_module_on_memcontainer_by_fd(fd=%d, offset=0x%x, mem_ct=0x%x, flags=0x%x, pOpt=*0x%x)", fd, offset, mem_ct, flags, pOpt);
return CELL_OK;
}
error_code _sys_prx_load_module_list(s32 count, vm::cpptr<char, u32, u64> path_list, u64 flags, vm::ptr<sys_prx_load_module_option_t> pOpt, vm::ptr<u32> id_list)
{
sys_prx.warning("_sys_prx_load_module_list(count=%d, path_list=**0x%x, flags=0x%x, pOpt=*0x%x, id_list=*0x%x)", count, path_list, flags, pOpt, id_list);
for (s32 i = 0; i < count; ++i)
{
auto path = path_list[i];
std::string name = path.get_ptr();
error_code result = prx_load_module(name, flags, pOpt);
if (result < 0)
return result;
id_list[i] = result;
}
return CELL_OK;
}
error_code _sys_prx_load_module_list_on_memcontainer(s32 count, vm::cpptr<char, u32, u64> path_list, u32 mem_ct, u64 flags, vm::ptr<sys_prx_load_module_option_t> pOpt, vm::ptr<u32> id_list)
{
sys_prx.todo("_sys_prx_load_module_list_on_memcontainer(count=%d, path_list=**0x%x, mem_ct=0x%x, flags=0x%x, pOpt=*0x%x, id_list=*0x%x)", count, path_list, mem_ct, flags, pOpt, id_list);
return CELL_OK;
}
error_code _sys_prx_load_module_on_memcontainer(vm::cptr<char> path, u32 mem_ct, u64 flags, vm::ptr<sys_prx_load_module_option_t> pOpt)
{
sys_prx.todo("_sys_prx_load_module_on_memcontainer(path=%s, mem_ct=0x%x, flags=0x%x, pOpt=*0x%x)", path, mem_ct, flags, pOpt);
return CELL_OK;
}
error_code _sys_prx_load_module(vm::cptr<char> path, u64 flags, vm::ptr<sys_prx_load_module_option_t> pOpt)
{
sys_prx.warning("_sys_prx_load_module(path=%s, flags=0x%x, pOpt=*0x%x)", path, flags, pOpt);
return prx_load_module(path.get_ptr(), flags, pOpt);
}
error_code _sys_prx_start_module(u32 id, u64 flags, vm::ptr<sys_prx_start_stop_module_option_t> pOpt)
{
sys_prx.warning("_sys_prx_start_module(id=0x%x, flags=0x%x, pOpt=*0x%x)", id, flags, pOpt);
const auto prx = idm::get<lv2_obj, lv2_prx>(id);
if (!prx)
{
return CELL_ESRCH;
}
//if (prx->is_started)
// return CELL_PRX_ERROR_ALREADY_STARTED;
//prx->is_started = true;
pOpt->entry.set(prx->start ? prx->start.addr() : ~0ull);
pOpt->entry2.set(prx->prologue ? prx->prologue.addr() : ~0ull);
return CELL_OK;
}
error_code _sys_prx_stop_module(u32 id, u64 flags, vm::ptr<sys_prx_start_stop_module_option_t> pOpt)
{
sys_prx.warning("_sys_prx_stop_module(id=0x%x, flags=0x%x, pOpt=*0x%x)", id, flags, pOpt);
const auto prx = idm::get<lv2_obj, lv2_prx>(id);
if (!prx)
{
return CELL_ESRCH;
}
//if (!prx->is_started)
// return CELL_PRX_ERROR_ALREADY_STOPPED;
//prx->is_started = false;
pOpt->entry.set(prx->stop ? prx->stop.addr() : ~0ull);
pOpt->entry2.set(prx->epilogue ? prx->epilogue.addr() : ~0ull);
return CELL_OK;
}
error_code _sys_prx_unload_module(u32 id, u64 flags, vm::ptr<sys_prx_unload_module_option_t> pOpt)
{
sys_prx.todo("_sys_prx_unload_module(id=0x%x, flags=0x%x, pOpt=*0x%x)", id, flags, pOpt);
// Get the PRX, free the used memory and delete the object and its ID
const auto prx = idm::withdraw<lv2_obj, lv2_prx>(id);
if (!prx)
{
return CELL_ESRCH;
}
ppu_unload_prx(*prx);
//s32 result = prx->exit ? prx->exit() : CELL_OK;
return CELL_OK;
}
error_code _sys_prx_register_module()
{
sys_prx.todo("_sys_prx_register_module()");
return CELL_OK;
}
error_code _sys_prx_query_module()
{
sys_prx.todo("_sys_prx_query_module()");
return CELL_OK;
}
error_code _sys_prx_register_library(vm::ptr<void> library)
{
sys_prx.todo("_sys_prx_register_library(library=*0x%x)", library);
return CELL_OK;
}
error_code _sys_prx_unregister_library(vm::ptr<void> library)
{
sys_prx.todo("_sys_prx_unregister_library(library=*0x%x)", library);
return CELL_OK;
}
error_code _sys_prx_link_library()
{
sys_prx.todo("_sys_prx_link_library()");
return CELL_OK;
}
error_code _sys_prx_unlink_library()
{
sys_prx.todo("_sys_prx_unlink_library()");
return CELL_OK;
}
error_code _sys_prx_query_library()
{
sys_prx.todo("_sys_prx_query_library()");
return CELL_OK;
}
error_code _sys_prx_get_module_list(u64 flags, vm::ptr<sys_prx_get_module_list_option_t> pInfo)
{
sys_prx.todo("_sys_prx_get_module_list(flags=%d, pInfo=*0x%x)", flags, pInfo);
return CELL_OK;
}
error_code _sys_prx_get_module_info(u32 id, u64 flags, vm::ptr<sys_prx_module_info_option_t> pOpt)
{
sys_prx.todo("_sys_prx_get_module_info(id=0x%x, flags=%d, pOpt=*0x%x)", id, flags, pOpt);
return CELL_OK;
}
error_code _sys_prx_get_module_id_by_name(vm::cptr<char> name, u64 flags, vm::ptr<sys_prx_get_module_id_by_name_option_t> pOpt)
{
sys_prx.todo("_sys_prx_get_module_id_by_name(name=%s, flags=%d, pOpt=*0x%x)", name, flags, pOpt);
//if (realName == "?") ...
return CELL_PRX_ERROR_UNKNOWN_MODULE;
}
error_code _sys_prx_get_module_id_by_address(u32 addr)
{
sys_prx.todo("_sys_prx_get_module_id_by_address(addr=0x%x)", addr);
return CELL_OK;
}
error_code _sys_prx_start()
{
sys_prx.todo("sys_prx_start()");
return CELL_OK;
}
error_code _sys_prx_stop()
{
sys_prx.todo("sys_prx_stop()");
return CELL_OK;
}
template <>
void fmt_class_string<CellPrxError>::format(std::string& out, u64 arg)
{
format_enum(out, arg, [](CellPrxError value)
{
switch (value)
{
STR_CASE(CELL_PRX_ERROR_ERROR);
STR_CASE(CELL_PRX_ERROR_ILLEGAL_PERM);
STR_CASE(CELL_PRX_ERROR_UNKNOWN_MODULE);
STR_CASE(CELL_PRX_ERROR_ALREADY_STARTED);
STR_CASE(CELL_PRX_ERROR_NOT_STARTED);
STR_CASE(CELL_PRX_ERROR_ALREADY_STOPPED);
STR_CASE(CELL_PRX_ERROR_CAN_NOT_STOP);
STR_CASE(CELL_PRX_ERROR_NOT_REMOVABLE);
STR_CASE(CELL_PRX_ERROR_LIBRARY_NOT_YET_LINKED);
STR_CASE(CELL_PRX_ERROR_LIBRARY_FOUND);
STR_CASE(CELL_PRX_ERROR_LIBRARY_NOTFOUND);
STR_CASE(CELL_PRX_ERROR_ILLEGAL_LIBRARY);
STR_CASE(CELL_PRX_ERROR_LIBRARY_INUSE);
STR_CASE(CELL_PRX_ERROR_ALREADY_STOPPING);
STR_CASE(CELL_PRX_ERROR_UNSUPPORTED_PRX_TYPE);
STR_CASE(CELL_PRX_ERROR_INVAL);
STR_CASE(CELL_PRX_ERROR_ILLEGAL_PROCESS);
STR_CASE(CELL_PRX_ERROR_NO_LIBLV2);
STR_CASE(CELL_PRX_ERROR_UNSUPPORTED_ELF_TYPE);
STR_CASE(CELL_PRX_ERROR_UNSUPPORTED_ELF_CLASS);
STR_CASE(CELL_PRX_ERROR_UNDEFINED_SYMBOL);
STR_CASE(CELL_PRX_ERROR_UNSUPPORTED_RELOCATION_TYPE);
STR_CASE(CELL_PRX_ERROR_ELF_IS_REGISTERED);
}
return unknown;
});
}