Compare commits

...

71 Commits

Author SHA1 Message Date
Tygyh
f08b27f204
Merge e3aa5f0763 into 65f3ba70f5 2025-06-07 17:55:17 -05:00
Jordan Woyak
65f3ba70f5
Merge pull request #13522 from tygyh/Enforce-overriding-destructor-style-Core&UnitTests
Core & UnitTests: Make overriding explicit and remove redundant virtual specifiers on overriding destructors
2025-06-07 17:55:14 -05:00
Jordan Woyak
ec52a74967
Merge pull request #13023 from tygyh/Replace-ties-with-structured-bindings
UnitTests: Replace ties with structured bindings
2025-06-07 17:50:34 -05:00
Jordan Woyak
8b7669550f
Merge pull request #13454 from tygyh/Use-constants-DolphinQt-FifoAnalyzer
DolphinQt/FIFO/FIFOAnalyzer: Make parameters, arguments etc. constant
2025-06-07 17:50:08 -05:00
Jordan Woyak
46e66fe945
Merge pull request #13544 from tygyh/DolphinNoGUI-Replace-deprecated-signal-header
DolphinNoGUI: Apply style-alignment refactorings
2025-06-07 17:47:11 -05:00
Jordan Woyak
056ece6f29
Merge pull request #13697 from tygyh/AudioCommon/Remove-unused-includes
AudioCommon: Remove unused includes
2025-06-07 17:45:50 -05:00
Jordan Woyak
a07a2fe398
Merge pull request #13698 from tygyh/AudioCommon/Remove-unused-qualifiers-and-make-variables-constant
AudioCommon: Remove unused qualifiers and make variables constant
2025-06-07 17:45:33 -05:00
JMC47
52fcdde485
Merge pull request #13386 from iwubcode/resource_manager_system
VideoCommon: add resource manager, tracks resources to load assets in optimal way and manage memory
2025-06-07 15:51:34 -04:00
JMC47
5eb61024c6
Merge pull request #13740 from JoshuaVandaele/bsod-fix-i-hope
Host: Clean up device handle in all cases
2025-06-07 12:27:49 -04:00
Admiral H. Curtiss
a27b845514
Merge pull request #13710 from TryTwo/UI_Sliders_Update
Advanced Panel convert QSliders into ConfigSliders
2025-06-07 17:39:40 +02:00
Admiral H. Curtiss
1b1ca019a4
Merge pull request #13724 from SuperSamus/gamelist-properties-noduplicates
GameList: Prevent opening Properties multiple times for the same game
2025-06-07 17:24:50 +02:00
Joshua Vandaële
241834709b
Host: Clean up device handle 2025-06-07 16:55:45 +02:00
JosJuice
185b080f03
Merge pull request #13142 from JosJuice/fifo-window-starting-stopping
DolphinQt: Call FIFOPlayerWindow::UpdateControls for Starting/Stopping
2025-06-07 10:43:19 +02:00
iwubcode
c3d3b81533 VideoCommon: remove 'GetByteSizeInMemory()' from custom asset, it is not needed anymore 2025-06-06 23:03:02 -05:00
iwubcode
774a84a953 VideoCommon: avoid race conditions with asset load/unload by moving the lock to the entire function, favor atomics for the memory/time getters 2025-06-06 23:03:02 -05:00
iwubcode
b3f50c969e VideoCommon: rename m_bytes_loaded in asset library to bytes_loaded 2025-06-06 23:03:02 -05:00
iwubcode
3b83907b88 VideoCommon: update CustomAsset's load time to be before the load occurs (this prevents issues where the load time might be incorrectly inflated by long load operations)
Co-authored-by: Jordan Woyak <jordan.woyak@gmail.com>
2025-06-06 23:03:02 -05:00
iwubcode
d940d62cae VideoCommon: watch texture pack folder for texture reloads (from dynamic input textures) 2025-06-06 23:03:02 -05:00
iwubcode
7afa9e6c6f VideoCommon: use CustomResourceManager in the texture cache and hook up to our hires textures 2025-06-06 23:03:02 -05:00
iwubcode
12d178a8df VideoCommon: initialize and shutdown the CustomResourceManager when the video thread initializes and shuts down 2025-06-06 23:03:02 -05:00
iwubcode
f910c1d934 Core: add CustomResourceManager to System 2025-06-06 23:03:02 -05:00
iwubcode
70abcb2030 VideoCommon: add resource manager and new asset loader; the resource manager uses a least recently used cache to determine which assets get priority for loading. Additionally, if the system is low on memory, assets will be purged with the less requested assets being the first to go. The loader is multithreaded now and loads assets as quickly as possible as long as memory is available
Co-authored-by: Jordan Woyak <jordan.woyak@gmail.com>
2025-06-06 23:03:02 -05:00
iwubcode
d8ea31ca46 VideoCommon: rename GameTextureAsset into TextureAsset and make it only contain CustomTextureData. Move validation and load logic to individual functions 2025-06-06 23:03:02 -05:00
iwubcode
2ae43324cb VideoCommon: move AssetMap to a types header file, so it can be pulled in without the DirectFilesystemAssetLibrary dependencies, the header will be expanded later 2025-06-06 23:03:02 -05:00
iwubcode
7d59c2743d Common: Add class 'FilesystemWatcher' that is used to watch paths and receive callbacks about filesystem level events for anything under that path 2025-06-06 23:03:02 -05:00
iwubcode
8113399b68 Externals: add watcher, a library used to watch a filesystem location for changes 2025-06-06 23:03:02 -05:00
iwubcode
bafe78203d VideoCommon: remove 'GetLastAssetWriteTime' and switch to a steady_clock for asset times 2025-06-06 23:03:02 -05:00
iwubcode
15f125ebee VideoCommon: change asset loading to return the number of bytes loaded instead of a pass/fail 2025-06-06 23:03:02 -05:00
iwubcode
316740daed VideoCommon: add 'Unload' functionality to CustomAsset 2025-06-06 23:03:02 -05:00
Jordan Woyak
903eafcf65
Merge pull request #13714 from Dentomologist/dolphinqt_remove_redundant_window_hints
DolphinQt: Remove redundant window hints
2025-06-06 22:13:01 -05:00
Dentomologist
2a7e8a4003 DolphinQt: Remove redundant window hints
Remove window hints clearing the flag Qt::WindowContextHelpButtonHint,
which is already off by default in Qt 6.

In Qt 5 this flag was set by default for QDialogs, and on Windows put a
? button in the corner of the title bar allowing users to activate Qt's
QWhatsThis help system for a given widget. Since we don't set that text
the ? button was useless and so we hid it manually.
2025-06-06 19:35:13 -07:00
iwubcode
9ec69b5925 VideoCommon: add a handle to custom asset, this is an id that is only relevant for a particular game session but is slightly faster as a numeric value for lookups than the traditional asset id 2025-06-06 19:20:25 -05:00
iwubcode
d7de49ccf6 Core / VideoCommon: Remove original custom asset loader 2025-06-06 19:20:25 -05:00
JMC47
5ec5db9240
Merge pull request #13392 from jordan-woyak/frame-pacing-accurate-time
CoreTiming: Add setting to pursue accurate overall emulation runtime
2025-06-06 19:17:44 -04:00
JMC47
974c56d3c5
Merge pull request #13731 from iwubcode/pixel_shader_gen_fix_complete_initialize
VideoCommon: ensure pixel shader gen input structure is completely initialized
2025-06-06 19:08:57 -04:00
Jordan Woyak
977f2da6a7
Merge pull request #13735 from JMC47/triopatch
GamePatch: Disney Trio of Destruction Pagetable Speedhack.
2025-06-06 17:54:36 -05:00
JMC47
b1d114f7f7
Merge pull request #13730 from jordan-woyak/controllers-on-main-config-dialog
DolphinQt: Move "Controllers" to main settings window.
2025-06-06 18:54:12 -04:00
JMC47
be3d48ec5f GamePatch: Disney Trio of Destruction Pagetable Speedhack. 2025-06-06 17:17:11 -04:00
iwubcode
ae26b38fc0 VideoCommon: fix pixel shader gen error about structure not being fully initialized 2025-06-05 01:37:45 -05:00
Jordan Woyak
b9bea58f0f DolphinQt: Move "Controllers" to main settings window. 2025-06-04 19:33:01 -05:00
Martino Fontana
2de9122b5f GameList: Prevent opening Properties multiple times for the same game 2025-06-04 23:11:09 +02:00
Dr. Dystopia
bae0e5f67a DolphinNoGUI: Make override explicit 2025-06-04 21:49:29 +02:00
Dr. Dystopia
2ae928ca79 DolphinNoGUI: Make parameters constant 2025-06-04 21:49:15 +02:00
Dr. Dystopia
f04f659710 DolphinNoGUI: Replace C-style cast with reinterpret_cast 2025-06-04 21:49:01 +02:00
Dr. Dystopia
ec1d659363 DolphinNoGUI: Make classes final 2025-06-04 21:48:53 +02:00
Dr. Dystopia
c37933932d DolphinNoGUI: Make variables constant 2025-06-04 21:48:40 +02:00
Dr. Dystopia
23af1e025b DolphinNoGUI: Make function static 2025-06-04 21:30:59 +02:00
Dr. Dystopia
135b6840e5 DolphinNoGUI: Remove unused include directives 2025-06-04 21:30:59 +02:00
Dr. Dystopia
e3df00b7f4 DolphinNoGUI: Make variables constexpr 2025-06-04 21:30:59 +02:00
Dr. Dystopia
71da0f2d24 DolphinNoGUI: Replace deprecated signal.h header 2025-06-04 21:30:59 +02:00
Dr. Dystopia
8192d9d2a9 Make parameters, arguments etc. constant 2025-05-31 20:57:54 +02:00
Dentomologist
e3aa5f0763 DolphinAnalytics: Remove unused headers 2025-05-31 08:28:58 +02:00
Dentomologist
1d0d123447 DolphinAnalytics: Extract sample aggregation
Moves remaining sample aggregation logic to
PerformanceSampleAggregation.
2025-05-31 08:28:58 +02:00
Dentomologist
4138d691ae DolphinAnalytics: Extract report generation
Move generation of completed performance sample report to
PerformanceSampleAggregator.
2025-05-31 08:28:58 +02:00
Dentomologist
d9b0fd2805 DolphinAnalytics: Extract timestamp functions
Moves functions that generate starting timestamps for performance
sampling to PerformanceSampleAggregator.
2025-05-31 08:28:57 +02:00
Dentomologist
d78e6fe165 Create PerformanceSampleAggregator 2025-05-31 08:28:57 +02:00
Dentomologist
41b0c09486 DolphinAnalytics: Move PerformanceSample to header
Avoid circular dependencies or forward declarations in upcoming commits.
2025-05-31 08:28:57 +02:00
Dentomologist
b4eee80103 DolphinAnalytics: Make GameQuirk members TitleCase
# Conflicts:
#	Source/Core/Core/DolphinAnalytics.cpp
2025-05-31 08:28:57 +02:00
Dentomologist
6b8533d012 DolphinAnalytics: Reformat comments 2025-05-31 08:28:57 +02:00
Dentomologist
d3fc0c89e4 DolphinAnalytics: Refactor redundant data accesses 2025-05-31 08:28:57 +02:00
Dentomologist
e3de3ada05 DolphinAnalytics: Make assorted variables const 2025-05-31 08:28:57 +02:00
Dentomologist
7208b64a94 DolphinAnalytics: Extract ReportBuilder functions 2025-05-31 08:28:07 +02:00
Dr. Dystopia
a6b04f53e0 AudioCommon: Remove unused qualifiers and make variables constant 2025-05-30 21:48:38 +02:00
Dentomologist
ca10f2fdf1 DolphinAnalytics: Refactor variable declaration
Move endpoint declaration from anonymous namespace to the only function
it's used in.
2025-05-30 19:59:26 +02:00
Dentomologist
013c162cf1 DolphinAnalytics: Remove redundant #include
STL header <functional> was included from both Analytics.h and
Analytics.cpp on Android.
2025-05-30 19:59:26 +02:00
TryTwo
a6a5e201b6 Qt Advanced Panel: Convert QSliders into ConfigSliders.
Part of the refactor into the config system.
2025-05-26 19:52:30 -07:00
Dr. Dystopia
7c237bbd7c AudioCommon: Remove unused includes 2025-05-25 10:30:41 +02:00
Jordan Woyak
ec29d120b5 CoreTiming: Add a setting to pursue accurate emulation time. 2025-05-02 15:23:43 -05:00
Dr. Dystopia
f240e20e3f Make overriding explicit and remove redundant virtual specifiers on overriding destructors - Core & UnitTests 2025-05-01 15:00:37 +02:00
JosJuice
d48e6e25ad DolphinQt: Call FIFOPlayerWindow::UpdateControls for Starting/Stopping
Follow-up for
https://github.com/dolphin-emu/dolphin/pull/12918#discussion_r1785153070.
2024-10-20 13:38:24 +02:00
Dr. Dystopia
096ab8c026 Replace ties with structured bindings - UnitTests 2024-08-20 15:09:44 +02:00
279 changed files with 2388 additions and 1772 deletions

