mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-05 06:21:26 +12:00
Implement Emulator::GracefulShutdown()
This commit is contained in:
parent
6c5b8dc31c
commit
e951c619c5
17 changed files with 180 additions and 89 deletions
|
@ -179,7 +179,7 @@ public:
|
|||
// Callback for thread_ctrl::wait or RSX wait
|
||||
virtual void cpu_wait(bs_t<cpu_flag> old);
|
||||
|
||||
// Callback for function abortion stats on Emu.Stop()
|
||||
// Callback for function abortion stats on Emu.Kill()
|
||||
virtual void cpu_on_stop() {}
|
||||
|
||||
// For internal use
|
||||
|
|
|
@ -56,8 +56,10 @@ extern void sysutil_register_cb(std::function<s32(ppu_thread&)>&& cb)
|
|||
cbm.registered.push(std::move(cb));
|
||||
}
|
||||
|
||||
extern void sysutil_send_system_cmd(u64 status, u64 param)
|
||||
extern u32 sysutil_send_system_cmd(u64 status, u64 param)
|
||||
{
|
||||
u32 count = 0;
|
||||
|
||||
if (auto cbm = g_fxo->try_get<sysutil_cb_manager>())
|
||||
{
|
||||
for (sysutil_cb_manager::registered_cb cb : cbm->callbacks)
|
||||
|
@ -70,9 +72,13 @@ extern void sysutil_send_system_cmd(u64 status, u64 param)
|
|||
cb.first(ppu, status, param, cb.second);
|
||||
return CELL_OK;
|
||||
});
|
||||
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
template <>
|
||||
|
|
|
@ -301,5 +301,5 @@ struct CellSysCacheParam
|
|||
};
|
||||
|
||||
extern void sysutil_register_cb(std::function<s32(ppu_thread&)>&&);
|
||||
extern void sysutil_send_system_cmd(u64 status, u64 param);
|
||||
extern u32 sysutil_send_system_cmd(u64 status, u64 param);
|
||||
s32 sysutil_check_name_string(const char* src, s32 minlen, s32 maxlen);
|
||||
|
|
|
@ -3405,7 +3405,7 @@ static void ppu_initialize2(jit_compiler& jit, const ppu_module& module_part, co
|
|||
{
|
||||
out.flush();
|
||||
ppu_log.error("LLVM: Verification failed for %s:\n%s", obj_name, result);
|
||||
Emu.CallAfter([]{ Emu.Stop(); });
|
||||
Emu.CallAfter([]{ Emu.GracefulShutdown(false, true); });
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -349,7 +349,7 @@ void _sys_process_exit(ppu_thread& ppu, s32 status, u32 arg2, u32 arg3)
|
|||
Emu.CallAfter([]()
|
||||
{
|
||||
sys_process.success("Process finished");
|
||||
Emu.Stop();
|
||||
Emu.Kill();
|
||||
});
|
||||
|
||||
// Wait for GUI thread
|
||||
|
@ -415,8 +415,7 @@ void _sys_process_exit2(ppu_thread& ppu, s32 status, vm::ptr<sys_exit2_param> ar
|
|||
, hdd1 = std::move(hdd1), klic = g_fxo->get<loaded_npdrm_keys>().last_key(), old_config = Emu.GetUsedConfig()]() mutable
|
||||
{
|
||||
sys_process.success("Process finished -> %s", argv[0]);
|
||||
Emu.SetForceBoot(true);
|
||||
Emu.Stop();
|
||||
Emu.Kill(false);
|
||||
Emu.argv = std::move(argv);
|
||||
Emu.envp = std::move(envp);
|
||||
Emu.data = std::move(data);
|
||||
|
@ -435,7 +434,7 @@ void _sys_process_exit2(ppu_thread& ppu, s32 status, vm::ptr<sys_exit2_param> ar
|
|||
if (res != game_boot_result::no_errors)
|
||||
{
|
||||
sys_process.fatal("Failed to boot from exitspawn! (path=\"%s\", error=%s)", path, res);
|
||||
Emu.Stop();
|
||||
Emu.Kill();
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -719,7 +719,7 @@ bool gdb_thread::cmd_attached_to_what(gdb_cmd&)
|
|||
bool gdb_thread::cmd_kill(gdb_cmd&)
|
||||
{
|
||||
GDB.notice("Kill command issued");
|
||||
Emu.Stop();
|
||||
Emu.CallAfter([](){ Emu.GracefulShutdown(); });
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ namespace rsx
|
|||
Emu.CallAfter([]()
|
||||
{
|
||||
rsx_log.notice("Aborted shader loading dialog");
|
||||
Emu.Stop();
|
||||
Emu.Kill(false);
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ namespace rsx
|
|||
if (status != CELL_OK)
|
||||
{
|
||||
rsx_log.notice("Aborted shader loading dialog");
|
||||
Emu.Stop();
|
||||
Emu.Kill(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -558,7 +558,7 @@ game_boot_result Emulator::Load(const std::string& title_id, bool add_only, bool
|
|||
|
||||
if (!IsStopped())
|
||||
{
|
||||
Stop();
|
||||
Kill();
|
||||
}
|
||||
|
||||
if (!title_id.empty())
|
||||
|
@ -886,8 +886,7 @@ game_boot_result Emulator::Load(const std::string& title_id, bool add_only, bool
|
|||
// Exit "process"
|
||||
CallAfter([]
|
||||
{
|
||||
Emu.SetForceBoot(true);
|
||||
Emu.Stop();
|
||||
Emu.Kill(false);
|
||||
});
|
||||
|
||||
m_path = m_path_old; // Reset m_path to fix boot from gui
|
||||
|
@ -1408,8 +1407,7 @@ game_boot_result Emulator::Load(const std::string& title_id, bool add_only, bool
|
|||
|
||||
if (ppu_exec != elf_error::ok)
|
||||
{
|
||||
SetForceBoot(true);
|
||||
Stop();
|
||||
Kill(false);
|
||||
|
||||
sys_log.error("Invalid or unsupported PPU executable format: %s", elf_path);
|
||||
|
||||
|
@ -1440,8 +1438,7 @@ game_boot_result Emulator::Load(const std::string& title_id, bool add_only, bool
|
|||
sys_log.warning("** ppu_prx -> %s", ppu_prx.get_error());
|
||||
sys_log.warning("** spu_exec -> %s", spu_exec.get_error());
|
||||
|
||||
SetForceBoot(true);
|
||||
Stop();
|
||||
Kill(false);
|
||||
return game_boot_result::invalid_file_or_folder;
|
||||
}
|
||||
|
||||
|
@ -1458,8 +1455,7 @@ game_boot_result Emulator::Load(const std::string& title_id, bool add_only, bool
|
|||
return libs.count(std::string(lib.first) + ":lle") || (!lib.second && !libs.count(std::string(lib.first) + ":hle"));
|
||||
}))
|
||||
{
|
||||
SetForceBoot(true);
|
||||
Stop();
|
||||
Kill(false);
|
||||
|
||||
CallAfter([this]()
|
||||
{
|
||||
|
@ -1581,17 +1577,13 @@ bool Emulator::Pause(bool freeze_emulation)
|
|||
|
||||
void Emulator::Resume()
|
||||
{
|
||||
// Get pause start time
|
||||
const u64 time = m_pause_start_time.exchange(0);
|
||||
|
||||
// Try to increment summary pause time
|
||||
if (time)
|
||||
if (m_state != system_state::paused)
|
||||
{
|
||||
m_pause_amend_time += get_system_time() - time;
|
||||
return;
|
||||
}
|
||||
|
||||
// Print and reset debug data collected
|
||||
if (m_state == system_state::paused && g_cfg.core.ppu_debug)
|
||||
if (g_cfg.core.ppu_debug)
|
||||
{
|
||||
PPUDisAsm dis_asm(cpu_disasm_mode::dump, vm::g_sudo_addr);
|
||||
|
||||
|
@ -1619,19 +1611,27 @@ void Emulator::Resume()
|
|||
ppu_log.notice("[RESUME] Dumping instruction stats:%s", dump);
|
||||
}
|
||||
|
||||
perf_stat_base::report();
|
||||
|
||||
// Try to resume
|
||||
if (!m_state.compare_and_swap_test(system_state::paused, system_state::running))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!time)
|
||||
// Get pause start time
|
||||
const u64 time = m_pause_start_time.exchange(0);
|
||||
|
||||
// Try to increment summary pause time
|
||||
if (time)
|
||||
{
|
||||
m_pause_amend_time += get_system_time() - time;
|
||||
}
|
||||
else
|
||||
{
|
||||
sys_log.error("Emulator::Resume() error: concurrent access");
|
||||
}
|
||||
|
||||
perf_stat_base::report();
|
||||
|
||||
auto on_select = [](u32, cpu_thread& cpu)
|
||||
{
|
||||
cpu.state -= cpu_flag::dbg_global_pause;
|
||||
|
@ -1657,25 +1657,70 @@ void Emulator::Resume()
|
|||
}
|
||||
}
|
||||
|
||||
void Emulator::Stop(bool restart)
|
||||
u32 sysutil_send_system_cmd(u64 status, u64 param);
|
||||
void process_qt_events();
|
||||
|
||||
void Emulator::GracefulShutdown(bool allow_autoexit, bool async_op)
|
||||
{
|
||||
if (m_state.exchange(system_state::stopped) == system_state::stopped)
|
||||
const auto old_state = m_state.load();
|
||||
|
||||
if (old_state == system_state::stopped)
|
||||
{
|
||||
if (restart)
|
||||
{
|
||||
// Reload with prior configs.
|
||||
if (const auto error = Load(m_title_id); error != game_boot_result::no_errors)
|
||||
sys_log.error("Restart failed: %s", error);
|
||||
return;
|
||||
}
|
||||
|
||||
m_force_boot = false;
|
||||
if (old_state == system_state::paused)
|
||||
{
|
||||
Resume();
|
||||
}
|
||||
|
||||
if (old_state == system_state::frozen || !sysutil_send_system_cmd(0x0101 /* CELL_SYSUTIL_REQUEST_EXITGAME */, 0))
|
||||
{
|
||||
// The callback has been rudely ignored, we have no other option but to force termination
|
||||
Kill(allow_autoexit);
|
||||
return;
|
||||
}
|
||||
|
||||
auto perform_kill = [allow_autoexit, this, info = ProcureCurrentEmulationCourseInformation()]()
|
||||
{
|
||||
for (u32 i = 0; i < 50; i++)
|
||||
{
|
||||
std::this_thread::sleep_for(50ms);
|
||||
Resume(); // TODO: Prevent pausing by other threads while in this loop
|
||||
process_qt_events(); // Is nullified when performed on non-main thread
|
||||
|
||||
if (static_cast<u64>(info) != m_stop_ctr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// An inevitable attempt to terminate the *current* emulation course will be issued after 5s
|
||||
CallAfter([allow_autoexit, this]()
|
||||
{
|
||||
Kill(allow_autoexit);
|
||||
}, info);
|
||||
};
|
||||
|
||||
if (async_op)
|
||||
{
|
||||
std::thread{perform_kill}.detach();
|
||||
}
|
||||
else
|
||||
{
|
||||
perform_kill();
|
||||
}
|
||||
}
|
||||
|
||||
void Emulator::Kill(bool allow_autoexit)
|
||||
{
|
||||
if (m_state.exchange(system_state::stopped) == system_state::stopped)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
sys_log.notice("Stopping emulator...");
|
||||
|
||||
if (!restart)
|
||||
{
|
||||
// Show visual feedback to the user in case that stopping takes a while.
|
||||
// This needs to be done before actually stopping, because otherwise the necessary threads will be terminated before we can show an image.
|
||||
|
@ -1783,15 +1828,7 @@ void Emulator::Stop(bool restart)
|
|||
m_stop_ctr++;
|
||||
m_stop_ctr.notify_all();
|
||||
|
||||
if (restart)
|
||||
{
|
||||
// Reload with prior configs.
|
||||
if (const auto error = Load(m_title_id); error != game_boot_result::no_errors)
|
||||
sys_log.error("Restart failed: %s", error);
|
||||
return;
|
||||
}
|
||||
|
||||
// Boot arg cleanup (preserved in the case restarting)
|
||||
// Boot arg cleanup
|
||||
argv.clear();
|
||||
envp.clear();
|
||||
data.clear();
|
||||
|
@ -1804,15 +1841,36 @@ void Emulator::Stop(bool restart)
|
|||
// Always Enable display sleep, not only if it was prevented.
|
||||
enable_display_sleep();
|
||||
|
||||
if (!m_force_boot)
|
||||
if (allow_autoexit)
|
||||
{
|
||||
if (Quit(g_cfg.misc.autoexit.get()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_force_boot = false;
|
||||
game_boot_result Emulator::Restart()
|
||||
{
|
||||
if (m_state == system_state::stopped)
|
||||
{
|
||||
return game_boot_result::generic_error;
|
||||
}
|
||||
|
||||
auto save_args = std::make_tuple(argv, envp, data, disc, klic, hdd1, m_config_mode, m_config_mode);
|
||||
|
||||
GracefulShutdown(false, false);
|
||||
|
||||
std::tie(argv, envp, data, disc, klic, hdd1, m_config_mode, m_config_mode) = std::move(save_args);
|
||||
|
||||
// Reload with prior configs.
|
||||
if (const auto error = Load(m_title_id); error != game_boot_result::no_errors)
|
||||
{
|
||||
sys_log.error("Restart failed: %s", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
return game_boot_result::no_errors;
|
||||
}
|
||||
|
||||
bool Emulator::Quit(bool force_quit)
|
||||
|
|
|
@ -111,9 +111,9 @@ class Emulator final
|
|||
std::string m_usr{"00000001"};
|
||||
u32 m_usrid{1};
|
||||
|
||||
// This flag should be adjusted before each Stop() or each BootGame() and similar because:
|
||||
// This flag should be adjusted before each Kill() or each BootGame() and similar because:
|
||||
// 1. It forces an application to boot immediately by calling Run() in Load().
|
||||
// 2. It signifies that we don't want to exit on Stop(), for example if we want to transition to another application.
|
||||
// 2. It signifies that we don't want to exit on Kill(), for example if we want to transition to another application.
|
||||
bool m_force_boot = false;
|
||||
|
||||
bool m_has_gui = true;
|
||||
|
@ -132,14 +132,14 @@ public:
|
|||
}
|
||||
|
||||
// Call from the GUI thread
|
||||
void CallAfter(std::function<void()>&& func, bool track_emu_state = true) const
|
||||
void CallAfter(std::function<void()>&& func, bool track_emu_state = true, u64 stop_ctr = umax) const
|
||||
{
|
||||
if (!track_emu_state)
|
||||
{
|
||||
return m_cb.call_after(std::move(func));
|
||||
}
|
||||
|
||||
std::function<void()> final_func = [this, before = IsStopped(), count = +m_stop_ctr, func = std::move(func)]
|
||||
std::function<void()> final_func = [this, before = IsStopped(), count = (stop_ctr == umax ? +m_stop_ctr : stop_ctr), func = std::move(func)]
|
||||
{
|
||||
if (count == m_stop_ctr && before == IsStopped())
|
||||
{
|
||||
|
@ -150,6 +150,18 @@ public:
|
|||
return m_cb.call_after(std::move(final_func));
|
||||
}
|
||||
|
||||
enum class stop_counter_t : u64{};
|
||||
|
||||
stop_counter_t ProcureCurrentEmulationCourseInformation() const
|
||||
{
|
||||
return stop_counter_t{+m_stop_ctr};
|
||||
}
|
||||
|
||||
void CallAfter(std::function<void()>&& func, stop_counter_t counter) const
|
||||
{
|
||||
CallAfter(std::move(func), true, static_cast<u64>(counter));
|
||||
}
|
||||
|
||||
/** Set emulator mode to running unconditionnaly.
|
||||
* Required to execute various part (PPUInterpreter, memory manager...) outside of rpcs3.
|
||||
*/
|
||||
|
@ -244,8 +256,9 @@ public:
|
|||
void Run(bool start_playtime);
|
||||
bool Pause(bool freeze_emulation = false);
|
||||
void Resume();
|
||||
void Stop(bool restart = false);
|
||||
void Restart() { Stop(true); }
|
||||
void GracefulShutdown(bool allow_autoexit = true, bool async_op = false);
|
||||
void Kill(bool allow_autoexit = true);
|
||||
game_boot_result Restart();
|
||||
bool Quit(bool force_quit);
|
||||
static void CleanUp();
|
||||
|
||||
|
|
|
@ -92,7 +92,7 @@ void progress_dialog_server::operator()()
|
|||
{
|
||||
// Abort everything
|
||||
sys_log.notice("Aborted progress dialog");
|
||||
Emu.Stop();
|
||||
Emu.GracefulShutdown(false, true);
|
||||
});
|
||||
|
||||
g_system_progress_canceled = true;
|
||||
|
|
|
@ -62,8 +62,7 @@ auto_pause_settings_dialog::auto_pause_settings_dialog(QWidget *parent) : QDialo
|
|||
});
|
||||
connect(cancelButton, &QAbstractButton::clicked, this, &QWidget::close);
|
||||
|
||||
Emu.SetForceBoot(true);
|
||||
Emu.Stop();
|
||||
Emu.GracefulShutdown(false);
|
||||
|
||||
LoadEntries();
|
||||
UpdateList();
|
||||
|
|
|
@ -1402,8 +1402,7 @@ void game_list_frame::ShowContextMenu(const QPoint &pos)
|
|||
|
||||
bool game_list_frame::CreatePPUCache(const std::string& path, const std::string& serial)
|
||||
{
|
||||
Emu.SetForceBoot(true);
|
||||
Emu.Stop();
|
||||
Emu.GracefulShutdown(false);
|
||||
Emu.SetForceBoot(true);
|
||||
|
||||
if (const auto error = Emu.BootGame(path, serial, true); error != game_boot_result::no_errors)
|
||||
|
@ -1701,7 +1700,7 @@ void game_list_frame::BatchCreatePPUCaches()
|
|||
if (!Emu.IsStopped())
|
||||
{
|
||||
QApplication::processEvents();
|
||||
Emu.Stop();
|
||||
Emu.GracefulShutdown(false);
|
||||
}
|
||||
|
||||
if (!pdlg->wasCanceled())
|
||||
|
|
|
@ -363,7 +363,7 @@ void gs_frame::close()
|
|||
|
||||
if (!Emu.IsStopped())
|
||||
{
|
||||
Emu.Stop();
|
||||
Emu.GracefulShutdown(true, false);
|
||||
}
|
||||
|
||||
deleteLater();
|
||||
|
|
|
@ -69,6 +69,14 @@ std::shared_ptr<CPUDisAsm> make_basic_ppu_disasm();
|
|||
|
||||
inline std::string sstr(const QString& _in) { return _in.toStdString(); }
|
||||
|
||||
extern void process_qt_events()
|
||||
{
|
||||
if (thread_ctrl::is_main())
|
||||
{
|
||||
QApplication::processEvents();
|
||||
}
|
||||
}
|
||||
|
||||
main_window::main_window(std::shared_ptr<gui_settings> gui_settings, std::shared_ptr<emu_settings> emu_settings, std::shared_ptr<persistent_settings> persistent_settings, QWidget *parent)
|
||||
: QMainWindow(parent)
|
||||
, ui(new Ui::main_window)
|
||||
|
@ -189,7 +197,7 @@ bool main_window::Init(bool with_cli_boot)
|
|||
connect(m_thumb_stop, &QWinThumbnailToolButton::clicked, this, []()
|
||||
{
|
||||
gui_log.notice("User clicked stop button on thumbnail toolbar");
|
||||
Emu.Stop();
|
||||
Emu.GracefulShutdown(false, true);
|
||||
});
|
||||
connect(m_thumb_restart, &QWinThumbnailToolButton::clicked, this, []()
|
||||
{
|
||||
|
@ -399,10 +407,9 @@ void main_window::Boot(const std::string& path, const std::string& title_id, boo
|
|||
return;
|
||||
}
|
||||
|
||||
m_app_icon = gui::utils::get_app_icon_from_path(path, title_id);
|
||||
Emu.GracefulShutdown(false);
|
||||
|
||||
Emu.SetForceBoot(true);
|
||||
Emu.Stop();
|
||||
m_app_icon = gui::utils::get_app_icon_from_path(path, title_id);
|
||||
|
||||
if (const auto error = Emu.BootGame(path, title_id, direct, add_only, config_mode, config_path); error != game_boot_result::no_errors)
|
||||
{
|
||||
|
@ -524,8 +531,7 @@ void main_window::BootRsxCapture(std::string path)
|
|||
return;
|
||||
}
|
||||
|
||||
Emu.SetForceBoot(true);
|
||||
Emu.Stop();
|
||||
Emu.GracefulShutdown(false);
|
||||
|
||||
if (!Emu.BootRsxCapture(path))
|
||||
{
|
||||
|
@ -651,6 +657,17 @@ void main_window::InstallPackages(QStringList file_paths)
|
|||
}
|
||||
}
|
||||
|
||||
if (!m_gui_settings->GetBootConfirmation(this))
|
||||
{
|
||||
// Last chance to cancel the operation
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Emu.IsStopped())
|
||||
{
|
||||
Emu.GracefulShutdown(false);
|
||||
}
|
||||
|
||||
// Install rap files if available
|
||||
int installed_rap_and_edat_count = 0;
|
||||
|
||||
|
@ -732,6 +749,8 @@ void main_window::HandlePackageInstallation(QStringList file_paths)
|
|||
return;
|
||||
}
|
||||
|
||||
Emu.GracefulShutdown(false);
|
||||
|
||||
progress_dialog pdlg(tr("RPCS3 Package Installer"), tr("Installing package, please wait..."), tr("Cancel"), 0, 1000, false, this);
|
||||
pdlg.setAutoClose(false);
|
||||
pdlg.show();
|
||||
|
@ -774,9 +793,6 @@ void main_window::HandlePackageInstallation(QStringList file_paths)
|
|||
pdlg.setLabelText(tr("Installing package (%0/%1), please wait...\n\n%2").arg(i + 1).arg(count).arg(app_info));
|
||||
pdlg.show();
|
||||
|
||||
Emu.SetForceBoot(true);
|
||||
Emu.Stop();
|
||||
|
||||
const QFileInfo file_info(package.path);
|
||||
const std::string path = sstr(package.path);
|
||||
const std::string file_name = sstr(file_info.fileName());
|
||||
|
@ -934,8 +950,7 @@ void main_window::ExtractTar()
|
|||
return;
|
||||
}
|
||||
|
||||
Emu.SetForceBoot(true);
|
||||
Emu.Stop();
|
||||
Emu.GracefulShutdown(false);
|
||||
|
||||
const QString path_last_tar = m_gui_settings->GetValue(gui::fd_ext_tar).toString();
|
||||
QStringList files = QFileDialog::getOpenFileNames(this, tr("Select TAR To extract"), path_last_tar, tr("All tar files (*.tar *.TAR *.tar.aa.* *.TAR.AA.*);;All files (*.*)"));
|
||||
|
@ -1011,8 +1026,7 @@ void main_window::HandlePupInstallation(const QString& file_path, const QString&
|
|||
return;
|
||||
}
|
||||
|
||||
Emu.SetForceBoot(true);
|
||||
Emu.Stop();
|
||||
Emu.GracefulShutdown(false);
|
||||
|
||||
m_gui_settings->SetValue(gui::fd_install_pup, QFileInfo(file_path).path());
|
||||
|
||||
|
@ -1257,7 +1271,7 @@ void main_window::HandlePupInstallation(const QString& file_path, const QString&
|
|||
}
|
||||
|
||||
// This is ugly, but PS3 headers shall not be included there.
|
||||
extern void sysutil_send_system_cmd(u64 status, u64 param);
|
||||
extern u32 sysutil_send_system_cmd(u64 status, u64 param);
|
||||
|
||||
void main_window::DecryptSPRXLibraries()
|
||||
{
|
||||
|
@ -2026,6 +2040,8 @@ void main_window::CreateConnects()
|
|||
|
||||
if (!paths.isEmpty())
|
||||
{
|
||||
Emu.GracefulShutdown(false);
|
||||
|
||||
for (const QString& path : paths)
|
||||
{
|
||||
AddGamesFromDir(path);
|
||||
|
@ -2087,7 +2103,7 @@ void main_window::CreateConnects()
|
|||
connect(ui->sysStopAct, &QAction::triggered, this, []()
|
||||
{
|
||||
gui_log.notice("User triggered stop action in menu bar");
|
||||
Emu.Stop();
|
||||
Emu.GracefulShutdown(false, true);
|
||||
});
|
||||
connect(ui->sysRebootAct, &QAction::triggered, this, []()
|
||||
{
|
||||
|
@ -2415,7 +2431,7 @@ void main_window::CreateConnects()
|
|||
connect(ui->toolbar_stop, &QAction::triggered, this, []()
|
||||
{
|
||||
gui_log.notice("User triggered stop action in toolbar");
|
||||
Emu.Stop();
|
||||
Emu.GracefulShutdown(false);
|
||||
});
|
||||
connect(ui->toolbar_start, &QAction::triggered, this, &main_window::OnPlayOrPause);
|
||||
|
||||
|
@ -2762,8 +2778,7 @@ void main_window::CreateFirmwareCache()
|
|||
return;
|
||||
}
|
||||
|
||||
Emu.SetForceBoot(true);
|
||||
Emu.Stop();
|
||||
Emu.GracefulShutdown(false);
|
||||
Emu.SetForceBoot(true);
|
||||
|
||||
if (const game_boot_result error = Emu.BootGame(g_cfg_vfs.get_dev_flash() + "sys", "", true);
|
||||
|
@ -2811,8 +2826,9 @@ void main_window::closeEvent(QCloseEvent* closeEvent)
|
|||
// Cleanly stop and quit the emulator.
|
||||
if (!Emu.IsStopped())
|
||||
{
|
||||
Emu.Stop();
|
||||
Emu.GracefulShutdown(false);
|
||||
}
|
||||
|
||||
Emu.Quit(true);
|
||||
}
|
||||
|
||||
|
@ -3007,10 +3023,13 @@ void main_window::dropEvent(QDropEvent* event)
|
|||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (const auto& path : drop_paths)
|
||||
{
|
||||
Emu.GracefulShutdown(false);
|
||||
AddGamesFromDir(path);
|
||||
}
|
||||
|
||||
m_game_list_frame->Refresh(true);
|
||||
break;
|
||||
}
|
||||
|
@ -3021,8 +3040,7 @@ void main_window::dropEvent(QDropEvent* event)
|
|||
return;
|
||||
}
|
||||
|
||||
Emu.SetForceBoot(true);
|
||||
Emu.Stop();
|
||||
Emu.GracefulShutdown(false);
|
||||
|
||||
if (const auto error = Emu.BootGame(sstr(drop_paths.first()), "", true); error != game_boot_result::no_errors)
|
||||
{
|
||||
|
|
|
@ -655,8 +655,7 @@ bool update_manager::handle_rpcs3(const QByteArray& data, bool auto_accept)
|
|||
QMessageBox::information(m_parent, tr("Auto-updater"), tr("Update successful!\nRPCS3 will now restart."));
|
||||
}
|
||||
|
||||
Emu.SetForceBoot(true);
|
||||
Emu.Stop();
|
||||
Emu.GracefulShutdown(false);
|
||||
Emu.CleanUp();
|
||||
|
||||
#ifdef _WIN32
|
||||
|
|
|
@ -361,7 +361,7 @@ void user_manager_dialog::OnUserLogin()
|
|||
}
|
||||
|
||||
gui_log.notice("Stopping current emulation in order to change the current user.");
|
||||
Emu.Stop();
|
||||
Emu.GracefulShutdown(false);
|
||||
}
|
||||
|
||||
const u32 key = GetUserKey();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue