Files

438 lines
16 KiB
C++
Raw Permalink Normal View History

// SPDX-FileCopyrightText: 2002-2026 PCSX2 Dev Team
2024-07-30 13:42:36 +02:00
// SPDX-License-Identifier: GPL-3.0+
2021-12-08 21:14:55 +10:00
#pragma once
#include <functional>
#include <mutex>
2021-12-08 21:14:55 +10:00
#include <optional>
#include <span>
2021-12-08 21:14:55 +10:00
#include <string>
#include <string_view>
2023-09-09 19:44:06 +10:00
#include <vector>
#include "common/Pcsx2Defs.h"
#include "Config.h"
2021-12-08 21:14:55 +10:00
enum class CDVD_SourceType : uint8_t;
enum class VMState
{
Shutdown,
Initializing,
Running,
Paused,
2023-01-25 22:02:19 +10:00
Resetting,
2021-12-08 21:14:55 +10:00
Stopping,
};
struct VMBootParameters
{
2022-03-13 00:52:52 +10:00
std::string filename;
2021-12-08 21:14:55 +10:00
std::string elf_override;
2022-03-13 00:52:52 +10:00
std::string save_state;
2022-05-03 14:26:49 +10:00
std::optional<s32> state_index;
2022-03-13 00:52:52 +10:00
std::optional<CDVD_SourceType> source_type;
2021-12-08 21:14:55 +10:00
std::optional<bool> fast_boot;
std::optional<bool> fullscreen;
std::optional<bool> start_turbo;
std::optional<bool> start_unlimited;
bool disable_achievements_hardcore_mode = false;
2021-12-08 21:14:55 +10:00
};
enum class VMBootResult
{
/// The boot succeeded.
StartupSuccess,
/// The boot failed and an error should be displayed in the UI.
StartupFailure,
/// The boot failed because the user needs to be prompted to disable
/// hardcore mode. If the user agrees, VMManager::Initialize should be
/// called again with disable_achievements_hardcore_mode set to true.
PromptDisableHardcoreMode
};
/// Callback used to restart the VM boot process after the user has consented
/// to hardcore mode being disabled.
using VMBootRestartCallback = std::function<void()>;
/// Callback used when the VM boot process has been interrupted because the user
/// needs to be prompted to disable hardcore mode.
using VMBootHardcoreDisableCallback = std::function<void(std::string reason, VMBootRestartCallback restart_callback)>;
/// Callback used when the VM boot process has finished. This may be called
/// asynchronously after the user has been prompted to disable hardcore mode.
using VMBootDoneCallback = std::function<void(VMBootResult result, const Error& error)>;
2021-12-08 21:14:55 +10:00
namespace VMManager
{
2022-10-01 23:29:29 +10:00
/// The number of usable save state slots.
static constexpr s32 NUM_SAVE_STATE_SLOTS = 10;
static constexpr u32 EMULATION_ONLY_RELEASE_PATCHES = (1u << 0);
static constexpr u32 EMULATION_ONLY_RELEASE_DISCORD_PRESENCE = (1u << 1);
static constexpr u32 EMULATION_ONLY_RELEASE_PINE = (1u << 2);
static constexpr u32 EMULATION_ONLY_RELEASE_ACHIEVEMENTS = (1u << 3);
static constexpr u32 EMULATION_ONLY_RELEASE_INPUT_RECORDING = (1u << 4);
static constexpr u32 EMULATION_ONLY_RELEASE_OSD = (1u << 5);
static constexpr u32 EMULATION_ONLY_RELEASE_ALL =
EMULATION_ONLY_RELEASE_PATCHES |
EMULATION_ONLY_RELEASE_DISCORD_PRESENCE |
EMULATION_ONLY_RELEASE_PINE |
EMULATION_ONLY_RELEASE_ACHIEVEMENTS |
EMULATION_ONLY_RELEASE_INPUT_RECORDING |
EMULATION_ONLY_RELEASE_OSD;
2022-10-01 23:29:29 +10:00
2023-05-24 21:14:16 -05:00
/// The stack size to use for threads running recompilers
static constexpr std::size_t EMU_THREAD_STACK_SIZE = 2 * 1024 * 1024; // µVU likes recursion
2022-05-27 19:48:59 +10:00
/// Makes sure that AVX2 is available if we were compiled with it.
bool PerformEarlyHardwareChecks(const char** error);
2021-12-08 21:14:55 +10:00
/// Returns the current state of the VM.
VMState GetState();
/// Alters the current state of the VM.
void SetState(VMState state);
/// Returns true if there is an active virtual machine.
bool HasValidVM();
/// Returns the path of the disc currently running.
std::string GetDiscPath();
/// Returns the serial of the disc currently running.
std::string GetDiscSerial();
2021-12-08 21:14:55 +10:00
/// Returns the path of the main ELF of the disc currently running.
std::string GetDiscELF();
2021-12-08 21:14:55 +10:00
/// Returns the name of the disc/executable currently running.
std::string GetTitle(bool prefer_en);
/// Returns the CRC for the main ELF of the disc currently running.
u32 GetDiscCRC();
/// Returns the version of the disc currently running.
std::string GetDiscVersion();
/// Returns the crc of the executable currently running.
u32 GetCurrentCRC();
2021-12-08 21:14:55 +10:00
/// Returns the path to the ELF which is currently running. Only safe to read on the EE thread.
const std::string& GetCurrentELF();
/// Initializes all system components. May restart itself asynchronously
/// using the provided hardcore_disable_callback function. Will call the
/// done_callback function on either success or failure.
void InitializeAsync(
const VMBootParameters& boot_params,
VMBootHardcoreDisableCallback hardcore_disable_callback,
VMBootDoneCallback done_callback);
/// Initializes all system components. Will not attempt to restart itself.
VMBootResult Initialize(const VMBootParameters& boot_params, Error* error = nullptr);
2021-12-08 21:14:55 +10:00
/// Destroys all system components.
2022-05-07 22:56:44 +10:00
void Shutdown(bool save_resume_state);
2021-12-08 21:14:55 +10:00
/// Resets all subsystems to a cold boot if it's safe to do so.
bool RequestReset();
2021-12-08 21:14:55 +10:00
/// Resets all subsystems to a cold boot.
void Reset();
/// Runs the VM until the CPU execution is canceled.
void Execute();
2023-09-17 20:19:51 +10:00
/// Polls input, updates subsystems which are present while paused/inactive.
void IdlePollUpdate();
2021-12-08 21:14:55 +10:00
/// Changes the pause state of the VM, resetting anything needed when unpausing.
void SetPaused(bool paused);
/// Reloads settings, and applies any changes present.
void ApplySettings();
/// Reloads game specific settings, and applys any changes present.
bool ReloadGameSettings();
2021-12-08 21:14:55 +10:00
/// Reloads game patches.
void ReloadPatches(bool reload_files, bool reload_enabled_list, bool verbose, bool verbose_if_changed);
/// Stops and releases optional runtime services while preserving the active VM,
/// renderer, audio, storage devices, networking devices, and controller input.
void ReleaseNonEssentialRuntimeResources(u32 release_flags);
/// Returns true after optional resources have been released for the current VM session.
bool IsEmulationOnlyMode();
/// Marks the active game's boot patches as applied. iOS waits for this and texture
/// replacement startup before automatically entering emulation-only mode.
void NotifyBootPatchesApplied();
/// Marks the active game's replacement-texture map/precache startup as complete.
void NotifyTextureReplacementStartupComplete();
/// Reloads input sources.
void ReloadInputSources();
/// Reloads input bindings.
2025-03-02 23:04:19 +00:00
/// Can be forced to load even when there is not an active virtual machine.
void ReloadInputBindings(bool force = false);
/// Sentinel slot value for the autosave-on-exit state. Routes
/// GetSaveStateFileName to a dedicated `.autosave.p2s` filename so the
/// "Save State And Exit" overlay action doesn't clobber numbered slot 0.
/// The load picker surfaces this slot only when the file exists.
static constexpr s32 SAVESTATE_SLOT_AUTOSAVE = -2;
2021-12-08 21:14:55 +10:00
/// Returns the save state filename for the given game serial/crc.
2025-04-26 19:19:34 +07:00
std::string GetSaveStateFileName(const char* game_serial, u32 game_crc, s32 slot, bool backup = false);
2021-12-08 21:14:55 +10:00
2022-05-07 22:56:44 +10:00
/// Returns the path to save state for the specified disc/elf.
2025-04-26 19:19:34 +07:00
std::string GetSaveStateFileName(const char* filename, s32 slot, bool backup = false);
2022-05-07 22:56:44 +10:00
2021-12-08 21:14:55 +10:00
/// Returns true if there is a save state in the specified slot.
bool HasSaveStateInSlot(const char* game_serial, u32 game_crc, s32 slot);
/// Loads state from the specified file.
2025-11-27 16:46:31 +00:00
bool LoadState(const char* filename, Error* error = nullptr);
2021-12-08 21:14:55 +10:00
/// Loads state from the specified slot.
2025-11-27 16:46:31 +00:00
bool LoadStateFromSlot(s32 slot, bool backup = false, Error* error = nullptr);
2021-12-08 21:14:55 +10:00
/// Saves state to the specified filename.
void SaveState(const char* filename, bool zip_on_thread, bool backup_old_state,
std::function<void(const std::string&)> error_callback);
2021-12-08 21:14:55 +10:00
/// Saves state to the specified slot.
void SaveStateToSlot(s32 slot, bool zip_on_thread, std::function<void(const std::string&)> error_callback);
2021-12-08 21:14:55 +10:00
/// Waits until all compressing save states have finished saving to disk.
void WaitForSaveStateFlush();
2022-10-01 23:29:29 +10:00
/// Removes all save states for the specified serial and crc. Returns the number of files deleted.
u32 DeleteSaveStates(const char* game_serial, u32 game_crc, bool also_backups = true);
2021-12-08 21:14:55 +10:00
/// Returns the current limiter mode.
LimiterModeType GetLimiterMode();
/// Updates the host vsync state, as well as timer frequencies. Call when the speed limiter is adjusted.
void SetLimiterMode(LimiterModeType type);
2023-09-09 19:44:06 +10:00
/// Returns the target speed, based on the limiter mode.
float GetTargetSpeed();
/// Ensures the target speed reflects the current configuration. Call if you change anything in
/// EmuConfig.EmulationSpeed without going through the usual config apply.
void UpdateTargetSpeed();
2024-04-24 01:17:52 +10:00
/// Returns true if the target speed is being synchronized with the host's refresh rate.
bool IsTargetSpeedAdjustedToHost();
2023-09-09 19:44:06 +10:00
/// Returns the current frame rate of the virtual machine.
float GetFrameRate();
2024-05-23 23:35:34 +10:00
/// Returns the desired vsync mode, depending on the runtime environment.
GSVSyncMode GetEffectiveVSyncMode();
/// Returns true if presents can be skipped, when running outside of normal speed.
bool ShouldAllowPresentThrottle();
2022-04-04 22:06:44 +10:00
/// Runs the virtual machine for the specified number of video frames, and then automatically pauses.
void FrameAdvance(u32 num_frames = 1);
2021-12-08 21:14:55 +10:00
/// Changes the disc in the virtual CD/DVD drive. Passing an empty will remove any current disc.
/// Returns false if the new disc can't be opened.
2022-06-28 23:34:45 +10:00
bool ChangeDisc(CDVD_SourceType source, std::string path);
2021-12-08 21:14:55 +10:00
2023-09-09 15:37:31 +10:00
/// Changes the ELF to boot ("ELF override"). The VM will be reset.
bool SetELFOverride(std::string path);
/// Changes the current GS dump being played back.
bool ChangeGSDump(const std::string& path);
2021-12-08 21:14:55 +10:00
/// Returns true if the specified path is an ELF.
bool IsElfFileName(const std::string_view path);
2021-12-08 21:14:55 +10:00
2022-06-29 19:31:44 +10:00
/// Returns true if the specified path is a blockdump.
bool IsBlockDumpFileName(const std::string_view path);
2022-06-29 19:31:44 +10:00
2022-03-12 23:20:23 +10:00
/// Returns true if the specified path is a GS Dump.
bool IsGSDumpFileName(const std::string_view path);
2022-05-26 17:49:40 +10:00
/// Returns true if the specified path is a save state.
bool IsSaveStateFileName(const std::string_view path);
2022-05-26 17:49:40 +10:00
/// Returns true if the specified path is a disc image.
bool IsDiscFileName(const std::string_view path);
2022-05-26 17:49:40 +10:00
/// Returns true if the specified path is a disc/elf/etc.
bool IsLoadableFileName(const std::string_view path);
2022-03-12 23:20:23 +10:00
/// Returns the serial to use when computing the game settings path for the current game.
std::string GetSerialForGameSettings();
2021-12-08 21:14:55 +10:00
/// Returns the path for the game settings ini file for the specified CRC.
std::string GetGameSettingsPath(const std::string_view game_serial, u32 game_crc);
2021-12-08 21:14:55 +10:00
/// Returns the ISO override for an ELF via gamesettings.
std::string GetDiscOverrideFromGameSettings(const std::string& elf_path);
2022-04-02 22:17:26 +10:00
/// Returns the path for the input profile ini file with the specified name (may not exist).
std::string GetInputProfilePath(const std::string_view name);
2022-04-02 22:17:26 +10:00
/// Returns the path for the debugger settings json file for the specified game serial and CRC.
std::string GetDebuggerSettingsFilePath(const std::string_view game_serial, u32 game_crc);
/// Returns the path for the debugger settings json file for the current game.
std::string GetDebuggerSettingsFilePathForCurrentGame();
2021-12-08 21:14:55 +10:00
/// Resizes the render window to the display size, with an optional scale.
/// If the scale is set to 0, the internal resolution will be used, otherwise it is treated as a multiplier to 1x.
void RequestDisplaySize(float scale = 0.0f);
/// Initializes default configuration in the specified file for the specified categories.
void SetDefaultSettings(SettingsInterface& si, bool folders, bool core, bool controllers, bool hotkeys, bool ui);
2021-10-31 19:59:31 +10:00
/// Returns the time elapsed in the current play session.
u64 GetSessionPlayedTime();
/// Called when the rich presence string, provided by RetroAchievements, changes.
void UpdateDiscordPresence(bool update_session_time);
/// Append bytes to the EE SIO RX FIFO. If it returns false, the FIFO is full and data is not inserted.
bool WriteBytesToEESIORXFIFO(const std::span<const u8> data);
2021-12-08 21:14:55 +10:00
/// Internal callbacks, implemented in the emu core.
namespace Internal
{
/// Checks settings version. Call once on startup. If it returns false, you should prompt the user to reset.
bool CheckSettingsVersion();
2022-03-16 21:03:24 +10:00
/// Loads early settings. Call once on startup.
void LoadStartupSettings();
2022-05-24 00:20:29 +10:00
2024-01-11 18:08:16 +10:00
/// Overrides the filename used for the file log.
void SetFileLogPath(std::string path);
/// Prevents the system console from being displayed.
void SetBlockSystemConsole(bool block);
/// Initializes common host state, called on the CPU thread.
bool CPUThreadInitialize();
2022-03-16 21:03:24 +10:00
/// Cleans up common host state, called on the CPU thread.
void CPUThreadShutdown();
/// Whether the caller is the CPU thread, i.e. the thread that ran CPUThreadInitialize().
/// The CPU thread owns EmuConfig and is the sole producer into the MTGS ring, so most core
/// mutation is only legal from it — everything else must marshal via Host::RunOnCPUThread()
/// (or Host::RunOnGSThread(), which chains through it). Returns true when no CPU thread is
/// registered, so startup/teardown and CPU-thread-less test harnesses stay unencumbered.
bool IsOnCPUThread();
/// Android: affinity mask of the performance ("big") CPU cluster hosting the
/// EE/VU/GS threads, so adjacent helper threads (e.g. the Oboe audio callback)
/// can pin onto the same cluster. Returns 0 when pinning is off / unresolved.
u64 GetPerformanceClusterAffinityMask();
/// Android: affinity mask of the performance ("big") CPU cluster hosting the
/// EE/VU/GS threads, so adjacent helper threads (e.g. the Oboe audio callback)
/// can pin onto the same cluster. Returns 0 when pinning is off / unresolved.
u64 GetPerformanceClusterAffinityMask();
/// Resets any state for hotkey-related VMs, called on VM startup.
void ResetVMHotkeyState();
/// Updates the variables in the EmuFolders namespace, reloading subsystems if needed.
void UpdateEmuFolders();
2022-03-16 21:03:24 +10:00
2024-06-09 17:57:50 +10:00
/// Returns true if the VM was fast booted.
bool WasFastBooted();
/// Returns true if fast booting is active (requested but ELF not started).
bool IsFastBootInProgress();
/// Disables fast boot if it was requested, and found to be incompatible.
void DisableFastBoot();
/// Returns true if the current ELF has started executing.
bool HasBootedELF();
/// Returns the PC of the currently-executing ELF's entry point.
u32 GetCurrentELFEntryPoint();
2023-09-09 19:44:06 +10:00
/// Called when the internal frame rate changes.
void FrameRateChanged();
/// Throttles execution, or limits the frame rate.
void Throttle();
2023-12-26 21:05:33 +10:00
/// Resets/clears all execution/code caches.
void ClearCPUExecutionCaches();
/// Returns a list of processors in the system, suitable for pinning for the software renderer.
const std::vector<u32>& GetSoftwareRendererProcessorList();
/// Diagnostic (OSD): where the EE/VU/GS threads are actually running (current core +
/// affinity mask) plus the cpuinfo cluster/frequency topology. Used to see whether the
/// worker threads are being scheduled onto slow cores / clamped by a cpuset.
std::string GetThreadPlacementDebug();
const std::string& GetELFOverride();
2021-12-08 21:14:55 +10:00
bool IsExecutionInterrupted();
void ELFLoadingOnCPUThread(std::string elf_path);
2022-05-24 23:10:39 +10:00
void EntryPointCompilingOnCPUThread();
2021-12-08 21:14:55 +10:00
void VSyncOnCPUThread();
2024-01-26 21:27:36 +10:00
void PollInputOnCPUThread();
} // namespace Internal
2021-12-08 21:14:55 +10:00
} // namespace VMManager
namespace Host
{
/// Called with the settings lock held, when system settings are being loaded (should load input sources, etc).
void LoadSettings(SettingsInterface& si, std::unique_lock<std::mutex>& lock);
/// Called after settings are updated.
void CheckForSettingsChanges(const Pcsx2Config& old_config);
2021-12-08 21:14:55 +10: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 shut down or destroyed.
void OnVMDestroyed();
/// Called when the VM is paused.
void OnVMPaused();
/// Called when the VM is resumed after being paused.
void OnVMResumed();
2022-04-03 23:46:05 +10:00
/// Called when performance metrics are updated, approximately once a second.
void OnPerformanceMetricsUpdated();
/// Called when a save state is loading, before the file is processed.
void OnSaveStateLoading(const std::string_view filename);
/// Called after a save state is successfully loaded. If the save state was invalid, was_successful will be false.
void OnSaveStateLoaded(const std::string_view filename, 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 std::string_view filename);
2021-12-08 21:14:55 +10:00
/// Provided by the host; called when the running executable changes.
void OnGameChanged(const std::string& title, const std::string& elf_override, const std::string& disc_path,
const std::string& disc_serial, u32 disc_crc, u32 current_crc);
2021-12-08 21:14:55 +10:00
/// Provided by the host; called once per frame at guest vsync.
2024-01-26 21:27:36 +10:00
void PumpMessagesOnCPUThread();
} // namespace Host