3
.gitmodules vendored
View File

@ -84,6 +84,9 @@
[submodule "Externals/Vulkan-Headers"]
path = Externals/Vulkan-Headers
url = https://github.com/KhronosGroup/Vulkan-Headers.git
[submodule "Externals/watcher/watcher"]
path = Externals/watcher/watcher
url = https://github.com/e-dant/watcher.git
[submodule "Externals/SFML/SFML"]
path = Externals/SFML/SFML
url = https://github.com/SFML/SFML.git

View File

@ -784,6 +784,8 @@ if (USE_RETRO_ACHIEVEMENTS)
add_subdirectory(Externals/rcheevos)
endif()
add_subdirectory(Externals/watcher)
########################################
# Pre-build events: Define configuration variables and write SCM info header
#

View File

@ -0,0 +1,9 @@
# SCYE4Q - Cars 2
[OnFrame]
#This speedhack modifies the way the game manages memory to run faster in Dolphin.
$BAT Speedhack
0x8019CB1C:dword:0x48000180
[OnFrame_Enabled]
$BAT Speedhack

View File

@ -0,0 +1,9 @@
# SCYP4Q - Cars 2
[OnFrame]
#This speedhack modifies the way the game manages memory to run faster in Dolphin.
$BAT Speedhack
0x8019CB1C:dword:0x48000180
[OnFrame_Enabled]
$BAT Speedhack

View File

@ -0,0 +1,9 @@
# SCYR4Q - Cars 2
[OnFrame]
#This speedhack modifies the way the game manages memory to run faster in Dolphin.
$BAT Speedhack
0x8019B4EC:dword:0x48000180
[OnFrame_Enabled]
$BAT Speedhack

View File

@ -0,0 +1,9 @@
# SCYX4Q - Cars 2
[OnFrame]
#This speedhack modifies the way the game manages memory to run faster in Dolphin.
$BAT Speedhack
0x8019CBBC:dword:0x48000180
[OnFrame_Enabled]
$BAT Speedhack

View File

@ -0,0 +1,9 @@
# SCYY4Q - Cars 2
[OnFrame]
#This speedhack modifies the way the game manages memory to run faster in Dolphin.
$BAT Speedhack
0x8019B55C:dword:0x48000180
[OnFrame_Enabled]
$BAT Speedhack

View File

@ -0,0 +1,9 @@
# SCYZ4Q - Cars 2
[OnFrame]
#This speedhack modifies the way the game manages memory to run faster in Dolphin.
$BAT Speedhack
0x8019B55C:dword:0x48000180
[OnFrame_Enabled]
$BAT Speedhack

View File

@ -1,4 +1,4 @@
# SQIE4Q, SQIP4Q - Disney Infinity
# SQIE4Q, SQIP4Q, SQIY4Q - Disney Infinity
[Core]
# Values set here will override the main Dolphin settings.

View File

@ -0,0 +1,9 @@
# SQIE4Q - Disney Infinity
[OnFrame]
#This speedhack modifies the way the game manages memory to run faster in Dolphin.
$BAT Speedhack
0x8008E60C:dword:0x48000180
[OnFrame_Enabled]
$BAT Speedhack

View File

@ -0,0 +1,9 @@
# SQIP4Q - Disney Infinity
[OnFrame]
#This speedhack modifies the way the game manages memory to run faster in Dolphin.
$BAT Speedhack
0x8008E60C:dword:0x48000180
[OnFrame_Enabled]
$BAT Speedhack

View File

@ -0,0 +1,9 @@
# SQIY4Q - Disney Infinity
[OnFrame]
#This speedhack modifies the way the game manages memory to run faster in Dolphin.
$BAT Speedhack
0x8008E60C:dword:0x48000180
[OnFrame_Enabled]
$BAT Speedhack

View File

@ -0,0 +1,9 @@
# STSE4Q - Toy Story 3
[OnFrame]
#This speedhack modifies the way the game manages memory to run faster in Dolphin.
$BAT Speedhack
0x801FA2E4:dword:0x48000180
[OnFrame_Enabled]
$BAT Speedhack

View File

@ -0,0 +1,9 @@
# STSP4Q - Toy Story 3
[OnFrame]
#This speedhack modifies the way the game manages memory to run faster in Dolphin.
$BAT Speedhack
0x801FA2E4:dword:0x48000180
[OnFrame_Enabled]
$BAT Speedhack

View File

@ -0,0 +1,9 @@
# STSP4Q - Toy Story 3
[OnFrame]
#This speedhack modifies the way the game manages memory to run faster in Dolphin.
$BAT Speedhack
0x801FA354:dword:0x48000180
[OnFrame_Enabled]
$BAT Speedhack

View File

@ -0,0 +1,9 @@
# STSX4Q - Toy Story 3
[OnFrame]
#This speedhack modifies the way the game manages memory to run faster in Dolphin.
$BAT Speedhack
0x801FA354:dword:0x48000180
[OnFrame_Enabled]
$BAT Speedhack

View File

@ -0,0 +1,9 @@
# STSY4Q - Toy Story 3
[OnFrame]
#This speedhack modifies the way the game manages memory to run faster in Dolphin.
$BAT Speedhack
0x801FA2E4:dword:0x48000180
[OnFrame_Enabled]
$BAT Speedhack

View File

@ -0,0 +1,9 @@
# STSY4Q - Toy Story 3
[OnFrame]
#This speedhack modifies the way the game manages memory to run faster in Dolphin.
$BAT Speedhack
0x801FA354:dword:0x48000180
[OnFrame_Enabled]
$BAT Speedhack

View File

@ -0,0 +1,9 @@
# STSZ4Q - Toy Story 3 Toy Box Special Edition
[OnFrame]
#This speedhack modifies the way the game manages memory to run faster in Dolphin.
$BAT Speedhack
0x801FA2E4:dword:0x48000180
[OnFrame_Enabled]
$BAT Speedhack

4
Externals/watcher/CMakeLists.txt vendored Normal file
View File

@ -0,0 +1,4 @@
add_library(watcher INTERFACE IMPORTED GLOBAL)
set_target_properties(watcher PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_LIST_DIR}/watcher/include
)

1
Externals/watcher/watcher vendored Submodule

@ -0,0 +1 @@
Subproject commit b03bdcfc11549df595b77239cefe2643943a3e2f

View File

@ -3,9 +3,7 @@
#pragma once
#include <atomic>
#include <condition_variable>
#include <mutex>
#include <thread>
#if defined(HAVE_ALSA) && HAVE_ALSA

View File

