mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-17 08:11:51 +00:00
Allow emulation to work without firmware (#9367)
* Allow emulation to work without firmware * Fix HLE prx path detection. * Fix manual list loading bugs. * Fix HLE gcm * GUI: Fix fonts search * GUI: Hardcode sprx list Do not depend on /dev_flash/sys/external/ contents.
This commit is contained in:
parent
51dcb4a79d
commit
2602be426f
@ -1077,7 +1077,7 @@ error_code GcmUnmapIoAddress(ppu_thread& ppu, gcm_config* cfg, u32 io)
|
||||
{
|
||||
if (u32 ea = cfg->offsetTable.eaAddress[io >>= 20], size = cfg->IoMapTable[ea]; size)
|
||||
{
|
||||
if (auto error = sys_rsx_context_iounmap(ppu, 0x55555555, io, size << 20))
|
||||
if (auto error = sys_rsx_context_iounmap(ppu, 0x55555555, io << 20, size << 20))
|
||||
{
|
||||
return error;
|
||||
}
|
||||
|
@ -1387,26 +1387,27 @@ void ppu_load_exec(const ppu_exec_object& elf)
|
||||
// Initialize process
|
||||
std::vector<std::shared_ptr<lv2_prx>> loaded_modules;
|
||||
|
||||
// Get LLE module list
|
||||
// Module list to load at startup
|
||||
std::set<std::string> load_libs;
|
||||
|
||||
if (g_cfg.core.lib_loading == lib_loading_type::manual)
|
||||
if ((g_cfg.core.lib_loading != lib_loading_type::hybrid && g_cfg.core.lib_loading != lib_loading_type::manual) || g_cfg.core.load_libraries.get_set().count("liblv2.sprx"))
|
||||
{
|
||||
// Load required set of modules (lib_loading_type::both processed in sys_prx.cpp)
|
||||
load_libs = g_cfg.core.load_libraries.get_set();
|
||||
// Will load libsysmodule.sprx internally
|
||||
load_libs.emplace("liblv2.sprx");
|
||||
}
|
||||
else
|
||||
else if (g_cfg.core.lib_loading == lib_loading_type::hybrid)
|
||||
{
|
||||
if (g_cfg.core.lib_loading != lib_loading_type::hybrid || g_cfg.core.load_libraries.get_set().count("liblv2.sprx"))
|
||||
{
|
||||
// Will load libsysmodule.sprx internally
|
||||
load_libs.emplace("liblv2.sprx");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Load only libsysmodule.sprx
|
||||
load_libs.emplace("libsysmodule.sprx");
|
||||
}
|
||||
// Load only libsysmodule.sprx
|
||||
load_libs.emplace("libsysmodule.sprx");
|
||||
}
|
||||
|
||||
const std::string lle_dir = vfs::get("/dev_flash/sys/external/");
|
||||
|
||||
if (!fs::is_file(lle_dir + "liblv2.sprx"))
|
||||
{
|
||||
ppu_loader.error("PS3 firmware is not installed or the installed firmware is invalid."
|
||||
"\nYou should install the PS3 Firmware (Menu: File -> Install Firmware)."
|
||||
"\nVisit https://rpcs3.net/ for Quickstart Guide and more information.");
|
||||
}
|
||||
|
||||
// Program entry
|
||||
@ -1414,15 +1415,6 @@ void ppu_load_exec(const ppu_exec_object& elf)
|
||||
|
||||
if (!load_libs.empty())
|
||||
{
|
||||
const std::string lle_dir = vfs::get("/dev_flash/sys/external/");
|
||||
|
||||
if (!fs::is_dir(lle_dir) || !fs::is_file(lle_dir + "libsysmodule.sprx"))
|
||||
{
|
||||
ppu_loader.error("PS3 firmware is not installed or the installed firmware is invalid."
|
||||
"\nYou should install the PS3 Firmware (Menu: File -> Install Firmware)."
|
||||
"\nVisit https://rpcs3.net/ for Quickstart Guide and more information.");
|
||||
}
|
||||
|
||||
for (const auto& name : load_libs)
|
||||
{
|
||||
const ppu_prx_object obj = decrypt_self(fs::file(lle_dir + name));
|
||||
@ -1455,7 +1447,7 @@ void ppu_load_exec(const ppu_exec_object& elf)
|
||||
}
|
||||
else
|
||||
{
|
||||
fmt::throw_exception("Failed to load /dev_flash/sys/external/%s: %s", name, obj.get_error());
|
||||
ppu_loader.error("Failed to load /dev_flash/sys/external/%s: %s (forcing HLE implementation)", name, obj.get_error());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -21,67 +21,150 @@ extern void ppu_initialize(const ppu_module&);
|
||||
|
||||
LOG_CHANNEL(sys_prx);
|
||||
|
||||
static const std::unordered_map<std::string, int> s_prx_ignore
|
||||
extern const std::unordered_map<std::string_view, int> g_prx_list
|
||||
{
|
||||
{ "/dev_flash/sys/external/libaudio.sprx", 0 },
|
||||
{ "/dev_flash/sys/external/libcamera.sprx", 0 },
|
||||
{ "/dev_flash/sys/external/libgem.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/libnetctl.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/libvdec.sprx", 0 },
|
||||
{ "/dev_flash/sys/external/libvoice.sprx", 0 },
|
||||
{ "libaacenc.sprx", 0 },
|
||||
{ "libaacenc_spurs.sprx", 0 },
|
||||
{ "libac3dec.sprx", 0 },
|
||||
{ "libac3dec2.sprx", 0 },
|
||||
{ "libadec.sprx", 0 },
|
||||
{ "libadec2.sprx", 0 },
|
||||
{ "libadec_internal.sprx", 0 },
|
||||
{ "libad_async.sprx", 0 },
|
||||
{ "libad_billboard_util.sprx", 0 },
|
||||
{ "libad_core.sprx", 0 },
|
||||
{ "libapostsrc_mini.sprx", 0 },
|
||||
{ "libasfparser2_astd.sprx", 0 },
|
||||
{ "libat3dec.sprx", 0 },
|
||||
{ "libat3multidec.sprx", 0 },
|
||||
{ "libatrac3multi.sprx", 0 },
|
||||
{ "libatrac3plus.sprx", 0 },
|
||||
{ "libatxdec.sprx", 0 },
|
||||
{ "libatxdec2.sprx", 0 },
|
||||
{ "libaudio.sprx", 1 },
|
||||
{ "libavcdec.sprx", 0 },
|
||||
{ "libavcenc.sprx", 0 },
|
||||
{ "libavcenc_small.sprx", 0 },
|
||||
{ "libavchatjpgdec.sprx", 0 },
|
||||
{ "libbeisobmf.sprx", 0 },
|
||||
{ "libbemp2sys.sprx", 0 },
|
||||
{ "libcamera.sprx", 1 },
|
||||
{ "libcelp8dec.sprx", 0 },
|
||||
{ "libcelp8enc.sprx", 0 },
|
||||
{ "libcelpdec.sprx", 0 },
|
||||
{ "libcelpenc.sprx", 0 },
|
||||
{ "libddpdec.sprx", 0 },
|
||||
{ "libdivxdec.sprx", 0 },
|
||||
{ "libdmux.sprx", 0 },
|
||||
{ "libdmuxpamf.sprx", 0 },
|
||||
{ "libdtslbrdec.sprx", 0 },
|
||||
{ "libfiber.sprx", 0 },
|
||||
{ "libfont.sprx", 0 },
|
||||
{ "libfontFT.sprx", 0 },
|
||||
{ "libfreetype.sprx", 0 },
|
||||
{ "libfreetypeTT.sprx", 0 },
|
||||
{ "libfs.sprx", 0 },
|
||||
{ "libfs_155.sprx", 0 },
|
||||
{ "libgcm_sys.sprx", 0 },
|
||||
{ "libgem.sprx", 1 },
|
||||
{ "libgifdec.sprx", 0 },
|
||||
{ "libhttp.sprx", 0 },
|
||||
{ "libio.sprx", 1 },
|
||||
{ "libjpgdec.sprx", 0 },
|
||||
{ "libjpgenc.sprx", 0 },
|
||||
{ "libkey2char.sprx", 0 },
|
||||
{ "libl10n.sprx", 0 },
|
||||
{ "liblv2.sprx", 0 },
|
||||
{ "liblv2coredump.sprx", 0 },
|
||||
{ "liblv2dbg_for_cex.sprx", 0 },
|
||||
{ "libm2bcdec.sprx", 0 },
|
||||
{ "libm4aacdec.sprx", 0 },
|
||||
{ "libm4aacdec2ch.sprx", 0 },
|
||||
{ "libm4hdenc.sprx", 0 },
|
||||
{ "libm4venc.sprx", 0 },
|
||||
{ "libmedi.sprx", 1 },
|
||||
{ "libmic.sprx", 1 },
|
||||
{ "libmp3dec.sprx", 0 },
|
||||
{ "libmp4.sprx", 0 },
|
||||
{ "libmpl1dec.sprx", 0 },
|
||||
{ "libmvcdec.sprx", 0 },
|
||||
{ "libnet.sprx", 0 },
|
||||
{ "libnetctl.sprx", 1 },
|
||||
{ "libpamf.sprx", 0 },
|
||||
{ "libpngdec.sprx", 0 },
|
||||
{ "libpngenc.sprx", 0 },
|
||||
{ "libresc.sprx", 0 },
|
||||
{ "librtc.sprx", 0 },
|
||||
{ "librudp.sprx", 0 },
|
||||
{ "libsail.sprx", 0 },
|
||||
{ "libsail_avi.sprx", 0 },
|
||||
{ "libsail_rec.sprx", 0 },
|
||||
{ "libsjvtd.sprx", 0 },
|
||||
{ "libsmvd2.sprx", 0 },
|
||||
{ "libsmvd4.sprx", 0 },
|
||||
{ "libspurs_jq.sprx", 0 },
|
||||
{ "libsre.sprx", 0 },
|
||||
{ "libssl.sprx", 0 },
|
||||
{ "libsvc1d.sprx", 0 },
|
||||
{ "libsync2.sprx", 0 },
|
||||
{ "libsysmodule.sprx", 0 },
|
||||
{ "libsysutil.sprx", 1 },
|
||||
{ "libsysutil_ap.sprx", 1 },
|
||||
{ "libsysutil_authdialog.sprx", 1 },
|
||||
{ "libsysutil_avc2.sprx", 1 },
|
||||
{ "libsysutil_avconf_ext.sprx", 1 },
|
||||
{ "libsysutil_avc_ext.sprx", 1 },
|
||||
{ "libsysutil_bgdl.sprx", 1 },
|
||||
{ "libsysutil_cross_controller.sprx", 1 },
|
||||
{ "libsysutil_dec_psnvideo.sprx", 1 },
|
||||
{ "libsysutil_dtcp_ip.sprx", 1 },
|
||||
{ "libsysutil_game.sprx", 1 },
|
||||
{ "libsysutil_game_exec.sprx", 1 },
|
||||
{ "libsysutil_imejp.sprx", 1 },
|
||||
{ "libsysutil_misc.sprx", 1 },
|
||||
{ "libsysutil_music.sprx", 1 },
|
||||
{ "libsysutil_music_decode.sprx", 1 },
|
||||
{ "libsysutil_music_export.sprx", 1 },
|
||||
{ "libsysutil_np.sprx", 1 },
|
||||
{ "libsysutil_np2.sprx", 1 },
|
||||
{ "libsysutil_np_clans.sprx", 1 },
|
||||
{ "libsysutil_np_commerce2.sprx", 1 },
|
||||
{ "libsysutil_np_eula.sprx", 1 },
|
||||
{ "libsysutil_np_installer.sprx", 1 },
|
||||
{ "libsysutil_np_sns.sprx", 1 },
|
||||
{ "libsysutil_np_trophy.sprx", 1 },
|
||||
{ "libsysutil_np_tus.sprx", 1 },
|
||||
{ "libsysutil_np_util.sprx", 1 },
|
||||
{ "libsysutil_oskdialog_ext.sprx", 1 },
|
||||
{ "libsysutil_pesm.sprx", 1 },
|
||||
{ "libsysutil_photo_decode.sprx", 1 },
|
||||
{ "libsysutil_photo_export.sprx", 1 },
|
||||
{ "libsysutil_photo_export2.sprx", 1 },
|
||||
{ "libsysutil_photo_import.sprx", 1 },
|
||||
{ "libsysutil_photo_network_sharing.sprx", 1 },
|
||||
{ "libsysutil_print.sprx", 1 },
|
||||
{ "libsysutil_rec.sprx", 1 },
|
||||
{ "libsysutil_remoteplay.sprx", 1 },
|
||||
{ "libsysutil_rtcalarm.sprx", 1 },
|
||||
{ "libsysutil_savedata.sprx", 1 },
|
||||
{ "libsysutil_savedata_psp.sprx", 1 },
|
||||
{ "libsysutil_screenshot.sprx", 1 },
|
||||
{ "libsysutil_search.sprx", 1 },
|
||||
{ "libsysutil_storagedata.sprx", 1 },
|
||||
{ "libsysutil_subdisplay.sprx", 1 },
|
||||
{ "libsysutil_syschat.sprx", 1 },
|
||||
{ "libsysutil_sysconf_ext.sprx", 1 },
|
||||
{ "libsysutil_userinfo.sprx", 1 },
|
||||
{ "libsysutil_video_export.sprx", 1 },
|
||||
{ "libsysutil_video_player.sprx", 1 },
|
||||
{ "libsysutil_video_upload.sprx", 1 },
|
||||
{ "libusbd.sprx", 0 },
|
||||
{ "libusbpspcm.sprx", 0 },
|
||||
{ "libvdec.sprx", 1 },
|
||||
{ "libvoice.sprx", 1 },
|
||||
{ "libvpost.sprx", 0 },
|
||||
{ "libvpost2.sprx", 0 },
|
||||
{ "libwmadec.sprx", 0 },
|
||||
};
|
||||
|
||||
static error_code prx_load_module(const std::string& vpath, u64 flags, vm::ptr<sys_prx_load_module_option_t> pOpt, fs::file src = {})
|
||||
@ -101,17 +184,13 @@ static error_code prx_load_module(const std::string& vpath, u64 flags, vm::ptr<s
|
||||
fmt::throw_exception("sys_prx: Unimplemented fixed address allocations" HERE);
|
||||
}
|
||||
|
||||
std::string name = vpath.substr(vpath.find_last_of('/') + 1);
|
||||
std::string path = vfs::get(vpath);
|
||||
std::string vpath0;
|
||||
const std::string path = vfs::get(vpath, nullptr, &vpath0);
|
||||
const std::string name = vpath0.substr(vpath0.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;
|
||||
return prx.path == path;
|
||||
});
|
||||
|
||||
if (existing)
|
||||
@ -121,28 +200,32 @@ static error_code prx_load_module(const std::string& vpath, u64 flags, vm::ptr<s
|
||||
|
||||
bool ignore = false;
|
||||
|
||||
if (g_cfg.core.lib_loading == lib_loading_type::liblv2list)
|
||||
constexpr std::string_view firmware_sprx_dir = "/dev_flash/sys/external/";
|
||||
const bool is_firmware_sprx = vpath0.starts_with(firmware_sprx_dir) && g_prx_list.count(std::string_view(vpath0).substr(firmware_sprx_dir.size()));
|
||||
|
||||
if (is_firmware_sprx)
|
||||
{
|
||||
if (vpath.starts_with("/dev_flash/sys/external/") && vpath != "/dev_flash/sys/external/libsysmodule.sprx"sv)
|
||||
// First condition, LLE for selected libs
|
||||
ignore = g_cfg.core.load_libraries.get_set().count(name) == 0;
|
||||
|
||||
if (g_cfg.core.lib_loading != lib_loading_type::liblv2list && g_cfg.core.lib_loading != lib_loading_type::manual)
|
||||
{
|
||||
ignore = g_cfg.core.load_libraries.get_set().count(name) == 0;
|
||||
// Override list setting condition for liblv2only
|
||||
// For the other modes g_prx_list is a second condition which filters HLE selected libs by list setting
|
||||
if (ignore || g_cfg.core.lib_loading == lib_loading_type::liblv2only)
|
||||
{
|
||||
ignore = g_prx_list.at(name) != 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
else if (vpath0.starts_with("/"))
|
||||
{
|
||||
ignore = s_prx_ignore.count(vpath) != 0;
|
||||
// Special case (currently unused): HLE for files outside of "/dev_flash/sys/external/"
|
||||
// Have to specify full path for them
|
||||
ignore = g_prx_list.count(vpath0) && g_prx_list.at(vpath0);
|
||||
}
|
||||
|
||||
if (ignore && (g_cfg.core.lib_loading == lib_loading_type::hybrid || g_cfg.core.lib_loading == lib_loading_type::liblv2both))
|
||||
{
|
||||
// Ignore ignore list if the library is selected in 'both' mode
|
||||
if (g_cfg.core.load_libraries.get_set().count(name) != 0)
|
||||
{
|
||||
ignore = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (ignore)
|
||||
auto hle_load = [&]()
|
||||
{
|
||||
const auto prx = idm::make_ptr<lv2_obj, lv2_prx>();
|
||||
|
||||
@ -152,6 +235,11 @@ static error_code prx_load_module(const std::string& vpath, u64 flags, vm::ptr<s
|
||||
sys_prx.warning(u8"Ignored module: “%s” (id=0x%x)", vpath, idm::last_id());
|
||||
|
||||
return not_an_error(idm::last_id());
|
||||
};
|
||||
|
||||
if (ignore)
|
||||
{
|
||||
return hle_load();
|
||||
}
|
||||
|
||||
if (!src)
|
||||
@ -160,6 +248,12 @@ static error_code prx_load_module(const std::string& vpath, u64 flags, vm::ptr<s
|
||||
|
||||
if (fs_error)
|
||||
{
|
||||
if (fs_error + 0u == CELL_ENOENT && is_firmware_sprx)
|
||||
{
|
||||
sys_prx.error(u8"firmware SPRX not found: “%s” (forcing HLE implementation)", vpath, idm::last_id());
|
||||
return hle_load();
|
||||
}
|
||||
|
||||
return {fs_error, vpath};
|
||||
}
|
||||
|
||||
|
@ -270,7 +270,6 @@ error_code sys_rsx_context_allocate(cpu_thread& cpu, vm::ptr<u32> context_id, vm
|
||||
render->current_display_buffer = 0;
|
||||
render->label_addr = vm::cast(*lpar_reports, HERE);
|
||||
render->device_addr = rsx_cfg->device_addr;
|
||||
render->dma_address = rsx_cfg->dma_address;
|
||||
render->local_mem_size = rsx_cfg->memory_size;
|
||||
render->init(vm::cast(*lpar_dma_control, HERE));
|
||||
|
||||
|
@ -119,6 +119,7 @@ namespace rsx
|
||||
case language_class::default_:
|
||||
{
|
||||
result.font_names.emplace_back("Arial.ttf");
|
||||
result.font_names.emplace_back("arial.ttf");
|
||||
#ifndef _WIN32
|
||||
result.font_names.emplace_back("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf"); // ubuntu
|
||||
result.font_names.emplace_back("/usr/share/fonts/TTF/DejaVuSans.ttf"); // arch
|
||||
@ -137,6 +138,7 @@ namespace rsx
|
||||
|
||||
// Known system font as last fallback
|
||||
result.font_names.emplace_back("Yu Gothic.ttf");
|
||||
result.font_names.emplace_back("YuGothR.ttc");
|
||||
break;
|
||||
}
|
||||
case language_class::hangul:
|
||||
@ -149,6 +151,7 @@ namespace rsx
|
||||
|
||||
// Known system font as last fallback
|
||||
result.font_names.emplace_back("Malgun Gothic.ttf");
|
||||
result.font_names.emplace_back("malgun.ttf");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -452,6 +452,12 @@ namespace rsx
|
||||
// Wait for startup (TODO)
|
||||
while (m_rsx_thread_exiting)
|
||||
{
|
||||
// Wait for external pause events
|
||||
if (external_interrupt_lock)
|
||||
{
|
||||
wait_pause();
|
||||
}
|
||||
|
||||
thread_ctrl::wait_for(1000);
|
||||
|
||||
if (Emu.IsStopped())
|
||||
@ -1957,6 +1963,7 @@ namespace rsx
|
||||
|
||||
void thread::init(u32 ctrlAddress)
|
||||
{
|
||||
dma_address = ctrlAddress;
|
||||
ctrl = vm::_ptr<RsxDmaControl>(ctrlAddress);
|
||||
flip_status = CELL_GCM_DISPLAY_FLIP_STATUS_DONE;
|
||||
|
||||
|
@ -1059,11 +1059,6 @@ game_boot_result Emulator::Load(const std::string& title_id, bool add_only, bool
|
||||
sys_log.notice("Hdd1: %s", vfs::get("/dev_hdd1"));
|
||||
}
|
||||
|
||||
if (!fs::is_file(g_cfg.vfs.get_dev_flash() + "sys/external/liblv2.sprx"))
|
||||
{
|
||||
return game_boot_result::firmware_missing;
|
||||
}
|
||||
|
||||
// Special boot mode (directory scan)
|
||||
if (!add_only && fs::is_dir(m_path))
|
||||
{
|
||||
@ -1682,6 +1677,15 @@ game_boot_result Emulator::Load(const std::string& title_id, bool add_only, bool
|
||||
{
|
||||
if (ppu_exec == elf_error::ok)
|
||||
{
|
||||
if (!fs::is_file(g_cfg.vfs.get_dev_flash() + "sys/external/liblv2.sprx"))
|
||||
{
|
||||
if (!GetCallbacks().on_missing_fw())
|
||||
{
|
||||
Stop();
|
||||
return game_boot_result::firmware_missing;
|
||||
}
|
||||
}
|
||||
|
||||
Run(true);
|
||||
}
|
||||
|
||||
|
@ -41,6 +41,7 @@ struct EmuCallbacks
|
||||
std::function<void()> on_resume;
|
||||
std::function<void()> on_stop;
|
||||
std::function<void()> on_ready;
|
||||
std::function<bool()> on_missing_fw;
|
||||
std::function<bool(bool)> exit; // (force_quit) close RPCS3
|
||||
std::function<void(s32, s32)> handle_taskbar_progress; // (type, value) type: 0 for reset, 1 for increment, 2 for set_limit
|
||||
std::function<void()> init_kb_handler;
|
||||
|
@ -11,7 +11,7 @@ void fmt_class_string<elf_error>::format(std::string& out, u64 arg)
|
||||
{
|
||||
case elf_error::ok: return "OK";
|
||||
|
||||
case elf_error::stream: return "Invalid stream or file not found";
|
||||
case elf_error::stream: return "File not found";
|
||||
case elf_error::stream_header: return "Failed to read ELF header";
|
||||
case elf_error::stream_phdrs: return "Failed to read ELF program headers";
|
||||
case elf_error::stream_shdrs: return "Failed to read ELF section headers";
|
||||
|
@ -344,6 +344,11 @@ void gui_application::InitializeCallbacks()
|
||||
callbacks.on_stop = [this]() { OnEmulatorStop(); };
|
||||
callbacks.on_ready = [this]() { OnEmulatorReady(); };
|
||||
|
||||
callbacks.on_missing_fw = [this]()
|
||||
{
|
||||
return m_gui_settings->GetBootConfirmation(m_main_window, gui::ib_confirm_fw);
|
||||
};
|
||||
|
||||
callbacks.handle_taskbar_progress = [this](s32 type, s32 value)
|
||||
{
|
||||
if (m_game_window)
|
||||
|
@ -154,9 +154,9 @@ void gui_settings::SetCategoryVisibility(int cat, const bool& val)
|
||||
SetValue(value, val);
|
||||
}
|
||||
|
||||
void gui_settings::ShowBox(bool confirm, const QString& title, const QString& text, const gui_save& entry, int* result = nullptr, QWidget* parent = nullptr, bool always_on_top = false)
|
||||
void gui_settings::ShowBox(QMessageBox::Icon icon, const QString& title, const QString& text, const gui_save& entry, int* result = nullptr, QWidget* parent = nullptr, bool always_on_top = false)
|
||||
{
|
||||
const std::string dialog_type = confirm ? "Confirmation" : "Info";
|
||||
const std::string dialog_type = icon != QMessageBox::Information ? "Confirmation" : "Info";
|
||||
const bool has_gui_setting = !entry.name.isEmpty();
|
||||
|
||||
if (has_gui_setting && !GetValue(entry).toBool())
|
||||
@ -165,13 +165,13 @@ void gui_settings::ShowBox(bool confirm, const QString& title, const QString& te
|
||||
return;
|
||||
}
|
||||
|
||||
const QFlags<QMessageBox::StandardButton> buttons = confirm ? QMessageBox::Yes | QMessageBox::No : QMessageBox::Ok;
|
||||
const QMessageBox::Icon icon = confirm ? QMessageBox::Question : QMessageBox::Information;
|
||||
const QFlags<QMessageBox::StandardButton> buttons = icon != QMessageBox::Information ? QMessageBox::Yes | QMessageBox::No : QMessageBox::Ok;
|
||||
|
||||
QMessageBox* mb = new QMessageBox(icon, title, text, buttons, parent, Qt::Dialog | Qt::MSWindowsFixedSizeDialogHint | (always_on_top ? Qt::WindowStaysOnTopHint : Qt::Widget));
|
||||
mb->deleteLater();
|
||||
mb->setTextFormat(Qt::RichText);
|
||||
|
||||
if (has_gui_setting)
|
||||
if (has_gui_setting && icon != QMessageBox::Critical)
|
||||
{
|
||||
mb->setCheckBox(new QCheckBox(tr("Don't show again")));
|
||||
}
|
||||
@ -182,7 +182,10 @@ void gui_settings::ShowBox(bool confirm, const QString& title, const QString& te
|
||||
{
|
||||
*result = res;
|
||||
}
|
||||
if (has_gui_setting && mb->checkBox()->isChecked())
|
||||
|
||||
const auto checkBox = mb->checkBox();
|
||||
|
||||
if (checkBox && checkBox->isChecked())
|
||||
{
|
||||
SetValue(entry, false);
|
||||
cfg_log.notice("%s Dialog for Entry %s is now disabled", dialog_type, sstr(entry.name));
|
||||
@ -194,12 +197,12 @@ void gui_settings::ShowBox(bool confirm, const QString& title, const QString& te
|
||||
|
||||
void gui_settings::ShowConfirmationBox(const QString& title, const QString& text, const gui_save& entry, int* result = nullptr, QWidget* parent = nullptr)
|
||||
{
|
||||
ShowBox(true, title, text, entry, result, parent, true);
|
||||
ShowBox(QMessageBox::Question, title, text, entry, result, parent, true);
|
||||
}
|
||||
|
||||
void gui_settings::ShowInfoBox(const QString& title, const QString& text, const gui_save& entry, QWidget* parent = nullptr)
|
||||
{
|
||||
ShowBox(false, title, text, entry, nullptr, parent, false);
|
||||
ShowBox(QMessageBox::Information, title, text, entry, nullptr, parent, false);
|
||||
}
|
||||
|
||||
bool gui_settings::GetBootConfirmation(QWidget* parent, const gui_save& gui_save_entry)
|
||||
@ -208,6 +211,7 @@ bool gui_settings::GetBootConfirmation(QWidget* parent, const gui_save& gui_save
|
||||
{
|
||||
QString title = tr("Close Running Game?");
|
||||
QString message = tr("Performing this action will close the current game.\nDo you really want to continue?\n\nAny unsaved progress will be lost!\n");
|
||||
auto icon = QMessageBox::Question;
|
||||
|
||||
if (gui_save_entry == gui::ib_confirm_boot)
|
||||
{
|
||||
@ -218,10 +222,18 @@ bool gui_settings::GetBootConfirmation(QWidget* parent, const gui_save& gui_save
|
||||
title = tr("Exit RPCS3?");
|
||||
message = tr("A game is currently running. Do you really want to close RPCS3?\n\nAny unsaved progress will be lost!\n");
|
||||
}
|
||||
else if (gui_save_entry == gui::ib_confirm_fw)
|
||||
{
|
||||
title = tr("Missing Firmware Detected!");
|
||||
message = tr("Install the PS3 Firmware (Menu: File -> Install Firmware)."
|
||||
"\n<br>For more information read the <a href=\"https://rpcs3.net/quickstart\">quickstart guide</a>."
|
||||
"\nCommercial games do not work without firmware! Do you wish to continue!?");
|
||||
icon = QMessageBox::Critical;
|
||||
}
|
||||
|
||||
int result = QMessageBox::Yes;
|
||||
|
||||
ShowConfirmationBox(title, message, gui_save_entry, &result, parent);
|
||||
ShowBox(icon, title, message, gui_save_entry, &result, parent);
|
||||
|
||||
if (result != QMessageBox::Yes)
|
||||
{
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include <QVariant>
|
||||
#include <QSize>
|
||||
#include <QColor>
|
||||
#include <QMessageBox>
|
||||
|
||||
namespace gui
|
||||
{
|
||||
@ -120,6 +121,7 @@ namespace gui
|
||||
const gui_save ib_show_welcome = gui_save(main_window, "infoBoxEnabledWelcome", true);
|
||||
const gui_save ib_confirm_exit = gui_save(main_window, "confirmationBoxExitGame", true);
|
||||
const gui_save ib_confirm_boot = gui_save(main_window, "confirmationBoxBootGame", true);
|
||||
const gui_save ib_confirm_fw = gui_save(main_window, "confirmationMissingFW", true);
|
||||
|
||||
const gui_save fd_install_pkg = gui_save(main_window, "lastExplorePathPKG", "");
|
||||
const gui_save fd_install_pup = gui_save(main_window, "lastExplorePathPUP", "");
|
||||
@ -273,7 +275,7 @@ public Q_SLOTS:
|
||||
private:
|
||||
void SaveConfigNameToDefault(const QString& config_name);
|
||||
void BackupSettingsToTarget(const QString& config_name);
|
||||
void ShowBox(bool confirm, const QString& title, const QString& text, const gui_save& entry, int* result, QWidget* parent, bool always_on_top);
|
||||
void ShowBox(QMessageBox::Icon icon, const QString& title, const QString& text, const gui_save& entry, int* result, QWidget* parent, bool always_on_top);
|
||||
|
||||
QString m_current_name;
|
||||
};
|
||||
|
@ -300,10 +300,6 @@ void main_window::OnPlayOrPause()
|
||||
|
||||
void main_window::show_boot_error(game_boot_result status)
|
||||
{
|
||||
if (status == game_boot_result::no_errors)
|
||||
{
|
||||
return;
|
||||
}
|
||||
QString message;
|
||||
switch (status)
|
||||
{
|
||||
@ -325,9 +321,9 @@ void main_window::show_boot_error(game_boot_result status)
|
||||
case game_boot_result::file_creation_error:
|
||||
message = tr("The emulator could not create files required for booting.");
|
||||
break;
|
||||
case game_boot_result::firmware_missing:
|
||||
message = tr("Firmware has not been installed. Install firmware with the \"File > Install Firmware\" menu option.");
|
||||
break;
|
||||
case game_boot_result::firmware_missing: // Handled elsewhere
|
||||
case game_boot_result::no_errors:
|
||||
return;
|
||||
case game_boot_result::generic_error:
|
||||
default:
|
||||
message = tr("Unknown error.");
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include "Crypto/unself.h"
|
||||
#include "Utilities/sysinfo.h"
|
||||
|
||||
#include <set>
|
||||
#include <unordered_set>
|
||||
#include <thread>
|
||||
|
||||
@ -41,6 +42,7 @@ LOG_CHANNEL(cfg_log, "CFG");
|
||||
|
||||
inline std::string sstr(const QString& _in) { return _in.toStdString(); }
|
||||
inline std::string sstr(const QVariant& _in) { return sstr(_in.toString()); }
|
||||
inline QString qsv(std::string_view sv) { return QString(sv.data()); }
|
||||
|
||||
settings_dialog::settings_dialog(std::shared_ptr<gui_settings> gui_settings, std::shared_ptr<emu_settings> emu_settings, const int& tab_index, QWidget *parent, const GameInfo* game)
|
||||
: QDialog(parent)
|
||||
@ -1026,47 +1028,28 @@ settings_dialog::settings_dialog(std::shared_ptr<gui_settings> gui_settings, std
|
||||
|
||||
m_emu_settings->EnhanceRadioButton(lib_mode_bg, emu_settings_type::LibLoadOptions);
|
||||
|
||||
// Sort string vector alphabetically
|
||||
static const auto sort_string_vector = [](std::vector<std::string>& vec)
|
||||
{
|
||||
std::sort(vec.begin(), vec.end(), [](const std::string &str1, const std::string &str2) { return str1 < str2; });
|
||||
};
|
||||
|
||||
std::vector<std::string> loadedLibs = m_emu_settings->GetLoadedLibraries();
|
||||
|
||||
sort_string_vector(loadedLibs);
|
||||
std::set<std::string_view> set(loadedLibs.begin(), loadedLibs.end());
|
||||
|
||||
for (const auto& lib : loadedLibs)
|
||||
for (const auto& lib : set)
|
||||
{
|
||||
QListWidgetItem* item = new QListWidgetItem(qstr(lib), ui->lleList);
|
||||
QListWidgetItem* item = new QListWidgetItem(qsv(lib), ui->lleList);
|
||||
item->setFlags(item->flags() | Qt::ItemIsUserCheckable); // set checkable flag
|
||||
item->setCheckState(Qt::Checked); // AND initialize check state
|
||||
ui->lleList->addItem(item);
|
||||
}
|
||||
|
||||
const std::string lle_dir = g_cfg.vfs.get_dev_flash() + "sys/external/";
|
||||
extern const std::unordered_map<std::string_view, int> g_prx_list;
|
||||
|
||||
std::unordered_set<std::string> set(loadedLibs.begin(), loadedLibs.end());
|
||||
std::vector<std::string> lle_module_list_unselected;
|
||||
|
||||
for (const auto& prxf : fs::dir(lle_dir))
|
||||
for (const auto& lib : g_prx_list)
|
||||
{
|
||||
// List found unselected modules
|
||||
if (prxf.is_directory || (prxf.name.substr(std::max<size_t>(size_t(3), prxf.name.length()) - 4)) != "sprx")
|
||||
if (set.count(lib.first))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (verify_npdrm_self_headers(fs::file(lle_dir + prxf.name)) && !set.count(prxf.name))
|
||||
{
|
||||
lle_module_list_unselected.push_back(prxf.name);
|
||||
}
|
||||
}
|
||||
|
||||
sort_string_vector(lle_module_list_unselected);
|
||||
|
||||
for (const auto& lib : lle_module_list_unselected)
|
||||
{
|
||||
QListWidgetItem* item = new QListWidgetItem(qstr(lib), ui->lleList);
|
||||
QListWidgetItem* item = new QListWidgetItem(qsv(lib.first), ui->lleList);
|
||||
item->setFlags(item->flags() | Qt::ItemIsUserCheckable); // set checkable flag
|
||||
item->setCheckState(Qt::Unchecked); // AND initialize check state
|
||||
ui->lleList->addItem(item);
|
||||
|
Loading…
Reference in New Issue
Block a user