mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-01-28 14:54:11 +00:00
Fix Emulation boot recursion
This commit is contained in:
parent
378a69ea85
commit
07df91d4e8
@ -142,6 +142,7 @@ void fmt_class_string<game_boot_result>::format(std::string& out, u64 arg)
|
||||
case game_boot_result::savestate_version_unsupported: return "Savestate versioning data differs from your RPCS3 build.\nTry to use an older or newer RPCS3 build.\nEspecially if you know the build that created the savestate.";
|
||||
case game_boot_result::still_running: return "Game is still running";
|
||||
case game_boot_result::already_added: return "Game was already added";
|
||||
case game_boot_result::currently_restricted: return "Booting is restricted at the time being";
|
||||
}
|
||||
return unknown;
|
||||
});
|
||||
@ -802,7 +803,7 @@ std::string Emulator::GetBackgroundPicturePath() const
|
||||
|
||||
bool Emulator::BootRsxCapture(const std::string& path)
|
||||
{
|
||||
if (m_state != system_state::stopped)
|
||||
if (m_state != system_state::stopped || m_restrict_emu_state_change)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -928,6 +929,11 @@ game_boot_result Emulator::GetElfPathFromDir(std::string& elf_path, const std::s
|
||||
|
||||
game_boot_result Emulator::BootGame(const std::string& path, const std::string& title_id, bool direct, cfg_mode config_mode, const std::string& config_path)
|
||||
{
|
||||
if (m_restrict_emu_state_change)
|
||||
{
|
||||
return game_boot_result::currently_restricted;
|
||||
}
|
||||
|
||||
auto save_args = std::make_tuple(m_path, m_path_original, argv, envp, data, disc, klic, hdd1, m_config_mode, m_config_path);
|
||||
|
||||
auto restore_on_no_boot = [&](game_boot_result result)
|
||||
@ -978,11 +984,18 @@ void Emulator::SetForceBoot(bool force_boot)
|
||||
|
||||
game_boot_result Emulator::Load(const std::string& title_id, bool is_disc_patch, usz recursion_count)
|
||||
{
|
||||
if (m_restrict_emu_state_change)
|
||||
{
|
||||
return game_boot_result::currently_restricted;
|
||||
}
|
||||
|
||||
if (m_state != system_state::stopped)
|
||||
{
|
||||
return game_boot_result::still_running;
|
||||
}
|
||||
|
||||
const auto guard = MakeEmulationStateGuard();
|
||||
|
||||
// Enable logging
|
||||
rpcs3::utils::configure_logs(true);
|
||||
|
||||
|
@ -57,6 +57,7 @@ enum class game_boot_result : u32
|
||||
savestate_version_unsupported,
|
||||
still_running,
|
||||
already_added,
|
||||
currently_restricted,
|
||||
};
|
||||
|
||||
constexpr bool is_error(game_boot_result res)
|
||||
@ -123,6 +124,7 @@ class Emulator final
|
||||
atomic_t<u64> m_pause_amend_time{0}; // increased when resumed
|
||||
atomic_t<u64> m_stop_ctr{1}; // Increments when emulation is stopped
|
||||
atomic_t<bool> m_emu_state_close_pending = false;
|
||||
atomic_t<u64> m_restrict_emu_state_change{0};
|
||||
|
||||
games_config m_games_config;
|
||||
|
||||
@ -206,8 +208,13 @@ public:
|
||||
enum class stop_counter_t : u64{};
|
||||
|
||||
// Returns a different value each time we start a new emulation.
|
||||
stop_counter_t GetEmulationIdentifier() const
|
||||
stop_counter_t GetEmulationIdentifier(bool subtract_one = false) const
|
||||
{
|
||||
if (subtract_one)
|
||||
{
|
||||
return stop_counter_t{m_stop_ctr - 1};
|
||||
}
|
||||
|
||||
return stop_counter_t{+m_stop_ctr};
|
||||
}
|
||||
|
||||
@ -338,6 +345,41 @@ public:
|
||||
return m_config_mode == cfg_mode::continuous;
|
||||
}
|
||||
|
||||
class emulation_state_guard_t
|
||||
{
|
||||
class Emulator* _this = nullptr;
|
||||
bool active = true;
|
||||
|
||||
public:
|
||||
explicit emulation_state_guard_t(Emulator* this0) noexcept
|
||||
: _this(this0)
|
||||
{
|
||||
_this->m_restrict_emu_state_change++;
|
||||
}
|
||||
|
||||
~emulation_state_guard_t() noexcept
|
||||
{
|
||||
if (active)
|
||||
{
|
||||
_this->m_restrict_emu_state_change--;
|
||||
}
|
||||
}
|
||||
|
||||
emulation_state_guard_t(emulation_state_guard_t&& rhs) noexcept
|
||||
{
|
||||
_this = rhs._this;
|
||||
active = std::exchange(rhs.active, false);
|
||||
}
|
||||
|
||||
emulation_state_guard_t& operator=(const emulation_state_guard_t&) = delete;
|
||||
emulation_state_guard_t(const emulation_state_guard_t&) = delete;
|
||||
};
|
||||
|
||||
emulation_state_guard_t MakeEmulationStateGuard()
|
||||
{
|
||||
return emulation_state_guard_t{this};
|
||||
}
|
||||
|
||||
game_boot_result BootGame(const std::string& path, const std::string& title_id = "", bool direct = false, cfg_mode config_mode = cfg_mode::custom, const std::string& config_path = "");
|
||||
bool BootRsxCapture(const std::string& path);
|
||||
|
||||
@ -349,6 +391,11 @@ public:
|
||||
void FixGuestTime();
|
||||
void FinalizeRunRequest();
|
||||
|
||||
bool IsBootingRestricted() const
|
||||
{
|
||||
return m_restrict_emu_state_change != 0;
|
||||
}
|
||||
|
||||
private:
|
||||
struct savestate_stage
|
||||
{
|
||||
|
@ -195,13 +195,17 @@ void gui_settings::ShowInfoBox(const QString& title, const QString& text, const
|
||||
|
||||
bool gui_settings::GetBootConfirmation(QWidget* parent, const gui_save& gui_save_entry)
|
||||
{
|
||||
auto info = Emu.GetEmulationIdentifier();
|
||||
// Ensure no game has booted inbetween
|
||||
const auto guard = Emu.MakeEmulationStateGuard();
|
||||
|
||||
const auto info = Emu.GetEmulationIdentifier();
|
||||
const auto old_status = Emu.GetStatus(false);
|
||||
|
||||
qt_events_aware_op(16, [&]()
|
||||
{
|
||||
if (Emu.GetStatus(false) != system_state::stopping)
|
||||
{
|
||||
ensure(info == Emu.GetEmulationIdentifier());
|
||||
ensure(info == Emu.GetEmulationIdentifier(old_status == system_state::stopping ? true : false));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -562,6 +562,7 @@ void main_window::show_boot_error(game_boot_result status)
|
||||
break;
|
||||
case game_boot_result::firmware_missing: // Handled elsewhere
|
||||
case game_boot_result::already_added: // Handled elsewhere
|
||||
case game_boot_result::currently_restricted:
|
||||
case game_boot_result::no_errors:
|
||||
return;
|
||||
case game_boot_result::generic_error:
|
||||
@ -576,12 +577,18 @@ void main_window::show_boot_error(game_boot_result status)
|
||||
msg->setTextFormat(Qt::RichText);
|
||||
msg->setStandardButtons(QMessageBox::Ok);
|
||||
msg->setText(tr("Booting failed: %1 %2").arg(message).arg(link));
|
||||
msg->setParent(this);
|
||||
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)
|
||||
{
|
||||
if (Emu.IsBootingRestricted())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_gui_settings->GetBootConfirmation(this, gui::ib_confirm_boot))
|
||||
{
|
||||
return;
|
||||
@ -3776,6 +3783,11 @@ void main_window::RemoveFirmwareCache()
|
||||
|
||||
void main_window::CreateFirmwareCache()
|
||||
{
|
||||
if (Emu.IsBootingRestricted())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_gui_settings->GetBootConfirmation(this))
|
||||
{
|
||||
return;
|
||||
@ -4092,6 +4104,11 @@ void main_window::dropEvent(QDropEvent* event)
|
||||
}
|
||||
case drop_type::drop_game: // import valid games to gamelist (games.yaml)
|
||||
{
|
||||
if (Emu.IsBootingRestricted())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_gui_settings->GetBootConfirmation(this))
|
||||
{
|
||||
return;
|
||||
|
Loading…
x
Reference in New Issue
Block a user