@ -166,7 +166,8 @@ void UpdateSoundStream(Core::System& system)
if (sound_stream)
{
int volume = Config::Get(Config::MAIN_AUDIO_MUTED) ? 0 : Config::Get(Config::MAIN_AUDIO_VOLUME);
int const volume =
Config::Get(Config::MAIN_AUDIO_MUTED) ? 0 : Config::Get(Config::MAIN_AUDIO_VOLUME);
sound_stream->SetVolume(volume);
}
}
@ -192,7 +193,7 @@ void SetSoundStreamRunning(Core::System& system, bool running)
void SendAIBuffer(Core::System& system, const short* samples, unsigned int num_samples)
{
SoundStream* sound_stream = system.GetSoundStream();
const SoundStream* const sound_stream = system.GetSoundStream();
if (!sound_stream)
return;
@ -212,9 +213,9 @@ void SendAIBuffer(Core::System& system, const short* samples, unsigned int num_s
void StartAudioDump(Core::System& system)
{
SoundStream* sound_stream = system.GetSoundStream();
const SoundStream* const sound_stream = system.GetSoundStream();
std::time_t start_time = std::time(nullptr);
std::time_t const start_time = std::time(nullptr);
std::string path_prefix = File::GetUserPath(D_DUMPAUDIO_IDX) + SConfig::GetInstance().GetGameID();
@ -232,7 +233,7 @@ void StartAudioDump(Core::System& system)
void StopAudioDump(Core::System& system)
{
SoundStream* sound_stream = system.GetSoundStream();
const SoundStream* const sound_stream = system.GetSoundStream();
if (!sound_stream)
return;
@ -265,7 +266,7 @@ void DecreaseVolume(Core::System& system, unsigned short offset)
void ToggleMuteVolume(Core::System& system)
{
bool isMuted = Config::Get(Config::MAIN_AUDIO_MUTED);
bool const isMuted = Config::Get(Config::MAIN_AUDIO_MUTED);
Config::SetBaseOrCurrent(Config::MAIN_AUDIO_MUTED, !isMuted);
UpdateSoundStream(system);
}

View File

@ -3,7 +3,6 @@
#pragma once
#include <memory>
#include <string>
#include <string_view>
#include <vector>

View File

@ -10,7 +10,6 @@
#include "Common/Event.h"
#include "Common/Logging/Log.h"
#include "Common/ScopeGuard.h"
#include "Common/Thread.h"
#include "Core/Config/MainSettings.h"
#ifdef _WIN32
@ -23,7 +22,7 @@ constexpr u32 BUFFER_SAMPLES = 512;
long CubebStream::DataCallback(cubeb_stream* stream, void* user_data, const void* /*input_buffer*/,
void* output_buffer, long num_frames)
{
auto* self = static_cast<CubebStream*>(user_data);
const auto* const self = static_cast<CubebStream*>(user_data);
if (self->m_stereo)
self->m_mixer->Mix(static_cast<short*>(output_buffer), num_frames);
@ -44,7 +43,7 @@ CubebStream::CubebStream()
Common::Event sync_event;
m_work_queue.Push([this, &sync_event] {
Common::ScopeGuard sync_event_guard([&sync_event] { sync_event.Set(); });
auto result = ::CoInitializeEx(nullptr, COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE);
auto const result = CoInitializeEx(nullptr, COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE);
m_coinit_success = result == S_OK;
m_should_couninit = result == S_OK || result == S_FALSE;
});

View File

@ -3,8 +3,6 @@
#pragma once
#include <cstddef>
#include <functional>
#include <memory>
#include <vector>

View File

@ -182,7 +182,8 @@ std::size_t Mixer::MixSurround(float* samples, std::size_t num_samples)
memset(samples, 0, num_samples * SURROUND_CHANNELS * sizeof(float));
std::size_t needed_frames = m_surround_decoder.QueryFramesNeededForSurroundOutput(num_samples);
std::size_t const needed_frames =
m_surround_decoder.QueryFramesNeededForSurroundOutput(num_samples);
constexpr std::size_t max_samples = 0x8000;
ASSERT_MSG(AUDIO, needed_frames <= max_samples,
@ -190,7 +191,7 @@ std::size_t Mixer::MixSurround(float* samples, std::size_t num_samples)
needed_frames, max_samples);
std::array<s16, max_samples> buffer;
std::size_t available_frames = Mix(buffer.data(), static_cast<std::size_t>(needed_frames));
std::size_t const available_frames = Mix(buffer.data(), static_cast<std::size_t>(needed_frames));
if (available_frames != needed_frames)
{
ERROR_LOG_FMT(AUDIO,
@ -229,7 +230,7 @@ void Mixer::PushSamples(const s16* samples, std::size_t num_samples)
if (m_log_dsp_audio)
{
const s32 sample_rate_divisor = m_dma_mixer.GetInputSampleRateDivisor();
auto volume = m_dma_mixer.GetVolume();
auto const volume = m_dma_mixer.GetVolume();
m_wave_writer_dsp.AddStereoSamplesBE(samples, static_cast<u32>(num_samples),
sample_rate_divisor, volume.first, volume.second);
}
@ -241,7 +242,7 @@ void Mixer::PushStreamingSamples(const s16* samples, std::size_t num_samples)
if (m_log_dtk_audio)
{
const s32 sample_rate_divisor = m_streaming_mixer.GetInputSampleRateDivisor();
auto volume = m_streaming_mixer.GetVolume();
auto const volume = m_streaming_mixer.GetVolume();
m_wave_writer_dtk.AddStereoSamplesBE(samples, static_cast<u32>(num_samples),
sample_rate_divisor, volume.first, volume.second);
}
@ -286,7 +287,8 @@ void Mixer::PushSkylanderPortalSamples(const u8* samples, std::size_t num_sample
{
for (std::size_t i = 0; i < num_samples; ++i)
{
s16 sample = static_cast<u16>(samples[i * 2 + 1]) << 8 | static_cast<u16>(samples[i * 2]);
s16 const sample =
static_cast<u16>(samples[i * 2 + 1]) << 8 | static_cast<u16>(samples[i * 2]);
samples_stereo[i * 2] = sample;
samples_stereo[i * 2 + 1] = sample;
}
@ -335,7 +337,8 @@ void Mixer::StartLogDTKAudio(const std::string& filename)
{
if (!m_log_dtk_audio)
{
bool success = m_wave_writer_dtk.Start(filename, m_streaming_mixer.GetInputSampleRateDivisor());
bool const success =
m_wave_writer_dtk.Start(filename, m_streaming_mixer.GetInputSampleRateDivisor());
if (success)
{
m_log_dtk_audio = true;
@ -372,7 +375,7 @@ void Mixer::StartLogDSPAudio(const std::string& filename)
{
if (!m_log_dsp_audio)
{
bool success = m_wave_writer_dsp.Start(filename, m_dma_mixer.GetInputSampleRateDivisor());
bool const success = m_wave_writer_dsp.Start(filename, m_dma_mixer.GetInputSampleRateDivisor());
if (success)
{
m_log_dsp_audio = true;
@ -494,10 +497,10 @@ void Mixer::MixerFifo::Enqueue()
0.0002984010f, 0.0002102045f, 0.0001443499f, 0.0000961509f, 0.0000616906f, 0.0000377350f,
0.0000216492f, 0.0000113187f, 0.0000050749f, 0.0000016272f};
const std::size_t head = m_queue_head.load(std::memory_order_acquire);
std::size_t const head = m_queue_head.load(std::memory_order_acquire);
// Check if we run out of space in the circular queue. (rare)
std::size_t next_head = (head + 1) & GRANULE_QUEUE_MASK;
std::size_t const next_head = (head + 1) & GRANULE_QUEUE_MASK;
if (next_head == m_queue_tail.load(std::memory_order_acquire))
{
WARN_LOG_FMT(AUDIO,

View File

@ -3,11 +3,9 @@
#pragma once
#include <algorithm>
#include <array>
#include <atomic>
#include <bit>
#include <cmath>
#include "AudioCommon/SurroundDecoder.h"
#include "AudioCommon/WaveFile.h"

View File

@ -76,7 +76,7 @@ static bool InitLibrary()
if (!InitFunctions())
{
::FreeLibrary(s_openal_dll);
FreeLibrary(s_openal_dll);
s_openal_dll = nullptr;
return false;
}
@ -168,7 +168,7 @@ bool OpenALStream::SetRunning(bool running)
static ALenum CheckALError(const char* desc)
{
ALenum err = palGetError();
ALenum const err = palGetError();
if (err != AL_NO_ERROR)
{
@ -211,16 +211,16 @@ void OpenALStream::SoundLoop()
{
Common::SetCurrentThreadName("Audio thread - openal");
bool float32_capable = palIsExtensionPresent("AL_EXT_float32") != 0;
bool surround_capable = palIsExtensionPresent("AL_EXT_MCFORMATS") || IsCreativeXFi();
bool const float32_capable = palIsExtensionPresent("AL_EXT_float32") != 0;
bool const surround_capable = palIsExtensionPresent("AL_EXT_MCFORMATS") || IsCreativeXFi();
bool use_surround = Config::ShouldUseDPL2Decoder() && surround_capable;
// As there is no extension to check for 32-bit fixed point support
// and we know that only a X-Fi with hardware OpenAL supports it,
// we just check if one is being used.
bool fixed32_capable = IsCreativeXFi();
bool const fixed32_capable = IsCreativeXFi();
u32 frequency = m_mixer->GetSampleRate();
u32 const frequency = m_mixer->GetSampleRate();
u32 frames_per_buffer;
// Can't have zero samples per buffer
@ -288,12 +288,12 @@ void OpenALStream::SoundLoop()
num_buffers_queued -= num_buffers_processed;
}
unsigned int min_frames = frames_per_buffer;
unsigned int const min_frames = frames_per_buffer;
if (use_surround)
{
std::array<float, OAL_MAX_FRAMES * SURROUND_CHANNELS> dpl2;
u32 rendered_frames = static_cast<u32>(m_mixer->MixSurround(dpl2.data(), min_frames));
u32 const rendered_frames = static_cast<u32>(m_mixer->MixSurround(dpl2.data(), min_frames));
if (rendered_frames < min_frames)
continue;
@ -351,7 +351,8 @@ void OpenALStream::SoundLoop()
}
else
{
u32 rendered_frames = static_cast<u32>(m_mixer->Mix(m_realtime_buffer.data(), min_frames));
u32 const rendered_frames =
static_cast<u32>(m_mixer->Mix(m_realtime_buffer.data(), min_frames));
if (!rendered_frames)
continue;

View File

@ -7,9 +7,6 @@
#include "AudioCommon/SoundStream.h"
#include "Common/Event.h"
#include "Core/Core.h"
#include "Core/HW/AudioInterface.h"
#include "Core/HW/SystemTimers.h"
#ifdef _WIN32
#include <al.h>

View File

@ -8,7 +8,6 @@
#endif
#include "AudioCommon/SoundStream.h"
#include "Common/CommonTypes.h"
#include "Common/Flag.h"
#include "Common/Thread.h"

View File

@ -32,7 +32,7 @@ size_t SurroundDecoder::QueryFramesNeededForSurroundOutput(const size_t output_f
if (m_decoded_fifo.size() < output_frames * SURROUND_CHANNELS)
{
// Output stereo frames needed to have at least the desired number of surround frames
size_t frames_needed = output_frames - m_decoded_fifo.size() / SURROUND_CHANNELS;
size_t const frames_needed = output_frames - m_decoded_fifo.size() / SURROUND_CHANNELS;
return frames_needed + m_frame_block_size - frames_needed % m_frame_block_size;
}

View File

@ -8,7 +8,6 @@
// clang-format off
#include <Audioclient.h>
#include <mmdeviceapi.h>
#include <devpkey.h>
#include <functiondiscoverykeys_devpkey.h>
#include <wil/resource.h>
// clang-format on
@ -159,8 +158,9 @@ ComPtr<IMMDevice> WASAPIStream::GetDeviceByName(std::string_view name)
bool WASAPIStream::Init()
{
ASSERT(m_enumerator == nullptr);
HRESULT result = CoCreateInstance(__uuidof(MMDeviceEnumerator), nullptr, CLSCTX_INPROC_SERVER,
IID_PPV_ARGS(m_enumerator.GetAddressOf()));
HRESULT const result =
CoCreateInstance(__uuidof(MMDeviceEnumerator), nullptr, CLSCTX_INPROC_SERVER,
IID_PPV_ARGS(m_enumerator.GetAddressOf()));
if (!HandleWinAPI("Failed to create MMDeviceEnumerator", result))
return false;

View File

@ -32,7 +32,7 @@ class WASAPIStream final : public SoundStream
#ifdef _WIN32
public:
explicit WASAPIStream();
~WASAPIStream();
~WASAPIStream() override;
bool Init() override;
bool SetRunning(bool running) override;

View File

@ -31,7 +31,7 @@ public:
{
m_active_block = &m_output_result.blocks.emplace_back(base_addr);
}
virtual ~GekkoIRPlugin() = default;
~GekkoIRPlugin() override = default;
void OnDirectivePre(GekkoDirective directive) override;
void OnDirectivePost(GekkoDirective directive) override;

View File

@ -64,6 +64,8 @@ add_library(common
FatFsUtil.h
FileSearch.cpp
FileSearch.h
FilesystemWatcher.cpp
FilesystemWatcher.h
FileUtil.cpp
FileUtil.h
FixedSizeQueue.h
@ -184,6 +186,7 @@ PRIVATE
FatFs
Iconv::Iconv
spng::spng
watcher
${VTUNE_LIBRARIES}
)

View File

@ -46,8 +46,7 @@ public:
ASSERT(!mbedtls_aes_setkey_dec(&ctx, key, 128));
}
virtual bool Crypt(const u8* iv, u8* iv_out, const u8* buf_in, u8* buf_out,
size_t len) const override
bool Crypt(const u8* iv, u8* iv_out, const u8* buf_in, u8* buf_out, size_t len) const override
{
std::array<u8, BLOCK_SIZE> iv_tmp{};
if (iv)
@ -206,8 +205,7 @@ public:
_mm_storeu_si128(&((__m128i*)buf_out)[d], block[d]);
}
virtual bool Crypt(const u8* iv, u8* iv_out, const u8* buf_in, u8* buf_out,
size_t len) const override
bool Crypt(const u8* iv, u8* iv_out, const u8* buf_in, u8* buf_out, size_t len) const override
{
if (len % BLOCK_SIZE)
return false;

View File

@ -41,18 +41,18 @@ public:
mbedtls_sha1_init(&ctx);
ASSERT(!mbedtls_sha1_starts_ret(&ctx));
}
~ContextMbed() { mbedtls_sha1_free(&ctx); }
virtual void Update(const u8* msg, size_t len) override
~ContextMbed() override { mbedtls_sha1_free(&ctx); }
void Update(const u8* msg, size_t len) override
{
ASSERT(!mbedtls_sha1_update_ret(&ctx, msg, len));
}
virtual Digest Finish() override
Digest Finish() override
{
Digest digest;
ASSERT(!mbedtls_sha1_finish_ret(&ctx, digest.data()));
return digest;
}
virtual bool HwAccelerated() const override { return false; }
bool HwAccelerated() const override { return false; }
private:
mbedtls_sha1_context ctx{};
@ -204,7 +204,7 @@ private:
}
ATTRIBUTE_TARGET("sha")
virtual void ProcessBlock(const u8* msg) override
void ProcessBlock(const u8* msg) override
{
// There are 80 rounds with 4 bytes per round, giving 0x140 byte work space, but we can keep
// active state in just 0x40 bytes.
@ -248,7 +248,7 @@ private:
// clang-format on
}
virtual Digest GetDigest() override
Digest GetDigest() override
{
Digest digest;
_mm_storeu_si128((__m128i*)&digest[0], byterev_16B(state[0]));
@ -257,7 +257,7 @@ private:
return digest;
}
virtual bool HwAccelerated() const override { return true; }
bool HwAccelerated() const override { return true; }
std::array<XmmReg, 2> state{};
};

View File

@ -0,0 +1,67 @@
// Copyright 2025 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "Common/FilesystemWatcher.h"
#include <wtr/watcher.hpp>
#include "Common/Logging/Log.h"
#include "Common/StringUtil.h"
namespace Common
{
FilesystemWatcher::FilesystemWatcher() = default;
FilesystemWatcher::~FilesystemWatcher() = default;
void FilesystemWatcher::Watch(const std::string& path)
{
const auto [iter, inserted] = m_watched_paths.try_emplace(path, nullptr);
if (inserted)
{
iter->second = std::make_unique<wtr::watch>(path, [this](wtr::event e) {
const auto watched_path = PathToString(e.path_name);
if (e.path_type == wtr::event::path_type::watcher)
{
if (watched_path.starts_with('e'))
ERROR_LOG_FMT(COMMON, "Filesystem watcher: '{}'", watched_path);
else if (watched_path.starts_with('w'))
WARN_LOG_FMT(COMMON, "Filesystem watcher: '{}'", watched_path);
return;
}
if (e.effect_type == wtr::event::effect_type::create)
{
const auto path = WithUnifiedPathSeparators(watched_path);
PathAdded(path);
}
else if (e.effect_type == wtr::event::effect_type::modify)
{
const auto path = WithUnifiedPathSeparators(watched_path);
PathModified(path);
}
else if (e.effect_type == wtr::event::effect_type::rename)
{
if (!e.associated)
{
WARN_LOG_FMT(COMMON, "Rename on path '{}' seen without association!", watched_path);
return;
}
const auto old_path = WithUnifiedPathSeparators(watched_path);
const auto new_path = WithUnifiedPathSeparators(PathToString(e.associated->path_name));
PathRenamed(old_path, new_path);
}
else if (e.effect_type == wtr::event::effect_type::destroy)
{
const auto path = WithUnifiedPathSeparators(watched_path);
PathDeleted(path);
}
});
}
}
void FilesystemWatcher::Unwatch(const std::string& path)
{
m_watched_paths.erase(path);
}
} // namespace Common

View File

@ -0,0 +1,47 @@
// Copyright 2025 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <map>
#include <memory>
#include <string>
#include <string_view>
namespace wtr
{
inline namespace watcher
{
class watch;
}
} // namespace wtr
namespace Common
{
// A class that can watch a path and receive callbacks
// when files or directories underneath that path receive events
class FilesystemWatcher
{
public:
FilesystemWatcher();
virtual ~FilesystemWatcher();
void Watch(const std::string& path);
void Unwatch(const std::string& path);
private:
// A new file or folder was added to one of the watched paths
virtual void PathAdded(std::string_view path) {}
// A file or folder was modified in one of the watched paths
virtual void PathModified(std::string_view path) {}
// A file or folder was renamed in one of the watched paths
virtual void PathRenamed(std::string_view old_path, std::string_view new_path) {}
// A file or folder was deleted in one of the watched paths
virtual void PathDeleted(std::string_view path) {}
std::map<std::string, std::unique_ptr<wtr::watch>> m_watched_paths;
};
} // namespace Common

View File

@ -10,9 +10,9 @@
class GLContextWGL final : public GLContext
{
public:
~GLContextWGL();
~GLContextWGL() override;
bool IsHeadless() const;
bool IsHeadless() const override;
std::unique_ptr<GLContext> CreateSharedContext() override;

View File

@ -101,7 +101,7 @@ class HostDisassemblerBochs final : public HostDisassembler
{
public:
explicit HostDisassemblerBochs();
~HostDisassemblerBochs() = default;
~HostDisassemblerBochs() override = default;
private:
disassembler m_disasm;

View File

@ -9,7 +9,7 @@ class ConsoleListener : public Common::Log::LogListener
{
public:
ConsoleListener();
~ConsoleListener();
~ConsoleListener() override;
void Log(Common::Log::LogLevel level, const char* text) override;

View File

@ -20,7 +20,7 @@ public:
explicit DolReader(const std::string& filename);
explicit DolReader(File::IOFile file);
explicit DolReader(std::vector<u8> buffer);
~DolReader();
~DolReader() override;
bool IsValid() const override { return m_is_valid; }
bool IsWii() const override { return m_is_wii; }

View File

@ -28,7 +28,7 @@ public:
explicit ElfReader(const std::string& filename);
explicit ElfReader(File::IOFile file);
explicit ElfReader(std::vector<u8> buffer);
~ElfReader();
~ElfReader() override;
u32 Read32(int off) const { return base32[off >> 2]; }
// Quick accessors
ElfType GetType() const { return (ElfType)(header->e_type); }

View File

@ -483,6 +483,9 @@ add_library(core
NetworkCaptureLogger.h
PatchEngine.cpp
PatchEngine.h
PerformanceSample.h
PerformanceSampleAggregator.cpp
PerformanceSampleAggregator.h
PowerPC/BreakPoints.cpp
PowerPC/BreakPoints.h
PowerPC/CachedInterpreter/CachedInterpreter_Disassembler.cpp

View File

@ -45,6 +45,7 @@ const Info<bool> MAIN_ACCURATE_CPU_CACHE{{System::Main, "Core", "AccurateCPUCach
const Info<bool> MAIN_DSP_HLE{{System::Main, "Core", "DSPHLE"}, true};
const Info<int> MAIN_MAX_FALLBACK{{System::Main, "Core", "MaxFallback"}, 100};
const Info<int> MAIN_TIMING_VARIANCE{{System::Main, "Core", "TimingVariance"}, 40};
const Info<bool> MAIN_CORRECT_TIME_DRIFT{{System::Main, "Core", "CorrectTimeDrift"}, false};
const Info<bool> MAIN_CPU_THREAD{{System::Main, "Core", "CPUThread"}, true};
const Info<bool> MAIN_SYNC_ON_SKIP_IDLE{{System::Main, "Core", "SyncOnSkipIdle"}, true};
const Info<std::string> MAIN_DEFAULT_ISO{{System::Main, "Core", "DefaultISO"}, ""};

View File

@ -63,6 +63,7 @@ extern const Info<bool> MAIN_ACCURATE_CPU_CACHE;
extern const Info<bool> MAIN_DSP_HLE;
extern const Info<int> MAIN_MAX_FALLBACK;
extern const Info<int> MAIN_TIMING_VARIANCE;
extern const Info<bool> MAIN_CORRECT_TIME_DRIFT;
extern const Info<bool> MAIN_CPU_THREAD;
extern const Info<bool> MAIN_SYNC_ON_SKIP_IDLE;
extern const Info<std::string> MAIN_DEFAULT_ISO;

View File

@ -82,7 +82,6 @@
#include "InputCommon/ControllerInterface/ControllerInterface.h"
#include "InputCommon/GCAdapter.h"
#include "VideoCommon/Assets/CustomAssetLoader.h"
#include "VideoCommon/AsyncRequests.h"
#include "VideoCommon/Fifo.h"
#include "VideoCommon/FrameDumper.h"
@ -528,9 +527,6 @@ static void EmuThread(Core::System& system, std::unique_ptr<BootParameters> boot
FreeLook::LoadInputConfig();
system.GetCustomAssetLoader().Init();
Common::ScopeGuard asset_loader_guard([&system] { system.GetCustomAssetLoader().Shutdown(); });
system.GetMovie().Init(*boot);
Common::ScopeGuard movie_guard([&system] { system.GetMovie().Shutdown(); });

View File

@ -105,10 +105,20 @@ void CoreTimingManager::Init()
m_last_oc_factor = m_config_oc_factor;
m_globals.last_OC_factor_inverted = m_config_oc_inv_factor;
m_on_state_changed_handle = Core::AddOnStateChangedCallback([this](Core::State state) {
if (state == Core::State::Running)
{
// We don't want Throttle to attempt catch-up for all the time lost while paused.
ResetThrottle(GetTicks());
}
});
}
void CoreTimingManager::Shutdown()
{
Core::RemoveOnStateChangedCallback(&m_on_state_changed_handle);
std::lock_guard lk(m_ts_write_lock);
MoveEvents();
ClearPendingEvents();
@ -131,6 +141,8 @@ void CoreTimingManager::RefreshConfig()
m_max_variance = std::chrono::duration_cast<DT>(DT_ms(Config::Get(Config::MAIN_TIMING_VARIANCE)));
m_correct_time_drift = Config::Get(Config::MAIN_CORRECT_TIME_DRIFT);
if (AchievementManager::GetInstance().IsHardcoreModeActive() &&
Config::Get(Config::MAIN_EMULATION_SPEED) < 1.0f &&
Config::Get(Config::MAIN_EMULATION_SPEED) > 0.0f)
@ -428,7 +440,9 @@ void CoreTimingManager::Throttle(const s64 target_cycle)
const TimePoint time = Clock::now();
const TimePoint min_target = time - m_max_fallback;
if (target_time < min_target)
// "Correct Time Drift" setting prevents timing relaxing.
if (!m_correct_time_drift && target_time < min_target)
{
// Core is running too slow.. i.e. CPU bottleneck.
const DT adjustment = min_target - target_time;

View File

@ -211,6 +211,7 @@ private:
DT m_max_fallback = {};
DT m_max_variance = {};
bool m_correct_time_drift = false;
double m_emulation_speed = 1.0;
bool IsSpeedUnlimited() const;
@ -225,6 +226,8 @@ private:
std::atomic_bool m_use_precision_timer = false;
Common::PrecisionTimer m_precision_cpu_timer;
Common::PrecisionTimer m_precision_gpu_timer;
int m_on_state_changed_handle;
};
} // namespace CoreTiming

View File

@ -132,7 +132,7 @@ class OSThreadView : public Common::Debug::ThreadView
{
public:
explicit OSThreadView(const Core::CPUThreadGuard& guard, u32 addr);
~OSThreadView() = default;
~OSThreadView() override = default;
const OSThread& Data() const;

View File

@ -7,7 +7,6 @@
#include <memory>
#include <mutex>
#include <string>
#include <vector>
#include <fmt/format.h>
@ -17,7 +16,6 @@
#elif defined(__APPLE__)
#include <objc/message.h>
#elif defined(ANDROID)
#include <functional>
#include "Common/AndroidAnalytics.h"
#endif
@ -28,24 +26,21 @@
#include "Common/Crypto/SHA1.h"
#include "Common/EnumUtils.h"
#include "Common/Random.h"
#include "Common/Timer.h"
#include "Common/Version.h"
#include "Core/Config/MainSettings.h"
#include "Core/ConfigManager.h"
#include "Core/HW/GCPad.h"
#include "Core/Movie.h"
#include "Core/NetPlayProto.h"
#include "Core/System.h"
#include "InputCommon/GCAdapter.h"
#include "InputCommon/InputConfig.h"
#include "VideoCommon/VideoBackendBase.h"
#include "VideoCommon/VideoConfig.h"
namespace
{
constexpr char ANALYTICS_ENDPOINT[] = "https://analytics.dolphin-emu.org/report";
} // namespace
#if defined(ANDROID)
static std::function<std::string(std::string)> s_get_val_func;
void DolphinAnalytics::AndroidSetGetValFunc(std::function<std::string(std::string)> func)
@ -54,6 +49,100 @@ void DolphinAnalytics::AndroidSetGetValFunc(std::function<std::string(std::strin
}
#endif
namespace
{
void AddVersionInformationToReportBuilder(Common::AnalyticsReportBuilder* builder)
{
builder->AddData("version-desc", Common::GetScmDescStr());
builder->AddData("version-hash", Common::GetScmRevGitStr());
builder->AddData("version-branch", Common::GetScmBranchStr());
builder->AddData("version-dist", Common::GetScmDistributorStr());
}
void AddAutoUpdateInformationToReportBuilder(Common::AnalyticsReportBuilder* builder)
{
builder->AddData("update-track", Config::Get(Config::MAIN_AUTOUPDATE_UPDATE_TRACK));
}
void AddCPUInformationToReportBuilder(Common::AnalyticsReportBuilder* builder)
{
builder->AddData("cpu-summary", cpu_info.Summarize());
}
#if defined(_WIN32)
void AddWindowsInformationToReportBuilder(Common::AnalyticsReportBuilder* builder)
{
const auto winver = WindowsRegistry::GetOSVersion();
builder->AddData("win-ver-major", static_cast<u32>(winver.dwMajorVersion));
builder->AddData("win-ver-minor", static_cast<u32>(winver.dwMinorVersion));
builder->AddData("win-ver-build", static_cast<u32>(winver.dwBuildNumber));
}
#elif defined(ANDROID)
void AddAndroidInformationToReportBuilder(Common::AnalyticsReportBuilder* builder)
{
builder->AddData("android-manufacturer", s_get_val_func("DEVICE_MANUFACTURER"));
builder->AddData("android-model", s_get_val_func("DEVICE_MODEL"));
builder->AddData("android-version", s_get_val_func("DEVICE_OS"));
}
#elif defined(__APPLE__)
void AddMacOSInformationToReportBuilder(Common::AnalyticsReportBuilder* builder)
{
// id processInfo = [NSProcessInfo processInfo]
id processInfo = reinterpret_cast<id (*)(Class, SEL)>(objc_msgSend)(
objc_getClass("NSProcessInfo"), sel_getUid("processInfo"));
if (processInfo)
{
struct OSVersion // NSOperatingSystemVersion
{
s64 major_version; // NSInteger majorVersion
s64 minor_version; // NSInteger minorVersion
s64 patch_version; // NSInteger patchVersion
};
// On x86_64, we need to explicitly call objc_msgSend_stret for a struct.
#ifdef _M_ARM_64
#define msgSend objc_msgSend
#else
#define msgSend objc_msgSend_stret
#endif
// NSOperatingSystemVersion version = [processInfo operatingSystemVersion]
OSVersion version = reinterpret_cast<OSVersion (*)(id, SEL)>(msgSend)(
processInfo, sel_getUid("operatingSystemVersion"));
#undef msgSend
builder->AddData("osx-ver-major", version.major_version);
builder->AddData("osx-ver-minor", version.minor_version);
builder->AddData("osx-ver-bugfix", version.patch_version);
}
}
#endif
void AddPlatformInformationToReportBuilder(Common::AnalyticsReportBuilder* builder)
{
#if defined(_WIN32)
builder->AddData("os-type", "windows");
AddWindowsInformationToReportBuilder(builder);
#elif defined(ANDROID)
builder->AddData("os-type", "android");
AddAndroidInformationToReportBuilder(builder);
#elif defined(__APPLE__)
builder->AddData("os-type", "osx");
AddMacOSInformationToReportBuilder(builder);
#elif defined(__linux__)
builder->AddData("os-type", "linux");
#elif defined(__FreeBSD__)
builder->AddData("os-type", "freebsd");
#elif defined(__OpenBSD__)
builder->AddData("os-type", "openbsd");
#elif defined(__NetBSD__)
builder->AddData("os-type", "netbsd");
#elif defined(__HAIKU__)
builder->AddData("os-type", "haiku");
#else
builder->AddData("os-type", "unknown");
#endif
}
} // namespace
// Under arm64, we need to call objc_msgSend to receive a struct.
DolphinAnalytics::DolphinAnalytics()
{
ReloadConfig();
@ -68,16 +157,17 @@ DolphinAnalytics& DolphinAnalytics::Instance()
void DolphinAnalytics::ReloadConfig()
{
std::lock_guard lk{m_reporter_mutex};
const std::lock_guard lk{m_reporter_mutex};
// Install the HTTP backend if analytics support is enabled.
std::unique_ptr<Common::AnalyticsReportingBackend> new_backend;
if (Config::Get(Config::MAIN_ANALYTICS_ENABLED))
{
constexpr char analytics_endpoint[] = "https://analytics.dolphin-emu.org/report";
#if defined(ANDROID)
new_backend = std::make_unique<Common::AndroidAnalyticsBackend>(ANALYTICS_ENDPOINT);
new_backend = std::make_unique<Common::AndroidAnalyticsBackend>(analytics_endpoint);
#else
new_backend = std::make_unique<Common::HttpAnalyticsBackend>(ANALYTICS_ENDPOINT);
new_backend = std::make_unique<Common::HttpAnalyticsBackend>(analytics_endpoint);
#endif
}
m_reporter.SetBackend(std::move(new_backend));
@ -134,7 +224,7 @@ void DolphinAnalytics::ReportGameStart()
// Reset per-game state.
m_reported_quirks.fill(false);
InitializePerformanceSampling();
m_sample_aggregator.InitializePerformanceSampling();
}
// Keep in sync with enum class GameQuirk definition.
@ -173,12 +263,12 @@ constexpr std::array GAME_QUIRKS_NAMES{
"invalid-texture-coordinate-component-format",
"invalid-color-component-format",
};
static_assert(GAME_QUIRKS_NAMES.size() == static_cast<u32>(GameQuirk::COUNT),
static_assert(GAME_QUIRKS_NAMES.size() == static_cast<u32>(GameQuirk::Count),
"Game quirks names and enum definition are out of sync.");
void DolphinAnalytics::ReportGameQuirk(GameQuirk quirk)
{
u32 quirk_idx = static_cast<u32>(quirk);
const u32 quirk_idx = static_cast<u32>(quirk);
// Only report once per run.
if (m_reported_quirks[quirk_idx])
@ -193,140 +283,34 @@ void DolphinAnalytics::ReportGameQuirk(GameQuirk quirk)
void DolphinAnalytics::ReportPerformanceInfo(PerformanceSample&& sample)
{
if (ShouldStartPerformanceSampling())
m_sample_aggregator.AddSampleIfSamplingInProgress(std::move(sample));
const std::optional<PerformanceSampleAggregator::CompletedReport> report_optional =
m_sample_aggregator.PopReportIfComplete();
if (!report_optional)
{
m_sampling_performance_info = true;
return;
}
const PerformanceSampleAggregator::CompletedReport& report = *report_optional;
if (m_sampling_performance_info)
{
m_performance_samples.emplace_back(std::move(sample));
}
// The per game builder should already exist -- there is no way we can be reporting performance
// info without a game start event having been generated.
Common::AnalyticsReportBuilder builder(m_per_game_builder);
builder.AddData("type", "performance");
builder.AddData("speed", report.speed);
builder.AddData("prims", report.primitives);
builder.AddData("draw-calls", report.draw_calls);
if (m_performance_samples.size() >= NUM_PERFORMANCE_SAMPLES_PER_REPORT)
{
std::vector<u32> speed_times_1000(m_performance_samples.size());
std::vector<u32> num_prims(m_performance_samples.size());
std::vector<u32> num_draw_calls(m_performance_samples.size());
for (size_t i = 0; i < m_performance_samples.size(); ++i)
{
speed_times_1000[i] = static_cast<u32>(m_performance_samples[i].speed_ratio * 1000);
num_prims[i] = m_performance_samples[i].num_prims;
num_draw_calls[i] = m_performance_samples[i].num_draw_calls;
}
// The per game builder should already exist -- there is no way we can be reporting performance
// info without a game start event having been generated.
Common::AnalyticsReportBuilder builder(m_per_game_builder);
builder.AddData("type", "performance");
builder.AddData("speed", speed_times_1000);
builder.AddData("prims", num_prims);
builder.AddData("draw-calls", num_draw_calls);
Send(builder);
// Clear up and stop sampling until next time ShouldStartPerformanceSampling() says so.
m_performance_samples.clear();
m_sampling_performance_info = false;
}
}
void DolphinAnalytics::InitializePerformanceSampling()
{
m_performance_samples.clear();
m_sampling_performance_info = false;
u64 wait_us =
PERFORMANCE_SAMPLING_INITIAL_WAIT_TIME_SECS * 1000000 +
Common::Random::GenerateValue<u64>() % (PERFORMANCE_SAMPLING_WAIT_TIME_JITTER_SECS * 1000000);
m_sampling_next_start_us = Common::Timer::NowUs() + wait_us;
}
bool DolphinAnalytics::ShouldStartPerformanceSampling()
{
if (Common::Timer::NowUs() < m_sampling_next_start_us)
return false;
u64 wait_us =
PERFORMANCE_SAMPLING_INTERVAL_SECS * 1000000 +
Common::Random::GenerateValue<u64>() % (PERFORMANCE_SAMPLING_WAIT_TIME_JITTER_SECS * 1000000);
m_sampling_next_start_us = Common::Timer::NowUs() + wait_us;
return true;
Send(builder);
}
void DolphinAnalytics::MakeBaseBuilder()
{
Common::AnalyticsReportBuilder builder;
m_base_builder = Common::AnalyticsReportBuilder();
// Version information.
builder.AddData("version-desc", Common::GetScmDescStr());
builder.AddData("version-hash", Common::GetScmRevGitStr());
builder.AddData("version-branch", Common::GetScmBranchStr());
builder.AddData("version-dist", Common::GetScmDistributorStr());
// Auto-Update information.
builder.AddData("update-track", Config::Get(Config::MAIN_AUTOUPDATE_UPDATE_TRACK));
// CPU information.
builder.AddData("cpu-summary", cpu_info.Summarize());
// OS information.
#if defined(_WIN32)
builder.AddData("os-type", "windows");
const auto winver = WindowsRegistry::GetOSVersion();
builder.AddData("win-ver-major", static_cast<u32>(winver.dwMajorVersion));
builder.AddData("win-ver-minor", static_cast<u32>(winver.dwMinorVersion));
builder.AddData("win-ver-build", static_cast<u32>(winver.dwBuildNumber));
#elif defined(ANDROID)
builder.AddData("os-type", "android");
builder.AddData("android-manufacturer", s_get_val_func("DEVICE_MANUFACTURER"));
builder.AddData("android-model", s_get_val_func("DEVICE_MODEL"));
builder.AddData("android-version", s_get_val_func("DEVICE_OS"));
#elif defined(__APPLE__)
builder.AddData("os-type", "osx");
// id processInfo = [NSProcessInfo processInfo]
id processInfo = reinterpret_cast<id (*)(Class, SEL)>(objc_msgSend)(
objc_getClass("NSProcessInfo"), sel_getUid("processInfo"));
if (processInfo)
{
struct OSVersion // NSOperatingSystemVersion
{
s64 major_version; // NSInteger majorVersion
s64 minor_version; // NSInteger minorVersion
s64 patch_version; // NSInteger patchVersion
};
// Under arm64, we need to call objc_msgSend to receive a struct.
// On x86_64, we need to explicitly call objc_msgSend_stret for a struct.
#ifdef _M_ARM_64
#define msgSend objc_msgSend
#else
#define msgSend objc_msgSend_stret
#endif
// NSOperatingSystemVersion version = [processInfo operatingSystemVersion]
OSVersion version = reinterpret_cast<OSVersion (*)(id, SEL)>(msgSend)(
processInfo, sel_getUid("operatingSystemVersion"));
#undef msgSend
builder.AddData("osx-ver-major", version.major_version);
builder.AddData("osx-ver-minor", version.minor_version);
builder.AddData("osx-ver-bugfix", version.patch_version);
}
#elif defined(__linux__)
builder.AddData("os-type", "linux");
#elif defined(__FreeBSD__)
builder.AddData("os-type", "freebsd");
#elif defined(__OpenBSD__)
builder.AddData("os-type", "openbsd");
#elif defined(__NetBSD__)
builder.AddData("os-type", "netbsd");
#elif defined(__HAIKU__)
builder.AddData("os-type", "haiku");
#else
builder.AddData("os-type", "unknown");
#endif
m_base_builder = builder;
AddVersionInformationToReportBuilder(&m_base_builder);
AddAutoUpdateInformationToReportBuilder(&m_base_builder);
AddCPUInformationToReportBuilder(&m_base_builder);
AddPlatformInformationToReportBuilder(&m_base_builder);
}
static const char* GetShaderCompilationMode(const VideoConfig& video_config)
@ -348,12 +332,13 @@ static const char* GetShaderCompilationMode(const VideoConfig& video_config)
void DolphinAnalytics::MakePerGameBuilder()
{
Common::AnalyticsReportBuilder builder(m_base_builder);
const SConfig& config = SConfig::GetInstance();
// Gameid.
builder.AddData("gameid", SConfig::GetInstance().GetGameID());
builder.AddData("gameid", config.GetGameID());
// Unique id bound to the gameid.
builder.AddData("id", MakeUniqueId(SConfig::GetInstance().GetGameID()));
builder.AddData("id", MakeUniqueId(config.GetGameID()));
// Configuration.
builder.AddData("cfg-dsp-hle", Config::Get(Config::MAIN_DSP_HLE));

View File

@ -7,10 +7,11 @@
#include <mutex>
#include <string>
#include <string_view>
#include <vector>
#include "Common/Analytics.h"
#include "Common/CommonTypes.h"
#include "Core/PerformanceSample.h"
#include "Core/PerformanceSampleAggregator.h"
#if defined(ANDROID)
#include <functional>
@ -21,86 +22,86 @@
enum class GameQuirk
{
// Several Wii DI commands that are rarely/never used and not implemented by Dolphin
USES_DVD_LOW_STOP_LASER,
USES_DVD_LOW_OFFSET,
USES_DVD_LOW_READ_DISK_BCA, // NSMBW known to use this
USES_DVD_LOW_REQUEST_DISC_STATUS,
USES_DVD_LOW_REQUEST_RETRY_NUMBER,
USES_DVD_LOW_SER_MEAS_CONTROL,
UsesDVDLowStopLaser,
UsesDVDLowOffset,
UsesDVDLowReadDiskBCA, // NSMBW known to use this
UsesDVDLowRequestDiscStatus,
UsesDVDLowRequestRetryNumber,
UsesDVDLowSerMeasControl,
// Dolphin only implements the simple DVDLowOpenPartition, not any of the variants where some
// already-read data is provided
USES_DIFFERENT_PARTITION_COMMAND,
UsesDifferentPartitionCommand,
// IOS has implementations for ioctls 0x85 and 0x89 and a stub for 0x87, but
// DVDLowMaskCoverInterrupt/DVDLowUnmaskCoverInterrupt/DVDLowUnmaskStatusInterrupts
// are all stubbed on the PPC side so they presumably will never be used.
// (DVDLowClearCoverInterrupt is used, though)
USES_DI_INTERRUPT_MASK_COMMAND,
UsesDIInterruptMaskCommand,
// Some games configure a mismatched number of texture coordinates or colors between the transform
// and TEV/BP stages of the rendering pipeline. Currently, Dolphin just skips over these objects
// as the hardware renderers are not equipped to handle the case where the registers between
// stages are mismatched.
MISMATCHED_GPU_TEXGENS_BETWEEN_XF_AND_BP,
MISMATCHED_GPU_COLORS_BETWEEN_XF_AND_BP,
MismatchedGPUTexgensBetweenXFAndBP,
MismatchedGPUColorsBetweenXFAndBP,
// The WD module can be configured to operate in six different modes.
// In practice, only mode 1 (DS communications) and mode 3 (AOSS access point scanning)
// are used by games and the system menu respectively.
USES_UNCOMMON_WD_MODE,
UsesUncommonWDMode,
USES_WD_UNIMPLEMENTED_IOCTL,
UsesWDUnimplementedIoctl,
// Some games use invalid/unknown graphics commands (see e.g. bug 10931).
// These are different from unknown opcodes: it is known that a BP/CP/XF command is being used,
// but the command itself is not understood.
USES_UNKNOWN_BP_COMMAND,
USES_UNKNOWN_CP_COMMAND,
USES_UNKNOWN_XF_COMMAND,
UsesUnknownBPCommand,
UsesUnknownCPCommand,
UsesUnknownXFCommand,
// YAGCD and Dolphin's implementation disagree about what is valid in some cases
USES_MAYBE_INVALID_CP_COMMAND,
UsesMaybeInvalidCPCommand,
// These commands are used by a few games (e.g. bug 12461), and seem to relate to perf queries.
// Track them separately.
USES_CP_PERF_COMMAND,
UsesCPPerfCommand,
// We don't implement all AX features yet.
USES_UNIMPLEMENTED_AX_COMMAND,
USES_AX_INITIAL_TIME_DELAY,
USES_AX_WIIMOTE_LOWPASS,
USES_AX_WIIMOTE_BIQUAD,
UsesUnimplementedAXCommand,
UsesAXInitialTimeDelay,
UsesAXWiimoteLowpass,
UsesAXWiimoteBiquad,
// We don't implement XFMEM_CLIPDISABLE yet.
SETS_XF_CLIPDISABLE_BIT_0,
SETS_XF_CLIPDISABLE_BIT_1,
SETS_XF_CLIPDISABLE_BIT_2,
SetsXFClipdisableBit0,
SetsXFClipdisableBit1,
SetsXFClipdisableBit2,
// Similar to the XF-BP mismatch, CP and XF might be configured with different vertex formats.
// Real hardware seems to hang in this case, so games probably don't do this, but it would
// be good to know if anything does it.
MISMATCHED_GPU_COLORS_BETWEEN_CP_AND_XF,
MISMATCHED_GPU_NORMALS_BETWEEN_CP_AND_XF,
MISMATCHED_GPU_TEX_COORDS_BETWEEN_CP_AND_XF,
MismatchedGPUColorsBetweenCPAndXF,
MismatchedGPUNormalsBetweenCPAndXF,
MismatchedGPUTexCoordsBetweenCPAndXF,
// Both CP and XF have normally-identical matrix index information. We currently always
// use the CP one in the hardware renderers and the XF one in the software renderer,
// but testing is needed to find out which of these is actually used for what.
MISMATCHED_GPU_MATRIX_INDICES_BETWEEN_CP_AND_XF,
MismatchedGPUMatrixIndicesBetweenCPAndXF,
// Only a few games use the Bounding Box feature. Note that every game initializes the bounding
// box registers (using BPMEM_CLEARBBOX1/BPMEM_CLEARBBOX2) on startup, as part of the SDK, but
// only a few read them (from PE_BBOX_LEFT etc.)
READS_BOUNDING_BOX,
ReadsBoundingBox,
// A few games use invalid vertex component formats, but the two known cases (Fifa Street and
// Def Jam: Fight for New York, see https://bugs.dolphin-emu.org/issues/12719) only use invalid
// normal formats and lighting is disabled in those cases, so it doesn't end up mattering.
// It's possible other games use invalid formats, possibly on other vertex components.
INVALID_POSITION_COMPONENT_FORMAT,
INVALID_NORMAL_COMPONENT_FORMAT,
INVALID_TEXTURE_COORDINATE_COMPONENT_FORMAT,
INVALID_COLOR_COMPONENT_FORMAT,
InvalidPositionComponentFormat,
InvalidNormalComponentFormat,
InvalidTextureCoordinateComponentFormat,
InvalidColorComponentFormat,
COUNT,
Count,
};
class DolphinAnalytics
@ -134,14 +135,12 @@ public:
// Get the base builder for building a report
const Common::AnalyticsReportBuilder& BaseBuilder() const { return m_base_builder; }
struct PerformanceSample
{
double speed_ratio; // See SystemTimers::GetEstimatedEmulationPerformance().
int num_prims;
int num_draw_calls;
};
// Reports performance information. This method performs its own throttling / aggregation --
// calling it does not guarantee when a report will actually be sent.
// Performance reports are generated using data from 100 consecutive frames.
// Report starting times are randomized to obtain a wider range of sample data.
// The first report begins 5-8 minutes after a game is launched.
// Successive reports begin 30-33 minutes after the previous report finishes.
//
// This method is NOT thread-safe.
void ReportPerformanceInfo(PerformanceSample&& sample);
@ -169,24 +168,10 @@ private:
// values created by MakeUniqueId.
std::string m_unique_id;
// Performance sampling configuration constants.
//
// 5min after startup + rand(0, 3min) jitter time, collect performance for 100 frames in a row.
// Repeat collection after 30min + rand(0, 3min).
static constexpr int NUM_PERFORMANCE_SAMPLES_PER_REPORT = 100;
static constexpr int PERFORMANCE_SAMPLING_INITIAL_WAIT_TIME_SECS = 300;
static constexpr int PERFORMANCE_SAMPLING_WAIT_TIME_JITTER_SECS = 180;
static constexpr int PERFORMANCE_SAMPLING_INTERVAL_SECS = 1800;
// Performance sampling state & internal helpers.
void InitializePerformanceSampling(); // Called on game start / title switch.
bool ShouldStartPerformanceSampling();
u64 m_sampling_next_start_us; // Next timestamp (in us) at which to trigger sampling.
bool m_sampling_performance_info = false; // Whether we are currently collecting samples.
std::vector<PerformanceSample> m_performance_samples;
PerformanceSampleAggregator m_sample_aggregator;
// What quirks have already been reported about the current game.
std::array<bool, static_cast<size_t>(GameQuirk::COUNT)> m_reported_quirks;
std::array<bool, static_cast<size_t>(GameQuirk::Count)> m_reported_quirks;
// Builder that contains all non variable data that should be sent with all
// reports.

View File

@ -220,7 +220,7 @@ class FifoPlayer::CPUCore final : public CPUCoreBase
public:
explicit CPUCore(FifoPlayer* parent) : m_parent(parent) {}
CPUCore(const CPUCore&) = delete;
~CPUCore() {}
~CPUCore() override {}
CPUCore& operator=(const CPUCore&) = delete;
void Init() override

View File

@ -157,7 +157,7 @@ class VAListStruct : public VAList
{
public:
explicit VAListStruct(const Core::CPUThreadGuard& guard, u32 address);
~VAListStruct() = default;
~VAListStruct() override = default;
private:
struct svr4_va_list

View File

@ -28,7 +28,7 @@ public:
DSPHLE(DSPHLE&& other) = delete;
DSPHLE& operator=(const DSPHLE& other) = delete;
DSPHLE& operator=(DSPHLE&& other) = delete;
~DSPHLE();
~DSPHLE() override;
bool Initialize(bool wii, bool dsp_thread) override;
void Shutdown() override;

View File

@ -27,7 +27,7 @@ public:
AESndAccelerator(AESndAccelerator&&) = delete;
AESndAccelerator& operator=(const AESndAccelerator&) = delete;
AESndAccelerator& operator=(AESndAccelerator&&) = delete;
~AESndAccelerator();
~AESndAccelerator() override;
protected:
void OnRawReadEndException() override {}

View File

@ -180,7 +180,7 @@ void AXUCode::HandleCommandList()
break;
case CMD_UNK_08:
DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::USES_UNIMPLEMENTED_AX_COMMAND);
DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::UsesUnimplementedAXCommand);
curr_idx += 10;
break; // TODO: check

View File

@ -129,7 +129,7 @@ public:
HLEAccelerator(HLEAccelerator&&) = delete;
HLEAccelerator& operator=(const HLEAccelerator&) = delete;
HLEAccelerator& operator=(HLEAccelerator&&) = delete;
~HLEAccelerator() = default;
~HLEAccelerator() override = default;
PB_TYPE* acc_pb = nullptr;
@ -536,7 +536,7 @@ void ProcessVoice(HLEAccelerator* accelerator, PB_TYPE& pb, const AXBuffers& buf
if (pb.initial_time_delay.on)
{
// TODO
DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::USES_AX_INITIAL_TIME_DELAY);
DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::UsesAXInitialTimeDelay);
}
#ifdef AX_WII
@ -548,12 +548,12 @@ void ProcessVoice(HLEAccelerator* accelerator, PB_TYPE& pb, const AXBuffers& buf
// Only one filter at most for Wiimotes.
if (pb.remote_iir.on == 2)
{
DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::USES_AX_WIIMOTE_BIQUAD);
DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::UsesAXWiimoteBiquad);
BiquadFilter(samples, count, pb.remote_iir.biquad);
}
else
{
DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::USES_AX_WIIMOTE_LOWPASS);
DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::UsesAXWiimoteLowpass);
LowPassFilter(samples, count, pb.remote_iir.lpf);
}
}

View File

@ -20,7 +20,7 @@ class DSPLLE : public DSPEmulator
{
public:
DSPLLE();
~DSPLLE();
~DSPLLE() override;
bool Initialize(bool wii, bool dsp_thread) override;
void Shutdown() override;

View File

@ -885,14 +885,14 @@ void DVDInterface::ExecuteCommand(ReplyType reply_type)
// Wii-exclusive
case DICommand::StopLaser:
ERROR_LOG_FMT(DVDINTERFACE, "DVDLowStopLaser");
DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::USES_DVD_LOW_STOP_LASER);
DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::UsesDVDLowStopLaser);
SetDriveError(DriveError::InvalidCommand);
interrupt_type = DIInterruptType::DEINT;
break;
// Wii-exclusive
case DICommand::Offset:
ERROR_LOG_FMT(DVDINTERFACE, "DVDLowOffset");
DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::USES_DVD_LOW_OFFSET);
DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::UsesDVDLowOffset);
SetDriveError(DriveError::InvalidCommand);
interrupt_type = DIInterruptType::DEINT;
break;
@ -900,7 +900,7 @@ void DVDInterface::ExecuteCommand(ReplyType reply_type)
case DICommand::ReadBCA:
{
WARN_LOG_FMT(DVDINTERFACE, "DVDLowReadDiskBca - supplying dummy data to appease NSMBW");
DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::USES_DVD_LOW_READ_DISK_BCA);
DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::UsesDVDLowReadDiskBCA);
// NSMBW checks that the first 0x33 bytes of the BCA are 0, then it expects a 1.
// Most (all?) other games have 0x34 0's at the start of the BCA, but don't actually
// read it. NSMBW doesn't care about the other 12 bytes (which contain manufacturing data?)
@ -915,14 +915,14 @@ void DVDInterface::ExecuteCommand(ReplyType reply_type)
// Wii-exclusive
case DICommand::RequestDiscStatus:
ERROR_LOG_FMT(DVDINTERFACE, "DVDLowRequestDiscStatus");
DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::USES_DVD_LOW_REQUEST_DISC_STATUS);
DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::UsesDVDLowRequestDiscStatus);
SetDriveError(DriveError::InvalidCommand);
interrupt_type = DIInterruptType::DEINT;
break;
// Wii-exclusive
case DICommand::RequestRetryNumber:
ERROR_LOG_FMT(DVDINTERFACE, "DVDLowRequestRetryNumber");
DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::USES_DVD_LOW_REQUEST_RETRY_NUMBER);
DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::UsesDVDLowRequestRetryNumber);
SetDriveError(DriveError::InvalidCommand);
interrupt_type = DIInterruptType::DEINT;
break;
@ -935,7 +935,7 @@ void DVDInterface::ExecuteCommand(ReplyType reply_type)
// Wii-exclusive
case DICommand::SerMeasControl:
ERROR_LOG_FMT(DVDINTERFACE, "DVDLowSerMeasControl");
DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::USES_DVD_LOW_SER_MEAS_CONTROL);
DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::UsesDVDLowSerMeasControl);
SetDriveError(DriveError::InvalidCommand);
interrupt_type = DIInterruptType::DEINT;
break;

View File

@ -18,7 +18,7 @@ class CEXIAgp : public IEXIDevice
{
public:
CEXIAgp(Core::System& system, const Slot slot);
virtual ~CEXIAgp() override;
~CEXIAgp() override;
bool IsPresent() const override { return true; }
void ImmWrite(u32 _uData, u32 _uSize) override;
u32 ImmRead(u32 _uSize) override;

View File

@ -216,7 +216,7 @@ class CEXIETHERNET : public IEXIDevice
{
public:
CEXIETHERNET(Core::System& system, BBADeviceType type);
virtual ~CEXIETHERNET();
~CEXIETHERNET() override;
void SetCS(int cs) override;
bool IsPresent() const override;
bool IsInterruptSet() override;

View File

@ -18,7 +18,7 @@ class CEXIMic : public IEXIDevice
{
public:
CEXIMic(Core::System& system, const int index);
virtual ~CEXIMic();
~CEXIMic() override;
void SetCS(int cs) override;
bool IsInterruptSet() override;
bool IsPresent() const override;

View File

@ -33,7 +33,7 @@ class CEXIModem : public IEXIDevice
{
public:
CEXIModem(Core::System& system, ModemDeviceType type);
virtual ~CEXIModem();
~CEXIModem() override;
void SetCS(int cs) override;
bool IsPresent() const override;
bool IsInterruptSet() override;
@ -136,13 +136,13 @@ private:
TAPServerNetworkInterface(CEXIModem* modem_ref, const std::string& destination);
public:
virtual bool Activate() override;
virtual void Deactivate() override;
virtual bool IsActivated() override;
virtual bool SendAndRemoveAllHDLCFrames(std::string* send_buffer) override;
virtual bool RecvInit() override;
virtual void RecvStart() override;
virtual void RecvStop() override;
bool Activate() override;
void Deactivate() override;
bool IsActivated() override;
bool SendAndRemoveAllHDLCFrames(std::string* send_buffer) override;
bool RecvInit() override;
void RecvStart() override;
void RecvStop() override;
private:
TAPServerConnection m_tapserver_if;

View File

@ -24,7 +24,7 @@ class GCMemcardDirectory : public MemoryCardBase
public:
GCMemcardDirectory(const std::string& directory, ExpansionInterface::Slot slot,
const Memcard::HeaderData& header_data, u32 game_id);
~GCMemcardDirectory();
~GCMemcardDirectory() override;
GCMemcardDirectory(const GCMemcardDirectory&) = delete;
GCMemcardDirectory& operator=(const GCMemcardDirectory&) = delete;

View File

@ -19,7 +19,7 @@ class MemoryCard : public MemoryCardBase
public:
MemoryCard(const std::string& filename, ExpansionInterface::Slot card_slot,
u16 size_mbits = Memcard::MBIT_SIZE_MEMORY_CARD_2043);
~MemoryCard();
~MemoryCard() override;
void FlushThread();
void MakeDirty();

View File

@ -39,7 +39,7 @@ class ConstantHandlingMethod : public ReadHandlingMethod<T>
{
public:
explicit ConstantHandlingMethod(T value) : value_(value) {}
virtual ~ConstantHandlingMethod() = default;
~ConstantHandlingMethod() override = default;
void AcceptReadVisitor(ReadHandlingMethodVisitor<T>& v) const override
{
v.VisitConstant(value_);
@ -62,7 +62,7 @@ class NopHandlingMethod : public WriteHandlingMethod<T>
{
public:
NopHandlingMethod() {}
virtual ~NopHandlingMethod() = default;
~NopHandlingMethod() override = default;
void AcceptWriteVisitor(WriteHandlingMethodVisitor<T>& v) const override { v.VisitNop(); }
};
template <typename T>
@ -79,7 +79,7 @@ class DirectHandlingMethod : public ReadHandlingMethod<T>, public WriteHandlingM
{
public:
DirectHandlingMethod(T* addr, u32 mask) : addr_(addr), mask_(mask) {}
virtual ~DirectHandlingMethod() = default;
~DirectHandlingMethod() override = default;
void AcceptReadVisitor(ReadHandlingMethodVisitor<T>& v) const override
{
v.VisitDirect(addr_, mask_);
@ -122,7 +122,7 @@ public:
{
}
virtual ~ComplexHandlingMethod() = default;
~ComplexHandlingMethod() override = default;
void AcceptReadVisitor(ReadHandlingMethodVisitor<T>& v) const override
{
v.VisitComplex(&read_lambda_);

View File

@ -21,7 +21,7 @@ class CSIDevice_GBAEmu final : public ISIDevice
{
public:
CSIDevice_GBAEmu(Core::System& system, SIDevices device, int device_number);
~CSIDevice_GBAEmu();
~CSIDevice_GBAEmu() override;
int RunBuffer(u8* buffer, int request_length) override;
int TransferInterval() override;

View File

@ -120,7 +120,7 @@ protected:
using EncryptedExtension::EncryptedExtension;
private:
void UpdateEncryptionKey() final override;
void UpdateEncryptionKey() final;
};
class Extension3rdParty : public EncryptedExtension
@ -129,7 +129,7 @@ protected:
using EncryptedExtension::EncryptedExtension;
private:
void UpdateEncryptionKey() final override;
void UpdateEncryptionKey() final;
};
} // namespace WiimoteEmu

View File

@ -137,7 +137,7 @@ public:
static constexpr const char* SIDEWAYS_OPTION = "Sideways Wiimote";
explicit Wiimote(unsigned int index);
~Wiimote();
~Wiimote() override;
std::string GetName() const override;

View File

@ -34,7 +34,7 @@ class WiimoteScannerHidapi final : public WiimoteScannerBackend
{
public:
WiimoteScannerHidapi();
~WiimoteScannerHidapi();
~WiimoteScannerHidapi() override;
bool IsReady() const override;
void FindWiimotes(std::vector<Wiimote*>&, Wiimote*&) override;
void Update() override {} // not needed for hidapi

View File

@ -233,7 +233,7 @@ class HotkeyManager : public ControllerEmu::EmulatedController
{
public:
HotkeyManager();
~HotkeyManager();
~HotkeyManager() override;
void GetInput(HotkeyStatus* hk, bool ignore_focus);
std::string GetName() const override;

View File

@ -261,7 +261,7 @@ std::optional<DIDevice::DIResult> DIDevice::StartIOCtl(const IOCtlRequest& reque
case DIIoctl::DVDLowMaskCoverInterrupt:
INFO_LOG_FMT(IOS_DI, "DVDLowMaskCoverInterrupt");
system.GetDVDInterface().SetInterruptEnabled(DVD::DIInterruptType::CVRINT, false);
DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::USES_DI_INTERRUPT_MASK_COMMAND);
DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::UsesDIInterruptMaskCommand);
return DIResult::Success;
case DIIoctl::DVDLowClearCoverInterrupt:
DEBUG_LOG_FMT(IOS_DI, "DVDLowClearCoverInterrupt");
@ -269,7 +269,7 @@ std::optional<DIDevice::DIResult> DIDevice::StartIOCtl(const IOCtlRequest& reque
return DIResult::Success;
case DIIoctl::DVDLowUnmaskStatusInterrupts:
INFO_LOG_FMT(IOS_DI, "DVDLowUnmaskStatusInterrupts");
DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::USES_DI_INTERRUPT_MASK_COMMAND);
DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::UsesDIInterruptMaskCommand);
// Dummied out
return DIResult::Success;
case DIIoctl::DVDLowGetCoverStatus:
@ -282,7 +282,7 @@ std::optional<DIDevice::DIResult> DIDevice::StartIOCtl(const IOCtlRequest& reque
case DIIoctl::DVDLowUnmaskCoverInterrupt:
INFO_LOG_FMT(IOS_DI, "DVDLowUnmaskCoverInterrupt");
system.GetDVDInterface().SetInterruptEnabled(DVD::DIInterruptType::CVRINT, true);
DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::USES_DI_INTERRUPT_MASK_COMMAND);
DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::UsesDIInterruptMaskCommand);
return DIResult::Success;
case DIIoctl::DVDLowReset:
{
@ -319,7 +319,7 @@ std::optional<DIDevice::DIResult> DIDevice::StartIOCtl(const IOCtlRequest& reque
}
case DIIoctl::DVDLowOpenPartition:
ERROR_LOG_FMT(IOS_DI, "DVDLowOpenPartition as an ioctl - rejecting");
DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::USES_DIFFERENT_PARTITION_COMMAND);
DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::UsesDifferentPartitionCommand);
return DIResult::SecurityError;
case DIIoctl::DVDLowClosePartition:
INFO_LOG_FMT(IOS_DI, "DVDLowClosePartition");
@ -372,23 +372,23 @@ std::optional<DIDevice::DIResult> DIDevice::StartIOCtl(const IOCtlRequest& reque
// Dolphin as games are unlikely to use them.
case DIIoctl::DVDLowGetNoDiscOpenPartitionParams:
ERROR_LOG_FMT(IOS_DI, "DVDLowGetNoDiscOpenPartitionParams as an ioctl - rejecting");
DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::USES_DIFFERENT_PARTITION_COMMAND);
DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::UsesDifferentPartitionCommand);
return DIResult::SecurityError;
case DIIoctl::DVDLowNoDiscOpenPartition:
ERROR_LOG_FMT(IOS_DI, "DVDLowNoDiscOpenPartition as an ioctl - rejecting");
DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::USES_DIFFERENT_PARTITION_COMMAND);
DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::UsesDifferentPartitionCommand);
return DIResult::SecurityError;
case DIIoctl::DVDLowGetNoDiscBufferSizes:
ERROR_LOG_FMT(IOS_DI, "DVDLowGetNoDiscBufferSizes as an ioctl - rejecting");
DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::USES_DIFFERENT_PARTITION_COMMAND);
DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::UsesDifferentPartitionCommand);
return DIResult::SecurityError;
case DIIoctl::DVDLowOpenPartitionWithTmdAndTicket:
ERROR_LOG_FMT(IOS_DI, "DVDLowOpenPartitionWithTmdAndTicket as an ioctl - rejecting");
DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::USES_DIFFERENT_PARTITION_COMMAND);
DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::UsesDifferentPartitionCommand);
return DIResult::SecurityError;
case DIIoctl::DVDLowOpenPartitionWithTmdAndTicketView:
ERROR_LOG_FMT(IOS_DI, "DVDLowOpenPartitionWithTmdAndTicketView as an ioctl - rejecting");
DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::USES_DIFFERENT_PARTITION_COMMAND);
DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::UsesDifferentPartitionCommand);
return DIResult::SecurityError;
case DIIoctl::DVDLowGetStatusRegister:
{
@ -721,14 +721,14 @@ std::optional<IPCReply> DIDevice::IOCtlV(const IOCtlVRequest& request)
{
ERROR_LOG_FMT(IOS_DI,
"DVDLowOpenPartition with ticket - not implemented, ignoring ticket parameter");
DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::USES_DIFFERENT_PARTITION_COMMAND);
DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::UsesDifferentPartitionCommand);
}
if (request.in_vectors[2].address != 0)
{
ERROR_LOG_FMT(
IOS_DI,
"DVDLowOpenPartition with cert chain - not implemented, ignoring certs parameter");
DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::USES_DIFFERENT_PARTITION_COMMAND);
DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::UsesDifferentPartitionCommand);
}
const u64 partition_offset =
@ -752,26 +752,26 @@ std::optional<IPCReply> DIDevice::IOCtlV(const IOCtlVRequest& request)
}
case DIIoctl::DVDLowGetNoDiscOpenPartitionParams:
ERROR_LOG_FMT(IOS_DI, "DVDLowGetNoDiscOpenPartitionParams - dummied out");
DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::USES_DIFFERENT_PARTITION_COMMAND);
DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::UsesDifferentPartitionCommand);
request.DumpUnknown(system, GetDeviceName(), Common::Log::LogType::IOS_DI);
break;
case DIIoctl::DVDLowNoDiscOpenPartition:
ERROR_LOG_FMT(IOS_DI, "DVDLowNoDiscOpenPartition - dummied out");
DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::USES_DIFFERENT_PARTITION_COMMAND);
DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::UsesDifferentPartitionCommand);
request.DumpUnknown(system, GetDeviceName(), Common::Log::LogType::IOS_DI);
break;
case DIIoctl::DVDLowGetNoDiscBufferSizes:
ERROR_LOG_FMT(IOS_DI, "DVDLowGetNoDiscBufferSizes - dummied out");
DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::USES_DIFFERENT_PARTITION_COMMAND);
DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::UsesDifferentPartitionCommand);
request.DumpUnknown(system, GetDeviceName(), Common::Log::LogType::IOS_DI);
break;
case DIIoctl::DVDLowOpenPartitionWithTmdAndTicket:
ERROR_LOG_FMT(IOS_DI, "DVDLowOpenPartitionWithTmdAndTicket - not implemented");
DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::USES_DIFFERENT_PARTITION_COMMAND);
DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::UsesDifferentPartitionCommand);
break;
case DIIoctl::DVDLowOpenPartitionWithTmdAndTicketView:
ERROR_LOG_FMT(IOS_DI, "DVDLowOpenPartitionWithTmdAndTicketView - not implemented");
DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::USES_DIFFERENT_PARTITION_COMMAND);
DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::UsesDifferentPartitionCommand);
break;
default:
ERROR_LOG_FMT(IOS_DI, "Unknown ioctlv {:#04x}", request.request);

