Qt: Deprecate proccessEvents() usage

This commit is contained in:
Elad 2024-11-24 09:23:32 +02:00
parent 3e427c57f0
commit fce07bbeab
9 changed files with 215 additions and 221 deletions

View file

@ -72,7 +72,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<void()> on_missing_fw;
std::function<void(std::shared_ptr<atomic_t<bool>>, int)> on_emulation_stop_no_response;
std::function<void(std::shared_ptr<atomic_t<bool>>, stx::shared_ptr<utils::serial>, stx::atomic_ptr<std::string>*, std::shared_ptr<void>)> on_save_state_progress;
std::function<void(bool enabled)> enable_disc_eject;
@ -183,7 +183,8 @@ public:
static constexpr std::string_view game_id_boot_prefix = "%RPCS3_GAMEID%:";
static constexpr std::string_view vfs_boot_prefix = "%RPCS3_VFS%:";
Emulator() = default;
Emulator() noexcept = default;
~Emulator() noexcept = default;
void SetCallbacks(EmuCallbacks&& cb)
{
@ -366,7 +367,7 @@ public:
bool IsRunning() const { return m_state == system_state::running; }
bool IsPaused() const { return m_state >= system_state::paused; } // ready/starting are also considered paused by this function
bool IsStopped() const { return m_state <= system_state::stopping; }
bool IsStopped(bool test_fully = false) const { return test_fully ? m_state == system_state::stopped : m_state <= system_state::stopping; }
bool IsReady() const { return m_state == system_state::ready; }
bool IsStarting() const { return m_state == system_state::starting; }
auto GetStatus(bool fixup = true) const { system_state state = m_state; return fixup && state == system_state::frozen ? system_state::paused : fixup && state == system_state::stopping ? system_state::stopped : state; }

View file

@ -155,7 +155,7 @@ void headless_application::InitializeCallbacks()
callbacks.enable_disc_eject = [](bool) {};
callbacks.enable_disc_insert = [](bool) {};
callbacks.on_missing_fw = []() { return false; };
callbacks.on_missing_fw = []() {};
callbacks.handle_taskbar_progress = [](s32, s32) {};

View file

@ -11,6 +11,7 @@
about_dialog::about_dialog(QWidget* parent) : QDialog(parent), ui(new Ui::about_dialog)
{
ui->setupUi(this);
setAttribute(Qt::WA_DeleteOnClose);
ui->close->setDefault(true);
ui->icon->load(QStringLiteral(":/rpcs3.svg"));

View file

@ -1133,7 +1133,7 @@ void game_list_frame::ShowContextMenu(const QPoint &pos)
static const auto is_game_running = [](const std::string& serial)
{
return Emu.GetStatus(false) != system_state::stopped && (serial == Emu.GetTitleID() || (serial == "vsh.self" && Emu.IsVsh()));
return !Emu.IsStopped(true) && (serial == Emu.GetTitleID() || (serial == "vsh.self" && Emu.IsVsh()));
};
const bool is_current_running_game = is_game_running(current_game.serial);
@ -2048,7 +2048,7 @@ bool game_list_frame::RemoveCustomPadConfiguration(const std::string& title_id,
if (!fs::is_dir(config_dir))
return true;
if (is_interactive && QMessageBox::question(this, tr("Confirm Removal"), (!Emu.IsStopped() && Emu.GetTitleID() == title_id)
if (is_interactive && QMessageBox::question(this, tr("Confirm Removal"), (!Emu.IsStopped(true) && Emu.GetTitleID() == title_id)
? tr("Remove custom pad configuration?\nYour configuration will revert to the global pad settings.")
: tr("Remove custom pad configuration?")) != QMessageBox::Yes)
return true;
@ -2064,7 +2064,7 @@ bool game_list_frame::RemoveCustomPadConfiguration(const std::string& title_id,
{
game->hasCustomPadConfig = false;
}
if (!Emu.IsStopped() && Emu.GetTitleID() == title_id)
if (!Emu.IsStopped(true) && Emu.GetTitleID() == title_id)
{
pad::set_enabled(false);
pad::reset(title_id);
@ -2277,11 +2277,124 @@ void game_list_frame::RemoveHDD1Cache(const std::string& base_dir, const std::st
game_list_log.fatal("Only %d/%d HDD1 cache directories could be removed in %s (%s)", dirs_removed, dirs_total, base_dir, title_id);
}
void game_list_frame::BatchActionBySerials(progress_dialog* pdlg, const std::set<std::string>& serials, QString progressLabel, std::function<bool(const std::string&)> action, std::function<void(u32, u32)> cancel_log, bool refresh_on_finish, bool can_be_concurrent, std::function<bool()> should_wait_cb)
{
// Concurrent tasks should not wait (at least not in current implementation)
ensure(!should_wait_cb || !can_be_concurrent);
const std::shared_ptr<std::function<bool(int)>> iterate_over_serial = std::make_shared<std::function<bool(int)>>();
const std::shared_ptr<atomic_t<int>> index = std::make_shared<atomic_t<int>>(0);
const int serials_size = ::narrow<int>(serials.size());
*iterate_over_serial = [=, this, index_ptr = index](int index)
{
if (index == serials_size)
{
return false;
}
const std::string& serial = *std::next(serials.begin(), index);
if (pdlg->wasCanceled() || g_system_progress_canceled)
{
cancel_log(index, serials_size);
return false;
}
else if (action(serial))
{
const int done = index_ptr->load();
pdlg->setLabelText(progressLabel.arg(done + 1).arg(serials_size));
pdlg->SetValue(done + 1);
}
(*index_ptr)++;
return true;
};
if (can_be_concurrent)
{
// Unused currently
QList<int> indices;
for (int i = 0; i < serials_size; i++)
{
indices.append(i);
}
QFutureWatcher<void>* future_watcher = new QFutureWatcher<void>(this);
future_watcher->setFuture(QtConcurrent::map(std::move(indices), *iterate_over_serial));
connect(future_watcher, &QFutureWatcher<void>::finished, this, [=, this]()
{
pdlg->setLabelText(progressLabel.arg(*index).arg(serials_size));
pdlg->setCancelButtonText(tr("OK"));
QApplication::beep();
if (refresh_on_finish && index)
{
Refresh(true);
}
future_watcher->deleteLater();
});
return;
}
const std::shared_ptr<std::function<void()>> periodic_func = std::make_shared<std::function<void()>>();
*periodic_func = [=]()
{
if (should_wait_cb && should_wait_cb())
{
// Conditions are not met for execution
// Check again later
QTimer::singleShot(5, this, *periodic_func);
return;
}
if ((*iterate_over_serial)(*index))
{
QTimer::singleShot(1, this, *periodic_func);
}
else
{
pdlg->setLabelText(progressLabel.arg(*index).arg(serials_size));
pdlg->setCancelButtonText(tr("OK"));
QApplication::beep();
if (refresh_on_finish && index)
{
Refresh(true);
}
pdlg->deleteLater();
}
};
// Invoked on the next event loop processing iteration
QTimer::singleShot(1, this, *periodic_func);
}
void game_list_frame::BatchCreateCPUCaches(const std::vector<game_info>& game_data)
{
const std::string vsh_path = g_cfg_vfs.get_dev_flash() + "vsh/module/";
const bool vsh_exists = game_data.empty() && fs::is_file(vsh_path + "vsh.self");
const usz total = !game_data.empty() ? game_data.size() : (m_game_data.size() + (vsh_exists ? 1 : 0));
std::set<std::string> serials;
if (game_data.empty())
{
serials.emplace("vsh.self");
}
for (const auto& game : (game_data.empty() ? m_game_data : game_data))
{
serials.emplace(game->info.serial);
}
const usz total = serials.size();
if (total == 0)
{
@ -2299,64 +2412,31 @@ void game_list_frame::BatchCreateCPUCaches(const std::vector<game_info>& game_da
progress_dialog* pdlg = new progress_dialog(tr("LLVM Cache Batch Creation"), main_label, tr("Cancel"), 0, ::narrow<s32>(total), false, this);
pdlg->setAutoClose(false);
pdlg->setAutoReset(false);
pdlg->show();
QApplication::processEvents();
pdlg->open();
u32 created = 0;
const auto wait_until_compiled = [pdlg]() -> bool
BatchActionBySerials(pdlg, serials, tr("%0\nProgress: %1/%2 caches compiled").arg(main_label),
[&, game_data](const std::string& serial)
{
while (!Emu.IsStopped())
if (Emu.IsStopped(true))
{
if (pdlg->wasCanceled())
const auto it = std::find_if(m_game_data.begin(), m_game_data.end(), FN(x->info.serial == serial));
if (it != m_game_data.end())
{
return false;
return CreateCPUCaches((*it)->info.path, serial);
}
QApplication::processEvents();
}
return true;
};
if (vsh_exists)
return false;
},
[this](u32, u32)
{
pdlg->setLabelText(tr("%0\nProgress: %1/%2. Compiling caches for VSH...", "Second line after main label").arg(main_label).arg(created).arg(total));
QApplication::processEvents();
if (CreateCPUCaches(vsh_path) && wait_until_compiled())
{
pdlg->SetValue(++created);
}
}
for (const auto& game : (game_data.empty() ? m_game_data : game_data))
{
if (pdlg->wasCanceled() || g_system_progress_canceled)
{
break;
}
pdlg->setLabelText(tr("%0\nProgress: %1/%2. Compiling caches for %3...", "Second line after main label").arg(main_label).arg(created).arg(total).arg(qstr(game->info.serial)));
QApplication::processEvents();
if (CreateCPUCaches(game) && wait_until_compiled())
{
pdlg->SetValue(++created);
}
}
if (pdlg->wasCanceled() || g_system_progress_canceled)
{
pdlg->deleteLater(); // We did not allow deletion earlier to prevent segfaults when canceling.
game_list_log.notice("LLVM Cache Batch Creation was canceled");
Emu.GracefulShutdown(false);
}
else
}, false, false,
[]()
{
pdlg->SetDeleteOnClose();
pdlg->setLabelText(tr("Created LLVM Caches for %n title(s)", "", created));
pdlg->setCancelButtonText(tr("OK"));
QApplication::beep();
}
return !Emu.IsStopped(true);
});
}
void game_list_frame::BatchRemovePPUCaches()
@ -2367,7 +2447,7 @@ void game_list_frame::BatchRemovePPUCaches()
}
std::set<std::string> serials;
serials.emplace("vsh");
serials.emplace("vsh.self");
for (const auto& game : m_game_data)
{
@ -2385,35 +2465,17 @@ void game_list_frame::BatchRemovePPUCaches()
progress_dialog* pdlg = new progress_dialog(tr("PPU Cache Batch Removal"), tr("Removing all PPU caches"), tr("Cancel"), 0, total, false, this);
pdlg->setAutoClose(false);
pdlg->setAutoReset(false);
pdlg->show();
pdlg->open();
u32 removed = 0;
for (const auto& serial : serials)
BatchActionBySerials(pdlg, serials, tr("%0/%1 caches cleared"),
[this](const std::string& serial)
{
if (pdlg->wasCanceled())
{
break;
}
QApplication::processEvents();
if (RemovePPUCache(GetCacheDirBySerial(serial)))
{
pdlg->SetValue(++removed);
}
}
if (pdlg->wasCanceled())
return Emu.IsStopped(true) && RemovePPUCache(GetCacheDirBySerial(serial));
},
[this](u32, u32)
{
pdlg->deleteLater(); // We did not allow deletion earlier to prevent segfaults when canceling.
game_list_log.notice("PPU Cache Batch Removal was canceled");
}
else
{
pdlg->SetDeleteOnClose();
pdlg->setLabelText(tr("%0/%1 caches cleared").arg(removed).arg(total));
pdlg->setCancelButtonText(tr("OK"));
QApplication::beep();
}
}, false);
}
void game_list_frame::BatchRemoveSPUCaches()
@ -2424,7 +2486,7 @@ void game_list_frame::BatchRemoveSPUCaches()
}
std::set<std::string> serials;
serials.emplace("vsh");
serials.emplace("vsh.self");
for (const auto& game : m_game_data)
{
@ -2442,35 +2504,17 @@ void game_list_frame::BatchRemoveSPUCaches()
progress_dialog* pdlg = new progress_dialog(tr("SPU Cache Batch Removal"), tr("Removing all SPU caches"), tr("Cancel"), 0, total, false, this);
pdlg->setAutoClose(false);
pdlg->setAutoReset(false);
pdlg->show();
pdlg->open();
u32 removed = 0;
for (const auto& serial : serials)
BatchActionBySerials(pdlg, serials, tr("%0/%1 caches cleared"),
[this](const std::string& serial)
{
if (pdlg->wasCanceled())
{
break;
}
QApplication::processEvents();
if (RemoveSPUCache(GetCacheDirBySerial(serial)))
{
pdlg->SetValue(++removed);
}
}
if (pdlg->wasCanceled())
return Emu.IsStopped(true) && RemoveSPUCache(GetCacheDirBySerial(serial));
},
[this](u32 removed, u32 total)
{
pdlg->deleteLater(); // We did not allow deletion earlier to prevent segfaults when canceling.
game_list_log.notice("SPU Cache Batch Removal was canceled. %d/%d folders cleared", removed, total);
}
else
{
pdlg->SetDeleteOnClose();
pdlg->setLabelText(tr("%0/%1 caches cleared").arg(removed).arg(total));
pdlg->setCancelButtonText(tr("OK"));
QApplication::beep();
}
}, false);
}
void game_list_frame::BatchRemoveCustomConfigurations()
@ -2483,6 +2527,7 @@ void game_list_frame::BatchRemoveCustomConfigurations()
serials.emplace(game->info.serial);
}
}
const u32 total = ::size32(serials);
if (total == 0)
@ -2494,37 +2539,17 @@ void game_list_frame::BatchRemoveCustomConfigurations()
progress_dialog* pdlg = new progress_dialog(tr("Custom Configuration Batch Removal"), tr("Removing all custom configurations"), tr("Cancel"), 0, total, false, this);
pdlg->setAutoClose(false);
pdlg->setAutoReset(false);
pdlg->show();
pdlg->open();
u32 removed = 0;
for (const auto& serial : serials)
BatchActionBySerials(pdlg, serials, tr("%0/%1 custom configurations cleared"),
[this](const std::string& serial)
{
if (pdlg->wasCanceled())
{
break;
}
QApplication::processEvents();
if (RemoveCustomConfiguration(serial))
{
pdlg->SetValue(++removed);
}
}
if (pdlg->wasCanceled())
return Emu.IsStopped(true) && RemoveCustomConfiguration(serial);
},
[this](u32 removed, u32 total)
{
pdlg->deleteLater(); // We did not allow deletion earlier to prevent segfaults when canceling.
game_list_log.notice("Custom Configuration Batch Removal was canceled. %d/%d custom configurations cleared", removed, total);
}
else
{
pdlg->SetDeleteOnClose();
pdlg->setLabelText(tr("%0/%1 custom configurations cleared").arg(removed).arg(total));
pdlg->setCancelButtonText(tr("OK"));
QApplication::beep();
}
Refresh(true);
}, true);
}
void game_list_frame::BatchRemoveCustomPadConfigurations()
@ -2548,37 +2573,17 @@ void game_list_frame::BatchRemoveCustomPadConfigurations()
progress_dialog* pdlg = new progress_dialog(tr("Custom Pad Configuration Batch Removal"), tr("Removing all custom pad configurations"), tr("Cancel"), 0, total, false, this);
pdlg->setAutoClose(false);
pdlg->setAutoReset(false);
pdlg->show();
pdlg->open();
u32 removed = 0;
for (const auto& serial : serials)
BatchActionBySerials(pdlg, serials, tr("%0/%1 custom pad configurations cleared"),
[this](const std::string& serial)
{
if (pdlg->wasCanceled())
{
break;
}
QApplication::processEvents();
if (RemoveCustomPadConfiguration(serial))
{
pdlg->SetValue(++removed);
}
}
if (pdlg->wasCanceled())
return Emu.IsStopped(true) && RemoveCustomPadConfiguration(serial);
},
[this](u32 removed, u32 total)
{
pdlg->deleteLater(); // We did not allow deletion earlier to prevent segfaults when canceling.
game_list_log.notice("Custom Pad Configuration Batch Removal was canceled. %d/%d custom pad configurations cleared", removed, total);
}
else
{
pdlg->SetDeleteOnClose();
pdlg->setLabelText(tr("%0/%1 custom pad configurations cleared").arg(removed).arg(total));
pdlg->setCancelButtonText(tr("OK"));
QApplication::beep();
}
Refresh(true);
}, true);
}
void game_list_frame::BatchRemoveShaderCaches()
@ -2589,7 +2594,7 @@ void game_list_frame::BatchRemoveShaderCaches()
}
std::set<std::string> serials;
serials.emplace("vsh");
serials.emplace("vsh.self");
for (const auto& game : m_game_data)
{
@ -2607,35 +2612,17 @@ void game_list_frame::BatchRemoveShaderCaches()
progress_dialog* pdlg = new progress_dialog(tr("Shader Cache Batch Removal"), tr("Removing all shader caches"), tr("Cancel"), 0, total, false, this);
pdlg->setAutoClose(false);
pdlg->setAutoReset(false);
pdlg->show();
pdlg->open();
u32 removed = 0;
for (const auto& serial : serials)
BatchActionBySerials(pdlg, serials, tr("%0/%1 shader caches cleared"),
[this](const std::string& serial)
{
if (pdlg->wasCanceled())
{
break;
}
QApplication::processEvents();
if (RemoveShadersCache(GetCacheDirBySerial(serial)))
{
pdlg->SetValue(++removed);
}
}
if (pdlg->wasCanceled())
return Emu.IsStopped(true) && RemoveShadersCache(GetCacheDirBySerial(serial));
},
[this](u32 removed, u32 total)
{
pdlg->deleteLater(); // We did not allow deletion earlier to prevent segfaults when canceling.
game_list_log.notice("Shader Cache Batch Removal was canceled");
}
else
{
pdlg->SetDeleteOnClose();
pdlg->setLabelText(tr("%0/%1 shader caches cleared").arg(removed).arg(total));
pdlg->setCancelButtonText(tr("OK"));
QApplication::beep();
}
game_list_log.notice("Shader Cache Batch Removal was canceled. %d/%d cleared", removed, total);
}, false);
}
void game_list_frame::ShowCustomConfigIcon(const game_info& game)

