2024-01-07 05:26:56 +00:00
|
|
|
// SPDX-FileCopyrightText: 2002-2024 PCSX2 Dev Team
|
2023-12-22 11:57:49 +00:00
|
|
|
// SPDX-License-Identifier: LGPL-3.0+
|
2021-12-13 12:12:54 +00:00
|
|
|
|
|
|
|
#pragma once
|
2022-09-07 09:20:50 +00:00
|
|
|
|
|
|
|
#include <atomic>
|
|
|
|
#include <memory>
|
|
|
|
#include <functional>
|
|
|
|
#include <optional>
|
2024-01-07 05:26:56 +00:00
|
|
|
#include <string>
|
|
|
|
#include <string_view>
|
2022-09-07 09:20:50 +00:00
|
|
|
|
2021-12-13 12:12:54 +00:00
|
|
|
#include "pcsx2/Host.h"
|
2023-05-13 04:30:41 +00:00
|
|
|
#include "pcsx2/Input/InputManager.h"
|
2021-12-13 12:12:54 +00:00
|
|
|
#include "pcsx2/VMManager.h"
|
2022-09-07 09:20:50 +00:00
|
|
|
|
|
|
|
#include <QtCore/QList>
|
|
|
|
#include <QtCore/QEventLoop>
|
2021-12-13 12:12:54 +00:00
|
|
|
#include <QtCore/QMetaType>
|
2022-09-07 09:20:50 +00:00
|
|
|
#include <QtCore/QPair>
|
2022-05-11 08:24:56 +00:00
|
|
|
#include <QtCore/QString>
|
2022-09-07 09:20:50 +00:00
|
|
|
#include <QtCore/QSemaphore>
|
|
|
|
#include <QtCore/QString>
|
|
|
|
#include <QtCore/QTimer>
|
|
|
|
#include <QtCore/QThread>
|
2021-12-13 12:12:54 +00:00
|
|
|
|
2024-01-07 05:26:56 +00:00
|
|
|
#include <QtGui/QIcon>
|
|
|
|
|
2021-12-13 12:12:54 +00:00
|
|
|
class SettingsInterface;
|
|
|
|
|
2022-09-07 09:20:50 +00:00
|
|
|
class DisplayWidget;
|
|
|
|
struct VMBootParameters;
|
2021-12-13 12:12:54 +00:00
|
|
|
|
2022-06-28 13:34:45 +00:00
|
|
|
enum class CDVD_SourceType : uint8_t;
|
|
|
|
|
2023-07-27 09:24:55 +00:00
|
|
|
namespace Achievements
|
|
|
|
{
|
|
|
|
enum class LoginRequestReason;
|
|
|
|
}
|
|
|
|
|
2021-12-13 12:12:54 +00:00
|
|
|
Q_DECLARE_METATYPE(std::shared_ptr<VMBootParameters>);
|
2022-04-06 10:42:23 +00:00
|
|
|
Q_DECLARE_METATYPE(std::optional<bool>);
|
|
|
|
Q_DECLARE_METATYPE(GSRendererType);
|
2021-12-13 12:12:54 +00:00
|
|
|
Q_DECLARE_METATYPE(InputBindingKey);
|
2022-06-28 13:34:45 +00:00
|
|
|
Q_DECLARE_METATYPE(CDVD_SourceType);
|
2023-07-27 09:24:55 +00:00
|
|
|
Q_DECLARE_METATYPE(Achievements::LoginRequestReason);
|
2021-12-13 12:12:54 +00:00
|
|
|
|
2022-09-07 09:20:50 +00:00
|
|
|
class EmuThread : public QThread
|
|
|
|
{
|
|
|
|
Q_OBJECT
|
|
|
|
|
|
|
|
public:
|
|
|
|
explicit EmuThread(QThread* ui_thread);
|
|
|
|
~EmuThread();
|
|
|
|
|
|
|
|
static void start();
|
|
|
|
static void stop();
|
|
|
|
|
|
|
|
__fi QEventLoop* getEventLoop() const { return m_event_loop; }
|
|
|
|
__fi bool isFullscreen() const { return m_is_fullscreen; }
|
2023-04-25 12:52:41 +00:00
|
|
|
__fi bool isExclusiveFullscreen() const { return m_is_exclusive_fullscreen; }
|
2022-09-07 09:20:50 +00:00
|
|
|
__fi bool isRenderingToMain() const { return m_is_rendering_to_main; }
|
|
|
|
__fi bool isSurfaceless() const { return m_is_surfaceless; }
|
2024-03-31 10:39:16 +00:00
|
|
|
__fi bool isRunningFullscreenUI() const { return m_run_fullscreen_ui.load(std::memory_order_acquire); }
|
2022-09-07 09:20:50 +00:00
|
|
|
|
2024-01-11 09:38:28 +00:00
|
|
|
__fi bool isOnEmuThread() const { return (QThread::currentThread() == this); }
|
|
|
|
__fi bool isOnUIThread() const { return (QThread::currentThread() == m_ui_thread); }
|
2022-10-01 15:14:39 +00:00
|
|
|
bool shouldRenderToMain() const;
|
2022-09-07 09:20:50 +00:00
|
|
|
|
|
|
|
/// Called back from the GS thread when the display state changes (e.g. fullscreen, render to main).
|
2023-04-25 12:52:41 +00:00
|
|
|
std::optional<WindowInfo> acquireRenderWindow(bool recreate_window);
|
2022-09-07 09:20:50 +00:00
|
|
|
void connectDisplaySignals(DisplayWidget* widget);
|
2023-04-01 05:54:04 +00:00
|
|
|
void releaseRenderWindow();
|
2022-09-07 09:20:50 +00:00
|
|
|
|
|
|
|
void startBackgroundControllerPollTimer();
|
|
|
|
void stopBackgroundControllerPollTimer();
|
|
|
|
void updatePerformanceMetrics(bool force);
|
|
|
|
|
|
|
|
public Q_SLOTS:
|
|
|
|
bool confirmMessage(const QString& title, const QString& message);
|
2022-09-14 12:41:50 +00:00
|
|
|
void loadSettings(SettingsInterface& si, std::unique_lock<std::mutex>& lock);
|
|
|
|
void checkForSettingChanges(const Pcsx2Config& old_config);
|
2022-09-07 09:20:50 +00:00
|
|
|
void startFullscreenUI(bool fullscreen);
|
|
|
|
void stopFullscreenUI();
|
|
|
|
void startVM(std::shared_ptr<VMBootParameters> boot_params);
|
|
|
|
void resetVM();
|
|
|
|
void setVMPaused(bool paused);
|
|
|
|
void shutdownVM(bool save_state = true);
|
|
|
|
void loadState(const QString& filename);
|
|
|
|
void loadStateFromSlot(qint32 slot);
|
|
|
|
void saveState(const QString& filename);
|
|
|
|
void saveStateToSlot(qint32 slot);
|
|
|
|
void toggleFullscreen();
|
2023-04-25 12:52:41 +00:00
|
|
|
void setFullscreen(bool fullscreen, bool allow_render_to_main);
|
2022-09-07 09:20:50 +00:00
|
|
|
void setSurfaceless(bool surfaceless);
|
|
|
|
void applySettings();
|
|
|
|
void reloadGameSettings();
|
|
|
|
void updateEmuFolders();
|
|
|
|
void toggleSoftwareRendering();
|
|
|
|
void changeDisc(CDVD_SourceType source, const QString& path);
|
2023-09-09 05:37:31 +00:00
|
|
|
void setELFOverride(const QString& path);
|
|
|
|
void changeGSDump(const QString& path);
|
2022-09-07 09:20:50 +00:00
|
|
|
void reloadPatches();
|
|
|
|
void reloadInputSources();
|
|
|
|
void reloadInputBindings();
|
2022-10-15 11:20:05 +00:00
|
|
|
void reloadInputDevices();
|
|
|
|
void closeInputSources();
|
2022-09-07 09:20:50 +00:00
|
|
|
void requestDisplaySize(float scale);
|
|
|
|
void enumerateInputDevices();
|
|
|
|
void enumerateVibrationMotors();
|
|
|
|
void runOnCPUThread(const std::function<void()>& func);
|
|
|
|
void queueSnapshot(quint32 gsdump_frames);
|
2022-12-18 13:05:00 +00:00
|
|
|
void beginCapture(const QString& path);
|
|
|
|
void endCapture();
|
2024-04-23 15:17:52 +00:00
|
|
|
void setAudioOutputVolume(int volume, int fast_forward_volume);
|
|
|
|
void setAudioOutputMuted(bool muted);
|
2022-09-07 09:20:50 +00:00
|
|
|
|
|
|
|
Q_SIGNALS:
|
|
|
|
bool messageConfirmed(const QString& title, const QString& message);
|
2024-05-14 21:42:19 +00:00
|
|
|
void statusMessage(const QString& message);
|
2022-09-07 09:20:50 +00:00
|
|
|
|
2023-04-25 12:52:41 +00:00
|
|
|
std::optional<WindowInfo> onAcquireRenderWindowRequested(bool recreate_window, bool fullscreen, bool render_to_main, bool surfaceless);
|
|
|
|
void onResizeRenderWindowRequested(qint32 width, qint32 height);
|
|
|
|
void onReleaseRenderWindowRequested();
|
2023-07-23 05:07:46 +00:00
|
|
|
void onMouseModeRequested(bool relative_mode, bool hide_cursor);
|
2023-09-04 11:34:57 +00:00
|
|
|
void onFullscreenUIStateChange(bool running);
|
2022-09-07 09:20:50 +00:00
|
|
|
|
|
|
|
/// Called when the VM is starting initialization, but has not been completed yet.
|
|
|
|
void onVMStarting();
|
|
|
|
|
|
|
|
/// Called when the VM is created.
|
|
|
|
void onVMStarted();
|
|
|
|
|
|
|
|
/// Called when the VM is paused.
|
|
|
|
void onVMPaused();
|
|
|
|
|
|
|
|
/// Called when the VM is resumed after being paused.
|
|
|
|
void onVMResumed();
|
|
|
|
|
|
|
|
/// Called when the VM is shut down or destroyed.
|
|
|
|
void onVMStopped();
|
|
|
|
|
|
|
|
/// Provided by the host; called when the running executable changes.
|
2023-06-13 12:43:11 +00:00
|
|
|
void onGameChanged(const QString& title, const QString& elf_override, const QString& disc_path,
|
|
|
|
const QString& serial, quint32 disc_crc, quint32 crc);
|
2022-09-07 09:20:50 +00:00
|
|
|
|
|
|
|
void onInputDevicesEnumerated(const QList<QPair<QString, QString>>& devices);
|
|
|
|
void onInputDeviceConnected(const QString& identifier, const QString& device_name);
|
|
|
|
void onInputDeviceDisconnected(const QString& identifier);
|
|
|
|
void onVibrationMotorsEnumerated(const QList<InputBindingKey>& motors);
|
|
|
|
|
|
|
|
/// Called when a save state is loading, before the file is processed.
|
|
|
|
void onSaveStateLoading(const QString& path);
|
|
|
|
|
|
|
|
/// Called after a save state is successfully loaded. If the save state was invalid, was_successful will be false.
|
|
|
|
void onSaveStateLoaded(const QString& path, bool was_successful);
|
|
|
|
|
|
|
|
/// Called when a save state is being created/saved. The compression/write to disk is asynchronous, so this callback
|
|
|
|
/// just signifies that the save has started, not necessarily completed.
|
|
|
|
void onSaveStateSaved(const QString& path);
|
|
|
|
|
2023-07-27 09:24:55 +00:00
|
|
|
/// Called when achievements login is requested.
|
|
|
|
void onAchievementsLoginRequested(Achievements::LoginRequestReason reason);
|
|
|
|
|
2022-04-18 13:35:14 +00:00
|
|
|
/// Called when achievements are reloaded/refreshed (e.g. game change, login, option change).
|
2023-09-17 10:19:51 +00:00
|
|
|
void onAchievementsRefreshed(quint32 id, const QString& game_info_string);
|
|
|
|
|
|
|
|
/// Called when hardcore mode is enabled or disabled.
|
|
|
|
void onAchievementsHardcoreModeChanged(bool enabled);
|
2022-04-18 13:35:14 +00:00
|
|
|
|
2024-01-18 11:10:32 +00:00
|
|
|
/// Big Picture UI requests.
|
2023-10-02 04:57:20 +00:00
|
|
|
void onCoverDownloaderOpenRequested();
|
2024-01-18 11:10:32 +00:00
|
|
|
void onCreateMemoryCardOpenRequested();
|
2023-10-02 04:57:20 +00:00
|
|
|
|
2023-07-06 13:18:30 +00:00
|
|
|
/// Called when video capture starts/stops.
|
|
|
|
void onCaptureStarted(const QString& filename);
|
|
|
|
void onCaptureStopped();
|
|
|
|
|
2022-09-07 09:20:50 +00:00
|
|
|
protected:
|
|
|
|
void run();
|
|
|
|
|
|
|
|
private:
|
|
|
|
/// Interval at which the controllers are polled when the system is not active.
|
|
|
|
static constexpr u32 BACKGROUND_CONTROLLER_POLLING_INTERVAL = 100;
|
|
|
|
|
|
|
|
/// Poll at half the vsync rate for FSUI to reduce the chance of getting a press+release in the same frame.
|
|
|
|
static constexpr u32 FULLSCREEN_UI_CONTROLLER_POLLING_INTERVAL = 8;
|
|
|
|
|
|
|
|
void destroyVM();
|
|
|
|
|
|
|
|
void createBackgroundControllerPollTimer();
|
|
|
|
void destroyBackgroundControllerPollTimer();
|
|
|
|
void connectSignals();
|
|
|
|
|
|
|
|
private Q_SLOTS:
|
|
|
|
void stopInThread();
|
|
|
|
void doBackgroundControllerPoll();
|
|
|
|
void onDisplayWindowResized(int width, int height, float scale);
|
|
|
|
void onApplicationStateChanged(Qt::ApplicationState state);
|
|
|
|
void redrawDisplayWindow();
|
|
|
|
|
|
|
|
private:
|
|
|
|
QThread* m_ui_thread;
|
|
|
|
QSemaphore m_started_semaphore;
|
|
|
|
QEventLoop* m_event_loop = nullptr;
|
|
|
|
QTimer* m_background_controller_polling_timer = nullptr;
|
|
|
|
|
|
|
|
std::atomic_bool m_shutdown_flag{false};
|
2024-03-31 10:39:16 +00:00
|
|
|
std::atomic_bool m_run_fullscreen_ui{false};
|
2022-09-07 09:20:50 +00:00
|
|
|
|
|
|
|
bool m_verbose_status = false;
|
|
|
|
bool m_is_rendering_to_main = false;
|
|
|
|
bool m_is_fullscreen = false;
|
2023-04-25 12:52:41 +00:00
|
|
|
bool m_is_exclusive_fullscreen = false;
|
2022-09-07 09:20:50 +00:00
|
|
|
bool m_is_surfaceless = false;
|
|
|
|
bool m_save_state_on_shutdown = false;
|
|
|
|
bool m_pause_on_focus_loss = false;
|
|
|
|
|
|
|
|
bool m_was_paused_by_focus_loss = false;
|
|
|
|
|
|
|
|
float m_last_speed = 0.0f;
|
|
|
|
float m_last_game_fps = 0.0f;
|
|
|
|
float m_last_video_fps = 0.0f;
|
|
|
|
int m_last_internal_width = 0;
|
|
|
|
int m_last_internal_height = 0;
|
2024-03-31 14:44:57 +00:00
|
|
|
GSRendererType m_last_renderer = GSRendererType::Auto;
|
2022-09-07 09:20:50 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
extern EmuThread* g_emu_thread;
|
|
|
|
|
2021-12-13 12:12:54 +00:00
|
|
|
namespace QtHost
|
|
|
|
{
|
2023-04-25 10:24:22 +00:00
|
|
|
/// Default theme name for the platform.
|
|
|
|
const char* GetDefaultThemeName();
|
|
|
|
|
2023-06-19 12:03:10 +00:00
|
|
|
/// Default language for the platform.
|
|
|
|
const char* GetDefaultLanguage();
|
|
|
|
|
2023-04-25 10:24:22 +00:00
|
|
|
/// Sets application theme according to settings.
|
|
|
|
void UpdateApplicationTheme();
|
|
|
|
|
2024-01-11 09:38:28 +00:00
|
|
|
/// Returns true if the application theme is using dark colours.
|
|
|
|
bool IsDarkApplicationTheme();
|
|
|
|
|
2023-09-09 05:55:38 +00:00
|
|
|
/// Sets the icon theme, based on the current style (light/dark).
|
|
|
|
void SetIconThemeFromStyle();
|
|
|
|
|
2022-05-03 04:26:49 +00:00
|
|
|
/// Sets batch mode (exit after game shutdown).
|
|
|
|
bool InBatchMode();
|
|
|
|
|
2022-07-09 09:14:48 +00:00
|
|
|
/// Sets NoGUI mode (implys batch mode, does not display main window, exits on shutdown).
|
|
|
|
bool InNoGUIMode();
|
|
|
|
|
2022-09-07 07:44:10 +00:00
|
|
|
/// Returns true if the calling thread is the UI thread.
|
|
|
|
bool IsOnUIThread();
|
|
|
|
|
2022-11-23 13:20:49 +00:00
|
|
|
/// Returns true if advanced settings should be shown.
|
|
|
|
bool ShouldShowAdvancedSettings();
|
|
|
|
|
2022-04-06 10:49:00 +00:00
|
|
|
/// Executes a function on the UI thread.
|
|
|
|
void RunOnUIThread(const std::function<void()>& func, bool block = false);
|
|
|
|
|
2023-06-19 12:03:10 +00:00
|
|
|
/// Returns a list of supported languages and codes (suffixes for translation files).
|
|
|
|
std::vector<std::pair<QString, QString>> GetAvailableLanguageList();
|
|
|
|
|
|
|
|
/// Call when the language changes.
|
2024-01-07 05:27:39 +00:00
|
|
|
void InstallTranslator(QWidget* dialog_parent);
|
2023-06-19 12:03:10 +00:00
|
|
|
|
2022-05-11 08:24:56 +00:00
|
|
|
/// Returns the application name and version, optionally including debug/devel config indicator.
|
|
|
|
QString GetAppNameAndVersion();
|
|
|
|
|
|
|
|
/// Returns the debug/devel config indicator.
|
|
|
|
QString GetAppConfigSuffix();
|
|
|
|
|
2024-01-07 05:26:56 +00:00
|
|
|
/// Returns the main application icon.
|
|
|
|
QIcon GetAppIcon();
|
|
|
|
|
2022-06-04 05:53:31 +00:00
|
|
|
/// Returns the base path for resources. This may be : prefixed, if we're using embedded resources.
|
|
|
|
QString GetResourcesBasePath();
|
|
|
|
|
2024-01-07 05:26:56 +00:00
|
|
|
/// Returns the URL to a runtime-downloaded resource.
|
|
|
|
std::string GetRuntimeDownloadedResourceURL(std::string_view name);
|
|
|
|
|
2024-05-04 13:33:35 +00:00
|
|
|
/// Saves a game settings interface.
|
|
|
|
bool SaveGameSettings(SettingsInterface* sif, bool delete_if_empty);
|
|
|
|
|
2024-01-07 05:26:56 +00:00
|
|
|
/// Downloads the specified URL to the provided path.
|
|
|
|
bool DownloadFile(QWidget* parent, const QString& title, std::string url, const std::string& path);
|
|
|
|
|
2022-06-28 12:53:26 +00:00
|
|
|
/// VM state, safe to access on UI thread.
|
|
|
|
bool IsVMValid();
|
|
|
|
bool IsVMPaused();
|
2023-09-09 02:38:02 +00:00
|
|
|
|
2024-01-11 08:19:27 +00:00
|
|
|
/// Accessors for game information.
|
|
|
|
const QString& GetCurrentGameTitle();
|
|
|
|
const QString& GetCurrentGameSerial();
|
|
|
|
const QString& GetCurrentGamePath();
|
|
|
|
|
2023-09-09 02:38:02 +00:00
|
|
|
/// Compare strings in the locale of the current UI language
|
|
|
|
int LocaleSensitiveCompare(QStringView lhs, QStringView rhs);
|
2021-12-13 12:12:54 +00:00
|
|
|
} // namespace QtHost
|