Loader: Make executable analyzation not halt UI when launching games

This commit is contained in:
Eladash 2023-04-08 18:03:05 +03:00 committed by Ivan
parent 17e6ad1fe8
commit 0e388639cc
8 changed files with 51 additions and 29 deletions

View file

@ -530,7 +530,7 @@ namespace ppu_patterns
};
}
void ppu_module::analyse(u32 lib_toc, u32 entry, const u32 sec_end, const std::basic_string<u32>& applied)
bool ppu_module::analyse(u32 lib_toc, u32 entry, const u32 sec_end, const std::basic_string<u32>& applied, std::function<bool()> check_aborted)
{
// Assume first segment is executable
const u32 start = segs[0].addr;
@ -841,6 +841,11 @@ void ppu_module::analyse(u32 lib_toc, u32 entry, const u32 sec_end, const std::b
// Main loop (func_queue may grow)
for (usz i = 0; i < func_queue.size(); i++)
{
if (check_aborted && check_aborted())
{
return false;
}
ppu_function& func = func_queue[i];
// Fixup TOCs
@ -1843,6 +1848,7 @@ void ppu_module::analyse(u32 lib_toc, u32 entry, const u32 sec_end, const std::b
}
ppu_log.notice("Block analysis: %zu blocks (%zu enqueued)", funcs.size(), block_queue.size());
return true;
}
// Temporarily

View file

@ -70,15 +70,15 @@ struct ppu_segment
// PPU Module Information
struct ppu_module
{
ppu_module() = default;
ppu_module() noexcept = default;
ppu_module(const ppu_module&) = delete;
ppu_module(ppu_module&&) = default;
ppu_module(ppu_module&&) noexcept = default;
ppu_module& operator=(const ppu_module&) = delete;
ppu_module& operator=(ppu_module&&) = default;
ppu_module& operator=(ppu_module&&) noexcept = default;
uchar sha1[20]{};
std::string name{};
@ -101,10 +101,17 @@ struct ppu_module
secs = info.secs;
}
void analyse(u32 lib_toc, u32 entry, u32 end, const std::basic_string<u32>& applied);
bool analyse(u32 lib_toc, u32 entry, u32 end, const std::basic_string<u32>& applied, std::function<bool()> check_aborted = {});
void validate(u32 reloc);
};
struct main_ppu_module : public ppu_module
{
u32 elf_entry;
u32 seg0_code_end;
std::basic_string<u32> applied_pathes;
};
// Aux
struct ppu_pattern
{

View file

@ -961,7 +961,7 @@ static auto ppu_load_imports(std::vector<ppu_reloc>& relocs, ppu_linkage_info* l
// For _sys_prx_register_module
void ppu_manual_load_imports_exports(u32 imports_start, u32 imports_size, u32 exports_start, u32 exports_size, std::basic_string<bool>& loaded_flags)
{
auto& _main = g_fxo->get<ppu_module>();
auto& _main = g_fxo->get<main_ppu_module>();
auto& link = g_fxo->get<ppu_linkage_info>();
ppu_load_exports(&link, exports_start, exports_start + exports_size, false, &loaded_flags);
@ -1158,7 +1158,7 @@ static void ppu_check_patch_spu_images(const ppu_segment& seg)
void try_spawn_ppu_if_exclusive_program(const ppu_module& m)
{
// If only PRX/OVL has been loaded at Emu.BootGame(), launch a single PPU thread so its memory can be viewed
if (Emu.IsReady() && g_fxo->get<ppu_module>().segs.empty() && !Emu.DeserialManager())
if (Emu.IsReady() && g_fxo->get<main_ppu_module>().segs.empty() && !Emu.DeserialManager())
{
ppu_thread_params p
{
@ -1706,7 +1706,7 @@ bool ppu_load_exec(const ppu_exec_object& elf, utils::serial* ar)
init_ppu_functions(ar, false);
// Set for delayed initialization in ppu_initialize()
auto& _main = g_fxo->get<ppu_module>();
auto& _main = g_fxo->get<main_ppu_module>();
// Access linkage information object
auto& link = g_fxo->get<ppu_linkage_info>();
@ -2126,11 +2126,9 @@ bool ppu_load_exec(const ppu_exec_object& elf, utils::serial* ar)
_main.name.clear();
_main.path = vfs::get(Emu.argv[0]);
// Analyse executable (TODO)
_main.analyse(0, static_cast<u32>(elf.header.e_entry), end, applied);
// Validate analyser results (not required)
_main.validate(0);
_main.elf_entry = static_cast<u32>(elf.header.e_entry);
_main.seg0_code_end = end;
_main.applied_pathes = applied;
// Set SDK version
g_ps3_process_info.sdk_ver = sdk_version;

View file

@ -3200,7 +3200,7 @@ extern void ppu_precompile(std::vector<std::string>& dir_queue, std::vector<ppu_
extern void ppu_initialize()
{
if (!g_fxo->is_init<ppu_module>())
if (!g_fxo->is_init<main_ppu_module>())
{
return;
}
@ -3210,9 +3210,20 @@ extern void ppu_initialize()
return;
}
auto& _main = g_fxo->get<ppu_module>();
auto& _main = g_fxo->get<main_ppu_module>();
scoped_progress_dialog progr = "Scanning PPU modules...";
scoped_progress_dialog progr = "Analyzing PPU Executable...";
// Analyse executable
if (!_main.analyse(0, _main.elf_entry, _main.seg0_code_end, _main.applied_pathes, [](){ return Emu.IsStopped(); }))
{
return;
}
// Validate analyser results (not required)
_main.validate(0);
g_progr = "Scanning PPU Modules...";
bool compile_main = false;

View file

@ -185,7 +185,7 @@ void Emulator::BlockingCallFromMainThread(std::function<void()>&& func) const
// This function ensures constant initialization order between different compilers and builds
void init_fxo_for_exec(utils::serial* ar, bool full = false)
{
g_fxo->init<ppu_module>();
g_fxo->init<main_ppu_module>();
void init_ppu_functions(utils::serial* ar, bool full);
@ -1352,7 +1352,7 @@ game_boot_result Emulator::Load(const std::string& title_id, bool add_only, bool
{
m_state = system_state::ready;
GetCallbacks().on_ready();
g_fxo->init<ppu_module>();
g_fxo->init<main_ppu_module>();
vm::init();
m_force_boot = false;
@ -1435,7 +1435,7 @@ game_boot_result Emulator::Load(const std::string& title_id, bool add_only, bool
if (obj == elf_error::ok && ppu_load_exec(obj))
{
g_fxo->get<ppu_module>().path = path;
g_fxo->get<main_ppu_module>().path = path;
}
else
{
@ -1455,14 +1455,14 @@ game_boot_result Emulator::Load(const std::string& title_id, bool add_only, bool
}
}
if (auto& _main = g_fxo->get<ppu_module>(); _main.path.empty())
if (auto& _main = g_fxo->get<main_ppu_module>(); _main.path.empty())
{
init_fxo_for_exec(nullptr, false);
}
g_fxo->init<named_thread>("SPRX Loader"sv, [this, dir_queue]() mutable
{
if (auto& _main = g_fxo->get<ppu_module>(); !_main.path.empty())
if (auto& _main = g_fxo->get<main_ppu_module>(); !_main.path.empty())
{
ppu_initialize(_main);
}
@ -2020,7 +2020,7 @@ game_boot_result Emulator::Load(const std::string& title_id, bool add_only, bool
sys_log.error("Booting HG category outside of HDD0!");
}
g_fxo->init<ppu_module>();
g_fxo->init<main_ppu_module>();
if (ppu_load_exec(ppu_exec, DeserialManager()))
{
@ -2032,7 +2032,7 @@ game_boot_result Emulator::Load(const std::string& title_id, bool add_only, bool
}
else
{
// Preserve emulation state for OVL excutable
// Preserve emulation state for OVL executable
Pause(true);
}
@ -3026,7 +3026,7 @@ s32 error_code::error_report(s32 result, const logs::message* channel, const cha
void Emulator::ConfigurePPUCache() const
{
auto& _main = g_fxo->get<ppu_module>();
auto& _main = g_fxo->get<main_ppu_module>();
_main.cache = rpcs3::utils::get_cache_dir();

View file

@ -12,9 +12,9 @@ namespace rpcs3::cache
{
std::string get_ppu_cache()
{
auto& _main = g_fxo->get<ppu_module>();
auto& _main = g_fxo->get<main_ppu_module>();
if (!g_fxo->is_init<ppu_module>() || _main.cache.empty())
if (!g_fxo->is_init<main_ppu_module>() || _main.cache.empty())
{
ppu_log.error("PPU Cache location not initialized.");
return {};

View file

@ -18,7 +18,7 @@ class scoped_progress_dialog final
const char* const m_prev;
public:
scoped_progress_dialog(const char* text)
scoped_progress_dialog(const char* text) noexcept
: m_prev(g_progr.exchange(text ? text : ""))
{
}
@ -27,7 +27,7 @@ public:
scoped_progress_dialog& operator=(const scoped_progress_dialog&) = delete;
~scoped_progress_dialog()
~scoped_progress_dialog() noexcept
{
g_progr.release(m_prev);
}

View file

@ -441,7 +441,7 @@ bool cheat_engine::is_addr_safe(const u32 offset)
if (Emu.IsStopped())
return false;
const auto ppum = g_fxo->try_get<ppu_module>();
const auto ppum = g_fxo->try_get<main_ppu_module>();
if (!ppum)
{