View File

@ -234,7 +234,7 @@ public:
ESDevice(ESDevice&& other) = delete;
ESDevice& operator=(const ESDevice& other) = delete;
ESDevice& operator=(ESDevice&& other) = delete;
~ESDevice();
~ESDevice() override;
static void InitializeEmulationState(CoreTiming::CoreTimingManager& core_timing);
static void FinalizeEmulationState();

View File

@ -117,7 +117,7 @@ class FSDevice final : public EmulationDevice
{
public:
FSDevice(EmulationKernel& ios, FSCore& core, const std::string& device_name);
~FSDevice();
~FSDevice() override;
void DoState(PointerWrap& p) override;

View File

@ -23,7 +23,7 @@ class HostFileSystem final : public FileSystem
{
public:
HostFileSystem(const std::string& root_path, std::vector<NandRedirect> nand_redirects = {});
~HostFileSystem();
~HostFileSystem() override;
void DoState(PointerWrap& p) override;

View File

@ -153,7 +153,7 @@ class EmulationKernel final : public Kernel
{
public:
EmulationKernel(Core::System& system, u64 ios_title_id);
~EmulationKernel();
~EmulationKernel() override;
// Get a resource manager by name.
// This only works for devices which are part of the device map.

View File

@ -84,7 +84,7 @@ class NetSSLDevice : public EmulationDevice
public:
NetSSLDevice(EmulationKernel& ios, const std::string& device_name);
virtual ~NetSSLDevice();
~NetSSLDevice() override;
std::optional<IPCReply> IOCtl(const IOCtlRequest& request) override;
std::optional<IPCReply> IOCtlV(const IOCtlVRequest& request) override;

View File

@ -198,7 +198,7 @@ std::optional<IPCReply> NetWDCommandDevice::Open(const OpenRequest& request)
if (mode != WD::Mode::DSCommunications && mode != WD::Mode::AOSSAccessPointScan)
{
ERROR_LOG_FMT(IOS_NET, "Unsupported WD operating mode: {}", mode);
DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::USES_UNCOMMON_WD_MODE);
DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::UsesUncommonWDMode);
return IPCReply(s32(ResultCode::UnavailableCommand));
}
@ -390,7 +390,7 @@ std::optional<IPCReply> NetWDCommandDevice::IOCtlV(const IOCtlVRequest& request)
case IOCTLV_WD_CHANGE_GAMEINFO:
case IOCTLV_WD_CHANGE_VTSF:
default:
DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::USES_WD_UNIMPLEMENTED_IOCTL);
DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::UsesWDUnimplementedIoctl);
request.Dump(GetSystem(), GetDeviceName(), Common::Log::LogType::IOS_NET,
Common::Log::LogLevel::LWARNING);
}

