mirror of
https://github.com/stenzek/duckstation.git
synced 2025-06-13 06:47:30 +00:00
Qt: Backport undo load state timestamps
This commit is contained in:
parent
29e55a2e5b
commit
cb2dfabeeb
@ -137,6 +137,11 @@ struct SaveStateBuffer
|
||||
size_t state_size;
|
||||
};
|
||||
|
||||
struct UndoSaveStateBuffer : public SaveStateBuffer
|
||||
{
|
||||
time_t timestamp;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
static void CheckCacheLineSize();
|
||||
@ -318,7 +323,7 @@ struct ALIGN_TO_CACHE_LINE StateVars
|
||||
Threading::ThreadHandle cpu_thread_handle;
|
||||
|
||||
// temporary save state, created when loading, used to undo load state
|
||||
std::optional<System::SaveStateBuffer> undo_load_state;
|
||||
std::optional<UndoSaveStateBuffer> undo_load_state;
|
||||
|
||||
// Used to track play time. We use a monotonic timer here, in case of clock changes.
|
||||
u64 session_start_time = 0;
|
||||
@ -2024,7 +2029,7 @@ void System::ClearRunningGame()
|
||||
s_state.running_game_entry = nullptr;
|
||||
s_state.running_game_hash = 0;
|
||||
|
||||
Host::OnGameChanged(s_state.running_game_path, s_state.running_game_serial, s_state.running_game_title,
|
||||
Host::OnSystemGameChanged(s_state.running_game_path, s_state.running_game_serial, s_state.running_game_title,
|
||||
s_state.running_game_hash);
|
||||
|
||||
UpdateRichPresence(true);
|
||||
@ -4212,7 +4217,7 @@ void System::UpdateRunningGame(const std::string& path, CDImage* image, bool boo
|
||||
FullscreenUI::OnRunningGameChanged(s_state.running_game_path, s_state.running_game_serial, s_state.running_game_title,
|
||||
s_state.running_game_hash);
|
||||
|
||||
Host::OnGameChanged(s_state.running_game_path, s_state.running_game_serial, s_state.running_game_title,
|
||||
Host::OnSystemGameChanged(s_state.running_game_path, s_state.running_game_serial, s_state.running_game_title,
|
||||
s_state.running_game_hash);
|
||||
}
|
||||
|
||||
@ -5282,12 +5287,14 @@ bool System::UndoLoadState()
|
||||
Host::ReportErrorAsync("Error",
|
||||
fmt::format("Failed to load undo state, resetting system:\n", error.GetDescription()));
|
||||
s_state.undo_load_state.reset();
|
||||
Host::OnSystemUndoStateAvailabilityChanged(false, 0);
|
||||
ResetSystem();
|
||||
return false;
|
||||
}
|
||||
|
||||
INFO_LOG("Loaded undo save state.");
|
||||
s_state.undo_load_state.reset();
|
||||
Host::OnSystemUndoStateAvailabilityChanged(false, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -5303,10 +5310,13 @@ bool System::SaveUndoLoadState()
|
||||
fmt::format(TRANSLATE_FS("OSDMessage", "Failed to save undo load state:\n{}"), error.GetDescription()),
|
||||
Host::OSD_CRITICAL_ERROR_DURATION);
|
||||
s_state.undo_load_state.reset();
|
||||
Host::OnSystemUndoStateAvailabilityChanged(false, 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
INFO_LOG("Saved undo load state: {} bytes", s_state.undo_load_state->state_size);
|
||||
s_state.undo_load_state->timestamp = std::time(nullptr);
|
||||
Host::OnSystemUndoStateAvailabilityChanged(true, static_cast<u64>(s_state.undo_load_state->timestamp));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -115,8 +115,11 @@ void OnSystemAbnormalShutdown(const std::string_view reason);
|
||||
void OnPerformanceCountersUpdated(const GPUBackend* gpu_backend);
|
||||
|
||||
/// Provided by the host; called when the running executable changes.
|
||||
void OnGameChanged(const std::string& disc_path, const std::string& game_serial, const std::string& game_name,
|
||||
GameHash game_hash);
|
||||
void OnSystemGameChanged(const std::string& disc_path, const std::string& game_serial, const std::string& game_name,
|
||||
GameHash game_hash);
|
||||
|
||||
/// Provided by the host; called when the undo save state availability changes.
|
||||
void OnSystemUndoStateAvailabilityChanged(bool available, u64 timestamp);
|
||||
|
||||
/// Called when media capture starts/stops.
|
||||
void OnMediaCaptureStarted();
|
||||
|
@ -1185,8 +1185,8 @@ void MiniHost::WarnAboutInterface()
|
||||
Host::AddIconOSDWarning("MiniWarning", ICON_EMOJI_WARNING, message, Host::OSD_INFO_DURATION);
|
||||
}
|
||||
|
||||
void Host::OnGameChanged(const std::string& disc_path, const std::string& game_serial, const std::string& game_name,
|
||||
GameHash game_hash)
|
||||
void Host::OnSystemGameChanged(const std::string& disc_path, const std::string& game_serial,
|
||||
const std::string& game_name, GameHash game_hash)
|
||||
{
|
||||
using namespace MiniHost;
|
||||
|
||||
@ -1195,6 +1195,11 @@ void Host::OnGameChanged(const std::string& disc_path, const std::string& game_s
|
||||
SDL_SetWindowTitle(s_state.sdl_window, GetWindowTitle(game_name).c_str());
|
||||
}
|
||||
|
||||
void Host::OnSystemUndoStateAvailabilityChanged(bool available, u64 timestamp)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
void Host::RunOnCPUThread(std::function<void()> function, bool block /* = false */)
|
||||
{
|
||||
using namespace MiniHost;
|
||||
|
@ -113,6 +113,7 @@ static QString s_current_game_title;
|
||||
static QString s_current_game_serial;
|
||||
static QString s_current_game_path;
|
||||
static QIcon s_current_game_icon;
|
||||
static std::optional<std::time_t> s_undo_state_timestamp;
|
||||
|
||||
bool QtHost::IsSystemPaused()
|
||||
{
|
||||
@ -576,6 +577,7 @@ void MainWindow::onSystemDestroyed()
|
||||
s_system_starting = false;
|
||||
s_system_valid = false;
|
||||
s_system_paused = false;
|
||||
s_undo_state_timestamp.reset();
|
||||
|
||||
// If we're closing or in batch mode, quit the whole application now.
|
||||
if (m_is_closing || QtHost::InBatchMode())
|
||||
@ -593,7 +595,7 @@ void MainWindow::onSystemDestroyed()
|
||||
switchToGameListView();
|
||||
}
|
||||
|
||||
void MainWindow::onRunningGameChanged(const QString& filename, const QString& game_serial, const QString& game_title)
|
||||
void MainWindow::onSystemGameChanged(const QString& filename, const QString& game_serial, const QString& game_title)
|
||||
{
|
||||
s_current_game_path = filename;
|
||||
s_current_game_title = game_title;
|
||||
@ -603,6 +605,14 @@ void MainWindow::onRunningGameChanged(const QString& filename, const QString& ga
|
||||
updateWindowTitle();
|
||||
}
|
||||
|
||||
void MainWindow::onSystemUndoStateAvailabilityChanged(bool available, quint64 timestamp)
|
||||
{
|
||||
if (!available)
|
||||
s_undo_state_timestamp.reset();
|
||||
else
|
||||
s_undo_state_timestamp = timestamp;
|
||||
}
|
||||
|
||||
void MainWindow::onMediaCaptureStarted()
|
||||
{
|
||||
QSignalBlocker sb(m_ui.actionMediaCapture);
|
||||
@ -891,7 +901,7 @@ void MainWindow::populateGameListContextMenu(const GameList::Entry* entry, QWidg
|
||||
}
|
||||
}
|
||||
|
||||
static QString FormatTimestampForSaveStateMenu(u64 timestamp)
|
||||
QString MainWindow::formatTimestampForSaveStateMenu(u64 timestamp)
|
||||
{
|
||||
const QDateTime qtime(QDateTime::fromSecsSinceEpoch(static_cast<qint64>(timestamp)));
|
||||
return qtime.toString(QLocale::system().dateTimeFormat(QLocale::ShortFormat));
|
||||
@ -904,7 +914,7 @@ void MainWindow::populateLoadStateMenu(std::string_view game_serial, QMenu* menu
|
||||
std::optional<SaveStateInfo> ssi = System::GetSaveStateInfo(serial, slot);
|
||||
|
||||
const QString menu_title =
|
||||
ssi.has_value() ? title.arg(slot).arg(FormatTimestampForSaveStateMenu(ssi->timestamp)) : empty_title.arg(slot);
|
||||
ssi.has_value() ? title.arg(slot).arg(formatTimestampForSaveStateMenu(ssi->timestamp)) : empty_title.arg(slot);
|
||||
|
||||
QAction* load_action = menu->addAction(menu_title);
|
||||
load_action->setEnabled(ssi.has_value());
|
||||
@ -925,8 +935,11 @@ void MainWindow::populateLoadStateMenu(std::string_view game_serial, QMenu* menu
|
||||
|
||||
g_emu_thread->loadState(path);
|
||||
});
|
||||
QAction* load_from_state = menu->addAction(tr("Undo Load State"));
|
||||
load_from_state->setEnabled(System::CanUndoLoadState());
|
||||
QAction* load_from_state =
|
||||
menu->addAction(s_undo_state_timestamp.has_value() ?
|
||||
tr("Undo Load State (%1)").arg(formatTimestampForSaveStateMenu(s_undo_state_timestamp.value())) :
|
||||
tr("Undo Load State"));
|
||||
load_from_state->setEnabled(s_undo_state_timestamp.has_value());
|
||||
connect(load_from_state, &QAction::triggered, g_emu_thread, &EmuThread::undoLoadState);
|
||||
menu->addSeparator();
|
||||
|
||||
@ -949,7 +962,7 @@ void MainWindow::populateSaveStateMenu(std::string_view game_serial, QMenu* menu
|
||||
std::optional<SaveStateInfo> ssi = System::GetSaveStateInfo(serial, slot);
|
||||
|
||||
const QString menu_title =
|
||||
ssi.has_value() ? title.arg(slot).arg(FormatTimestampForSaveStateMenu(ssi->timestamp)) : empty_title.arg(slot);
|
||||
ssi.has_value() ? title.arg(slot).arg(formatTimestampForSaveStateMenu(ssi->timestamp)) : empty_title.arg(slot);
|
||||
|
||||
QAction* save_action = menu->addAction(menu_title);
|
||||
connect(save_action, &QAction::triggered,
|
||||
@ -2123,7 +2136,9 @@ void MainWindow::connectSignals()
|
||||
connect(g_emu_thread, &EmuThread::systemDestroyed, this, &MainWindow::onSystemDestroyed);
|
||||
connect(g_emu_thread, &EmuThread::systemPaused, this, &MainWindow::onSystemPaused);
|
||||
connect(g_emu_thread, &EmuThread::systemResumed, this, &MainWindow::onSystemResumed);
|
||||
connect(g_emu_thread, &EmuThread::runningGameChanged, this, &MainWindow::onRunningGameChanged);
|
||||
connect(g_emu_thread, &EmuThread::systemGameChanged, this, &MainWindow::onSystemGameChanged);
|
||||
connect(g_emu_thread, &EmuThread::systemUndoStateAvailabilityChanged, this,
|
||||
&MainWindow::onSystemUndoStateAvailabilityChanged);
|
||||
connect(g_emu_thread, &EmuThread::mediaCaptureStarted, this, &MainWindow::onMediaCaptureStarted);
|
||||
connect(g_emu_thread, &EmuThread::mediaCaptureStopped, this, &MainWindow::onMediaCaptureStopped);
|
||||
connect(g_emu_thread, &EmuThread::mouseModeRequested, this, &MainWindow::onMouseModeRequested);
|
||||
|
@ -146,7 +146,8 @@ private Q_SLOTS:
|
||||
void onSystemDestroyed();
|
||||
void onSystemPaused();
|
||||
void onSystemResumed();
|
||||
void onRunningGameChanged(const QString& filename, const QString& game_serial, const QString& game_title);
|
||||
void onSystemGameChanged(const QString& filename, const QString& game_serial, const QString& game_title);
|
||||
void onSystemUndoStateAvailabilityChanged(bool available, quint64 timestamp);
|
||||
void onMediaCaptureStarted();
|
||||
void onMediaCaptureStopped();
|
||||
void onAchievementsLoginRequested(Achievements::LoginRequestReason reason);
|
||||
@ -215,7 +216,6 @@ private Q_SLOTS:
|
||||
void onDebugLogChannelsMenuAboutToShow();
|
||||
void openCPUDebugger();
|
||||
|
||||
|
||||
protected:
|
||||
void showEvent(QShowEvent* event) override;
|
||||
void closeEvent(QCloseEvent* event) override;
|
||||
@ -296,6 +296,8 @@ private:
|
||||
void startFileOrChangeDisc(const QString& path);
|
||||
void promptForDiscChange(const QString& path);
|
||||
|
||||
static QString formatTimestampForSaveStateMenu(u64 timestamp);
|
||||
|
||||
Ui::MainWindow m_ui;
|
||||
|
||||
GameListWidget* m_game_list_widget = nullptr;
|
||||
|
@ -2517,11 +2517,16 @@ void Host::OnPerformanceCountersUpdated(const GPUBackend* gpu_backend)
|
||||
g_emu_thread->updatePerformanceCounters(gpu_backend);
|
||||
}
|
||||
|
||||
void Host::OnGameChanged(const std::string& disc_path, const std::string& game_serial, const std::string& game_name,
|
||||
GameHash hash)
|
||||
void Host::OnSystemGameChanged(const std::string& disc_path, const std::string& game_serial,
|
||||
const std::string& game_name, GameHash hash)
|
||||
{
|
||||
emit g_emu_thread->runningGameChanged(QString::fromStdString(disc_path), QString::fromStdString(game_serial),
|
||||
QString::fromStdString(game_name));
|
||||
emit g_emu_thread->systemGameChanged(QString::fromStdString(disc_path), QString::fromStdString(game_serial),
|
||||
QString::fromStdString(game_name));
|
||||
}
|
||||
|
||||
void Host::OnSystemUndoStateAvailabilityChanged(bool available, u64 timestamp)
|
||||
{
|
||||
emit g_emu_thread->systemUndoStateAvailabilityChanged(available, timestamp);
|
||||
}
|
||||
|
||||
void Host::OnMediaCaptureStarted()
|
||||
|
@ -140,6 +140,8 @@ Q_SIGNALS:
|
||||
void systemDestroyed();
|
||||
void systemPaused();
|
||||
void systemResumed();
|
||||
void systemGameChanged(const QString& filename, const QString& game_serial, const QString& game_title);
|
||||
void systemUndoStateAvailabilityChanged(bool available, quint64 timestamp);
|
||||
void gameListRefreshed();
|
||||
void gameListRowsChanged(const QList<int>& rows_changed);
|
||||
std::optional<WindowInfo> onAcquireRenderWindowRequested(RenderAPI render_api, bool fullscreen,
|
||||
@ -148,7 +150,6 @@ Q_SIGNALS:
|
||||
void onResizeRenderWindowRequested(qint32 width, qint32 height);
|
||||
void onReleaseRenderWindowRequested();
|
||||
void focusDisplayWidgetRequested();
|
||||
void runningGameChanged(const QString& filename, const QString& game_serial, const QString& game_title);
|
||||
void inputProfileLoaded();
|
||||
void mouseModeRequested(bool relative, bool hide_cursor);
|
||||
void fullscreenUIStartedOrStopped(bool running);
|
||||
|
@ -316,14 +316,19 @@ void Host::OnPerformanceCountersUpdated(const GPUBackend* gpu_backend)
|
||||
//
|
||||
}
|
||||
|
||||
void Host::OnGameChanged(const std::string& disc_path, const std::string& game_serial, const std::string& game_name,
|
||||
GameHash hash)
|
||||
void Host::OnSystemGameChanged(const std::string& disc_path, const std::string& game_serial,
|
||||
const std::string& game_name, GameHash hash)
|
||||
{
|
||||
INFO_LOG("Disc Path: {}", disc_path);
|
||||
INFO_LOG("Game Serial: {}", game_serial);
|
||||
INFO_LOG("Game Name: {}", game_name);
|
||||
}
|
||||
|
||||
void Host::OnSystemUndoStateAvailabilityChanged(bool available, u64 timestamp)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
void Host::OnMediaCaptureStarted()
|
||||
{
|
||||
//
|
||||
@ -890,7 +895,7 @@ bool RegTestHost::ParseCommandLineParameters(int argc, char* argv[], std::option
|
||||
|
||||
INFO_LOG("Setting CPU execution mode to {}.", Settings::GetCPUExecutionModeName(cpu.value()));
|
||||
s_base_settings_interface.SetStringValue("CPU", "ExecutionMode",
|
||||
Settings::GetCPUExecutionModeName(cpu.value()));
|
||||
Settings::GetCPUExecutionModeName(cpu.value()));
|
||||
continue;
|
||||
}
|
||||
else if (CHECK_ARG("-pgxp"))
|
||||
|
Loading…
x
Reference in New Issue
Block a user