View file

@ -141,6 +141,7 @@ private:
static u32 RemoveContentPathList(const std::vector<std::string>& path_list, const std::string& desc);
static bool RemoveContentBySerial(const std::string& base_dir, const std::string& serial, const std::string& desc);
static std::vector<std::string> GetDirListBySerial(const std::string& base_dir, const std::string& serial);
void BatchActionBySerials(progress_dialog* pdlg, const std::set<std::string>& serials, QString progressLabel, std::function<bool(const std::string&)> action, std::function<void(u32, u32)> cancel_log, bool refresh_on_finish, bool can_be_concurrent = false, std::function<bool()> should_wait_cb = {});
static std::string GetCacheDirBySerial(const std::string& serial);
static std::string GetDataDirBySerial(const std::string& serial);
std::string CurrentSelectionPath();

View file

@ -577,8 +577,12 @@ void gui_application::InitializeCallbacks()
callbacks.on_missing_fw = [this]()
{
if (!m_main_window) return false;
return m_main_window->OnMissingFw();
if (!m_main_window)
{
return;
}
m_main_window->OnMissingFw();
};
callbacks.handle_taskbar_progress = [this](s32 type, s32 value)

View file

@ -187,7 +187,7 @@ void log_viewer::show_context_menu(const QPoint& pos)
connect(config, &QAction::triggered, this, [this]()
{
config_checker* dlg = new config_checker(this, m_full_log, true);
dlg->exec();
dlg->open();
});
connect(filter, &QAction::triggered, this, [this]()

View file

@ -339,24 +339,23 @@ QIcon main_window::GetAppIcon() const
return m_app_icon;
}
bool main_window::OnMissingFw()
void main_window::OnMissingFw()
{
const QString title = tr("Missing Firmware Detected!");
const QString message = tr("Commercial games require the firmware (PS3UPDAT.PUP file) to be installed."
"\n<br>For information about how to obtain the required firmware read the <a %0 href=\"https://rpcs3.net/quickstart\">quickstart guide</a>.").arg(gui::utils::get_link_style());
QMessageBox mb(QMessageBox::Question, title, message, QMessageBox::Ok | QMessageBox::Cancel, this, Qt::Dialog | Qt::MSWindowsFixedSizeDialogHint | Qt::WindowStaysOnTopHint);
mb.setTextFormat(Qt::RichText);
QMessageBox* mb = new QMessageBox(QMessageBox::Question, title, message, QMessageBox::Ok | QMessageBox::Cancel, this, Qt::Dialog | Qt::MSWindowsFixedSizeDialogHint | Qt::WindowStaysOnTopHint);
mb->setTextFormat(Qt::RichText);
mb.button(QMessageBox::Ok)->setText(tr("Locate PS3UPDAT.PUP"));
mb->button(QMessageBox::Ok)->setText(tr("Locate PS3UPDAT.PUP"));
mb->setAttribute(Qt::WA_DeleteOnClose);
mb->open();
if (mb.exec() == QMessageBox::Ok)
connect(mb, &QDialog::accepted, this, [this]()
{
InstallPup();
return true;
}
return false;
});
}
void main_window::ResizeIcons(int index)
@ -520,13 +519,14 @@ void main_window::show_boot_error(game_boot_result status)
}
const QString link = tr("<br /><br />For information on setting up the emulator and dumping your PS3 games, read the <a %0 href=\"https://rpcs3.net/quickstart\">quickstart guide</a>.").arg(gui::utils::get_link_style());
QMessageBox msg;
msg.setWindowTitle(tr("Boot Failed"));
msg.setIcon(QMessageBox::Critical);
msg.setTextFormat(Qt::RichText);
msg.setStandardButtons(QMessageBox::Ok);
msg.setText(tr("Booting failed: %1 %2").arg(message).arg(link));
msg.exec();
QMessageBox* msg = new QMessageBox();
msg->setWindowTitle(tr("Boot Failed"));
msg->setIcon(QMessageBox::Critical);
msg->setTextFormat(Qt::RichText);
msg->setStandardButtons(QMessageBox::Ok);
msg->setText(tr("Booting failed: %1 %2").arg(message).arg(link));
msg->setAttribute(Qt::WA_DeleteOnClose);
msg->open();
}
void main_window::Boot(const std::string& path, const std::string& title_id, bool direct, bool refresh_list, cfg_mode config_mode, const std::string& config_path)
@ -2744,13 +2744,13 @@ void main_window::CreateConnects()
const auto open_settings = [this](int tabIndex)
{
settings_dialog dlg(m_gui_settings, m_emu_settings, tabIndex, this);
connect(&dlg, &settings_dialog::GuiStylesheetRequest, this, &main_window::RequestGlobalStylesheetChange);
connect(&dlg, &settings_dialog::GuiRepaintRequest, this, &main_window::RepaintGui);
connect(&dlg, &settings_dialog::EmuSettingsApplied, this, &main_window::NotifyEmuSettingsChange);
connect(&dlg, &settings_dialog::EmuSettingsApplied, this, &main_window::update_gui_pad_thread);
connect(&dlg, &settings_dialog::EmuSettingsApplied, m_log_frame, &log_frame::LoadSettings);
dlg.exec();
settings_dialog* dlg = new settings_dialog(m_gui_settings, m_emu_settings, tabIndex, this);
connect(dlg, &settings_dialog::GuiStylesheetRequest, this, &main_window::RequestGlobalStylesheetChange);
connect(dlg, &settings_dialog::GuiRepaintRequest, this, &main_window::RepaintGui);
connect(dlg, &settings_dialog::EmuSettingsApplied, this, &main_window::NotifyEmuSettingsChange);
connect(dlg, &settings_dialog::EmuSettingsApplied, this, &main_window::update_gui_pad_thread);
connect(dlg, &settings_dialog::EmuSettingsApplied, m_log_frame, &log_frame::LoadSettings);
dlg->open();
};
connect(ui->confCPUAct, &QAction::triggered, this, [open_settings]() { open_settings(0); });
@ -3202,8 +3202,8 @@ void main_window::CreateConnects()
connect(ui->aboutAct, &QAction::triggered, this, [this]
{
about_dialog dlg(this);
dlg.exec();
about_dialog* dlg = new about_dialog(this);
dlg->open();
});
connect(ui->aboutQtAct, &QAction::triggered, qApp, &QApplication::aboutQt);

View file

@ -88,7 +88,7 @@ public:
~main_window();
bool Init(bool with_cli_boot);
QIcon GetAppIcon() const;
bool OnMissingFw();
void OnMissingFw();
bool InstallPackages(QStringList file_paths = {}, bool from_boot = false);
void InstallPup(QString file_path = "");
@ -123,7 +123,7 @@ private Q_SLOTS:
void BootSavestate();
void BootRsxCapture(std::string path = "");
void DecryptSPRXLibraries();
static void show_boot_error(game_boot_result status);
void show_boot_error(game_boot_result status);
void SaveWindowState() const;
void SetIconSizeActions(int idx) const;