View File

@ -41,7 +41,7 @@ class BluetoothEmuDevice final : public BluetoothBaseDevice
public:
BluetoothEmuDevice(EmulationKernel& ios, const std::string& device_name);
virtual ~BluetoothEmuDevice();
~BluetoothEmuDevice() override;
std::optional<IPCReply> Close(u32 fd) override;
std::optional<IPCReply> IOCtlV(const IOCtlVRequest& request) override;

View File

@ -73,7 +73,7 @@ class SkylanderUSB final : public Device
{
public:
SkylanderUSB();
~SkylanderUSB();
~SkylanderUSB() override;
DeviceDescriptor GetDeviceDescriptor() const override;
std::vector<ConfigDescriptor> GetConfigurations() const override;
std::vector<InterfaceDescriptor> GetInterfaces(u8 config) const override;

View File

@ -78,8 +78,8 @@ std::string USBHost::GetDeviceNameFromVIDPID(u16 vid, u16 pid)
libusb_get_string_descriptor_ascii(handle, desc.iProduct, buffer, sizeof(buffer)) > 0)
{
device_name = reinterpret_cast<char*>(buffer);
libusb_close(handle);
}
libusb_close(handle);
}
return false;
}

View File

@ -25,7 +25,7 @@ class USBHost : public EmulationDevice
{
public:
USBHost(EmulationKernel& ios, const std::string& device_name);
virtual ~USBHost();
~USBHost() override;
std::optional<IPCReply> Open(const OpenRequest& request) override;

View File

@ -27,7 +27,7 @@ class LibusbDevice final : public Device
{
public:
LibusbDevice(libusb_device* device, const libusb_device_descriptor& device_descriptor);
~LibusbDevice();
~LibusbDevice() override;
DeviceDescriptor GetDeviceDescriptor() const override;
std::vector<ConfigDescriptor> GetConfigurations() const override;
std::vector<InterfaceDescriptor> GetInterfaces(u8 config) const override;

View File

@ -116,7 +116,7 @@ public:
NetPlayClient(const std::string& address, const u16 port, NetPlayUI* dialog,
const std::string& name, const NetTraversalConfig& traversal_config);
~NetPlayClient();
~NetPlayClient() override;
std::vector<const Player*> GetPlayers();
const NetSettings& GetNetSettings() const;

View File

@ -44,7 +44,7 @@ public:
NetPlayServer(u16 port, bool forward_port, NetPlayUI* dialog,
const NetTraversalConfig& traversal_config);
~NetPlayServer();
~NetPlayServer() override;
bool ChangeGame(const SyncIdentifier& sync_identifier, const std::string& netplay_name);
bool ComputeGameDigest(const SyncIdentifier& sync_identifier);

View File

@ -86,7 +86,7 @@ class PCAPSSLCaptureLogger final : public NetworkCaptureLogger
{
public:
PCAPSSLCaptureLogger();
~PCAPSSLCaptureLogger();
~PCAPSSLCaptureLogger() override;
void OnNewSocket(s32 socket) override;

View File

@ -0,0 +1,12 @@
// Copyright 2021 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#pragma once
struct PerformanceSample
{
double speed_ratio; // See SystemTimers::GetEstimatedEmulationPerformance().
int num_prims;
int num_draw_calls;
};

View File

@ -0,0 +1,105 @@
// Copyright 2021 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include "Core/PerformanceSampleAggregator.h"
#include <limits>
#include "Common/Random.h"
namespace
{
constexpr size_t s_samples_per_report = 100;
std::chrono::microseconds GetCurrentMicroseconds()
{
const std::chrono::high_resolution_clock::duration time_since_epoch =
std::chrono::high_resolution_clock::now().time_since_epoch();
return std::chrono::duration_cast<std::chrono::microseconds>(time_since_epoch);
}
std::chrono::microseconds GetSamplingStartTimeJitter()
{
constexpr long long max_delay = std::chrono::microseconds(std::chrono::minutes(3)).count();
return std::chrono::microseconds(Common::Random::GenerateValue<u64>() % max_delay);
}
std::chrono::microseconds
GetSamplingStartTimestampUsingBaseDelay(const std::chrono::microseconds base_delay)
{
const std::chrono::microseconds now = GetCurrentMicroseconds();
const std::chrono::microseconds jitter = GetSamplingStartTimeJitter();
const std::chrono::microseconds sampling_start_timestamp = now + base_delay + jitter;
return sampling_start_timestamp;
}
std::chrono::microseconds GetInitialSamplingStartTimestamp()
{
constexpr std::chrono::microseconds base_initial_delay = std::chrono::minutes(5);
return GetSamplingStartTimestampUsingBaseDelay(base_initial_delay);
}
std::chrono::microseconds GetRepeatSamplingStartTimestamp()
{
constexpr std::chrono::microseconds base_repeat_delay = std::chrono::minutes(30);
return GetSamplingStartTimestampUsingBaseDelay(base_repeat_delay);
}
PerformanceSampleAggregator::CompletedReport
GetCompletedReport(const std::vector<PerformanceSample>& samples)
{
PerformanceSampleAggregator::CompletedReport report;
const size_t num_samples = samples.size();
report.speed.resize(num_samples);
report.primitives.resize(num_samples);
report.draw_calls.resize(num_samples);
for (size_t i = 0; i < num_samples; ++i)
{
const PerformanceSample& sample = samples[i];
report.speed[i] = static_cast<u32>(sample.speed_ratio * 1'000);
report.primitives[i] = sample.num_prims;
report.draw_calls[i] = sample.num_draw_calls;
}
return report;
}
} // namespace
PerformanceSampleAggregator::PerformanceSampleAggregator()
: m_samples(std::vector<PerformanceSample>(s_samples_per_report)),
m_next_starting_timestamp(std::numeric_limits<std::chrono::microseconds>::max())
{
}
void PerformanceSampleAggregator::InitializePerformanceSampling()
{
m_samples.clear();
m_next_starting_timestamp = GetInitialSamplingStartTimestamp();
}
void PerformanceSampleAggregator::ResetPerformanceSampling()
{
m_samples.clear();
m_next_starting_timestamp = GetRepeatSamplingStartTimestamp();
}
void PerformanceSampleAggregator::AddSampleIfSamplingInProgress(PerformanceSample&& sample)
{
if (GetCurrentMicroseconds() >= m_next_starting_timestamp)
{
m_samples.push_back(sample);
}
}
std::optional<PerformanceSampleAggregator::CompletedReport>
PerformanceSampleAggregator::PopReportIfComplete()
{
if (m_samples.size() < s_samples_per_report)
{
return std::nullopt;
}
const CompletedReport report = GetCompletedReport(m_samples);
ResetPerformanceSampling();
return report;
}

View File

@ -0,0 +1,38 @@
// Copyright 2021 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#pragma once
#include <chrono>
#include <optional>
#include <vector>
#include "Common/CommonTypes.h"
#include "Core/PerformanceSample.h"
class PerformanceSampleAggregator
{
public:
PerformanceSampleAggregator();
struct CompletedReport
{
std::vector<u32> speed;
std::vector<u32> primitives;
std::vector<u32> draw_calls;
};
// Called on game start / title switch.
void InitializePerformanceSampling();
void AddSampleIfSamplingInProgress(PerformanceSample&& sample);
std::optional<CompletedReport> PopReportIfComplete();
private:
// Called after sampling report is completed
void ResetPerformanceSampling();
std::vector<PerformanceSample> m_samples;
std::chrono::microseconds m_next_starting_timestamp;
};

View File

@ -31,7 +31,7 @@ public:
CachedInterpreter(CachedInterpreter&&) = delete;
CachedInterpreter& operator=(const CachedInterpreter&) = delete;
CachedInterpreter& operator=(CachedInterpreter&&) = delete;
~CachedInterpreter();
~CachedInterpreter() override;
void Init() override;
void Shutdown() override;

View File

@ -30,7 +30,7 @@ public:
Interpreter(Interpreter&&) = delete;
Interpreter& operator=(const Interpreter&) = delete;
Interpreter& operator=(Interpreter&&) = delete;
~Interpreter();
~Interpreter() override;
void Init() override;
void Shutdown() override;

View File

@ -8,7 +8,7 @@
class CSVSignatureDB final : public HashSignatureDB
{
public:
~CSVSignatureDB() = default;
~CSVSignatureDB() override = default;
bool Load(const std::string& file_path) override;
bool Save(const std::string& file_path) const override;
};

View File

@ -8,7 +8,7 @@
class DSYSignatureDB final : public HashSignatureDB
{
public:
~DSYSignatureDB() = default;
~DSYSignatureDB() override = default;
bool Load(const std::string& file_path) override;
bool Save(const std::string& file_path) const override;
};

View File

@ -33,7 +33,7 @@
#include "IOS/USB/Emulated/Infinity.h"
#include "IOS/USB/Emulated/Skylanders/Skylander.h"
#include "IOS/USB/USBScanner.h"
#include "VideoCommon/Assets/CustomAssetLoader.h"
#include "VideoCommon/Assets/CustomResourceManager.h"
#include "VideoCommon/CommandProcessor.h"
#include "VideoCommon/Fifo.h"
#include "VideoCommon/GeometryShaderManager.h"
@ -96,7 +96,7 @@ struct System::Impl
VideoInterface::VideoInterfaceManager m_video_interface;
Interpreter m_interpreter;
JitInterface m_jit_interface;
VideoCommon::CustomAssetLoader m_custom_asset_loader;
VideoCommon::CustomResourceManager m_custom_resource_manager;
FifoPlayer m_fifo_player;
FifoRecorder m_fifo_recorder;
Movie::MovieManager m_movie;
@ -335,8 +335,8 @@ VideoInterface::VideoInterfaceManager& System::GetVideoInterface() const
return m_impl->m_video_interface;
}
VideoCommon::CustomAssetLoader& System::GetCustomAssetLoader() const
VideoCommon::CustomResourceManager& System::GetCustomResourceManager() const
{
return m_impl->m_custom_asset_loader;
return m_impl->m_custom_resource_manager;
}
} // namespace Core

View File

@ -108,8 +108,8 @@ class SystemTimersManager;
}
namespace VideoCommon
{
class CustomAssetLoader;
}
class CustomResourceManager;
} // namespace VideoCommon
namespace VideoInterface
{
class VideoInterfaceManager;
@ -197,7 +197,7 @@ public:
VertexShaderManager& GetVertexShaderManager() const;
XFStateManager& GetXFStateManager() const;
VideoInterface::VideoInterfaceManager& GetVideoInterface() const;
VideoCommon::CustomAssetLoader& GetCustomAssetLoader() const;
VideoCommon::CustomResourceManager& GetCustomResourceManager() const;
private:
System();

View File

@ -107,7 +107,7 @@ protected:
class SectorReader : public BlobReader
{
public:
virtual ~SectorReader() = 0;
~SectorReader() override = 0;
bool Read(u64 offset, u64 size, u8* out_ptr) override;

View File

@ -45,7 +45,7 @@ class CompressedBlobReader final : public SectorReader
public:
static std::unique_ptr<CompressedBlobReader> Create(File::IOFile file,
const std::string& filename);
~CompressedBlobReader();
~CompressedBlobReader() override;
const CompressedBlobHeader& GetHeader() const { return m_header; }

Some files were not shown because too many files have changed in this diff Show More