This commit is contained in:
Nayla Hanegan 2025-01-01 17:56:43 -05:00
commit 89d176fd8b
31 changed files with 316 additions and 191 deletions

View file

@ -1320,12 +1320,8 @@ c24e6288 00000006
e2000001 80008000
*Battle Minigames do not count towards the Mini-Game Star.
$Minigame - Battle Games - Can Replace 1VS3 or 2VS2 Minigames [Tabitha]
0421E51C 60000000
0421E520 60000000
$Minigame - Battle Games - Coins Taken is based off of Progress [Tabitha]
C221E520 0000001A
C221E520 0000001D
3DC08029 89EE151D
3A000001 7DEF8214
3A000005 7DEF83D6
@ -1351,6 +1347,9 @@ C221E520 0000001A
3E603AA0 62730000
3F808022 639C124C
927C0000 48000004
3A600000 3B800000
39C00000 39E00000
3A000000 3A400000
2C000000 00000000
*Battle minigames take coins dependent on the progress of the game.
*(1/5 = 5), (2/5 = 10), (3/5 = 20), (4/5 = 30), (5/5 = 50)
@ -1730,4 +1729,4 @@ c204a98c 00000002
7c9f2378 7ca50e70
60000000 00000000
*Game runs at 30Hz but still feel like 60FPS. Great for people with bad PCs
*Can break certain minigames
*Can break certain minigames

View file

@ -124,7 +124,7 @@ class Settings : Closeable {
const val SECTION_INI_DSP = "DSP"
const val SECTION_LOGGER_LOGS = "Logs"
const val SECTION_LOGGER_OPTIONS = "Options"
const val SECTION_GFX_HARDWARE = "Settings"
const val SECTION_GFX_HARDWARE = "Hardware"
const val SECTION_GFX_SETTINGS = "Settings"
const val SECTION_GFX_ENHANCEMENTS = "Enhancements"
const val SECTION_GFX_COLOR_CORRECTION = "ColorCorrection"

View file

@ -34,6 +34,7 @@ add_library(common
Config/Enums.h
Config/Layer.cpp
Config/Layer.h
Contains.h
CPUDetect.h
Crypto/AES.cpp
Crypto/AES.h

View file

@ -0,0 +1,61 @@
// Copyright 2025 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <algorithm>
#include <iterator>
namespace Common
{
struct ContainsFn
{
template <std::input_iterator I, std::sentinel_for<I> S, class T, class Proj = std::identity>
requires std::indirect_binary_predicate < std::ranges::equal_to, std::projected<I, Proj>,
const T* > constexpr bool operator()(I first, S last, const T& value, Proj proj = {}) const
{
return std::ranges::find(std::move(first), last, value, std::move(proj)) != last;
}
template <std::ranges::input_range R, class T, class Proj = std::identity>
requires std::indirect_binary_predicate < std::ranges::equal_to,
std::projected<std::ranges::iterator_t<R>, Proj>,
const T* > constexpr bool operator()(R&& r, const T& value, Proj proj = {}) const
{
return (*this)(std::ranges::begin(r), std::ranges::end(r), value, std::move(proj));
}
};
struct ContainsSubrangeFn
{
template <std::forward_iterator I1, std::sentinel_for<I1> S1, std::forward_iterator I2,
std::sentinel_for<I2> S2, class Pred = std::ranges::equal_to,
class Proj1 = std::identity, class Proj2 = std::identity>
requires std::indirectly_comparable<I1, I2, Pred, Proj1, Proj2>
constexpr bool operator()(I1 first1, S1 last1, I2 first2, S2 last2, Pred pred = {},
Proj1 proj1 = {}, Proj2 proj2 = {}) const
{
return !std::ranges::search(std::move(first1), std::move(last1), std::move(first2),
std::move(last2), std::move(pred), std::move(proj1),
std::move(proj2))
.empty();
}
template <std::ranges::forward_range R1, std::ranges::forward_range R2,
class Pred = std::ranges::equal_to, class Proj1 = std::identity,
class Proj2 = std::identity>
requires std::indirectly_comparable<std::ranges::iterator_t<R1>, std::ranges::iterator_t<R2>,
Pred, Proj1, Proj2>
constexpr bool operator()(R1&& r1, R2&& r2, Pred pred = {}, Proj1 proj1 = {},
Proj2 proj2 = {}) const
{
return (*this)(std::ranges::begin(r1), std::ranges::end(r1), std::ranges::begin(r2),
std::ranges::end(r2), std::move(pred), std::move(proj1), std::move(proj2));
}
};
// TODO C++23: Replace with std::ranges::contains.
inline constexpr ContainsFn Contains{};
// TODO C++23: Replace with std::ranges::contains_subrange.
inline constexpr ContainsSubrangeFn ContainsSubrange{};
} // namespace Common

View file

@ -11,6 +11,7 @@
#include <fmt/ranges.h>
#include "Common/CommonTypes.h"
#include "Common/Contains.h"
#include "Common/FileUtil.h"
#include "Common/StringUtil.h"
@ -105,9 +106,8 @@ bool IsTitlePath(const std::string& path, std::optional<FromWhichRoot> from, u64
static bool IsIllegalCharacter(char c)
{
static constexpr auto illegal_chars = {'\"', '*', '/', ':', '<', '>', '?', '\\', '|', '\x7f'};
return static_cast<unsigned char>(c) <= 0x1F ||
std::find(illegal_chars.begin(), illegal_chars.end(), c) != illegal_chars.end();
static constexpr char illegal_chars[] = {'\"', '*', '/', ':', '<', '>', '?', '\\', '|', '\x7f'};
return static_cast<unsigned char>(c) <= 0x1F || Common::Contains(illegal_chars, c);
}
std::string EscapeFileName(const std::string& filename)

View file

@ -17,6 +17,7 @@
#include "Common/Assert.h"
#include "Common/CommonTypes.h"
#include "Common/Contains.h"
#include "Common/StringUtil.h"
#include "Core/Host.h"
#include "DiscIO/Enums.h"
@ -38,17 +39,13 @@ static std::optional<DiscIO::Language> TryParseLanguage(const std::string& local
// Special handling of Chinese due to its two writing systems
if (split_locale[0] == "zh")
{
const auto locale_contains = [&split_locale](std::string_view str) {
return std::find(split_locale.cbegin(), split_locale.cend(), str) != split_locale.cend();
};
if (locale_contains("Hans"))
if (Common::Contains(split_locale, "Hans"))
return DiscIO::Language::SimplifiedChinese;
if (locale_contains("Hant"))
if (Common::Contains(split_locale, "Hant"))
return DiscIO::Language::TraditionalChinese;
// Mainland China and Singapore use simplified characters
if (locale_contains("CN") || locale_contains("SG"))
if (Common::Contains(split_locale, "CN") || Common::Contains(split_locale, "SG"))
return DiscIO::Language::SimplifiedChinese;
else
return DiscIO::Language::TraditionalChinese;

View file

@ -6,6 +6,7 @@
#include <algorithm>
#include <array>
#include "Common/Contains.h"
#include "Core/Config/WiimoteSettings.h"
namespace ConfigLoaders
@ -15,8 +16,7 @@ bool IsSettingSaveable(const Config::Location& config_location)
static constexpr std::array systems_not_saveable = {Config::System::GCPad, Config::System::WiiPad,
Config::System::GCKeyboard};
if (std::find(begin(systems_not_saveable), end(systems_not_saveable), config_location.system) ==
end(systems_not_saveable))
if (!Common::Contains(systems_not_saveable, config_location.system))
{
return true;
}

View file

@ -7,6 +7,7 @@
#include <chrono>
#include <regex>
#include "Common/Contains.h"
#include "Common/Event.h"
#include "Core/Core.h"
#include "Core/Debugger/PPCDebugInterface.h"
@ -254,12 +255,9 @@ HitType CodeTrace::TraceLogic(const TraceOutput& current_instr, bool first_hit)
// The reg_itr will be used later for erasing.
auto reg_itr = std::ranges::find(m_reg_autotrack, instr.reg0);
const bool match_reg123 =
(!instr.reg1.empty() && std::find(m_reg_autotrack.begin(), m_reg_autotrack.end(),
instr.reg1) != m_reg_autotrack.end()) ||
(!instr.reg2.empty() && std::find(m_reg_autotrack.begin(), m_reg_autotrack.end(),
instr.reg2) != m_reg_autotrack.end()) ||
(!instr.reg3.empty() && std::find(m_reg_autotrack.begin(), m_reg_autotrack.end(),
instr.reg3) != m_reg_autotrack.end());
(!instr.reg1.empty() && Common::Contains(m_reg_autotrack, instr.reg1)) ||
(!instr.reg2.empty() && Common::Contains(m_reg_autotrack, instr.reg2)) ||
(!instr.reg3.empty() && Common::Contains(m_reg_autotrack, instr.reg3));
const bool match_reg0 = reg_itr != m_reg_autotrack.end();
if (!match_reg0 && !match_reg123 && !mem_hit)

View file

@ -13,6 +13,7 @@
#include <fmt/format.h>
#include "Common/Align.h"
#include "Common/Contains.h"
#include "Common/GekkoDisassembler.h"
#include "Common/StringUtil.h"
@ -253,7 +254,7 @@ Common::Debug::Threads PPCDebugInterface::GetThreads(const Core::CPUThreadGuard&
const auto insert_threads = [&guard, &threads, &visited_addrs](u32 addr, auto get_next_addr) {
while (addr != 0 && PowerPC::MMU::HostIsRAMAddress(guard, addr))
{
if (std::find(visited_addrs.begin(), visited_addrs.end(), addr) != visited_addrs.end())
if (Common::Contains(visited_addrs, addr))
break;
visited_addrs.push_back(addr);
auto thread = std::make_unique<Core::Debug::OSThreadView>(guard, addr);

View file

@ -24,6 +24,7 @@
#include "Common/ChunkFile.h"
#include "Common/CommonTypes.h"
#include "Common/Contains.h"
#include "Common/Event.h"
#include "Common/FileUtil.h"
#include "Common/IOFile.h"
@ -261,9 +262,7 @@ static int GetEmptySlot(const std::vector<SlotWithTimestamp>& used_slots)
{
for (int i = 1; i <= (int)NUM_STATES; i++)
{
const auto it = std::find_if(used_slots.begin(), used_slots.end(),
[i](const SlotWithTimestamp& slot) { return slot.slot == i; });
if (it == used_slots.end())
if (!Common::Contains(used_slots, i, &SlotWithTimestamp::slot))
return i;
}
return -1;

View file

@ -10,6 +10,7 @@
#include <array>
#include <fmt/format.h>
#include "Common/Contains.h"
#include "Common/IniFile.h"
#include "Common/StringUtil.h"
@ -86,10 +87,7 @@ static void LoadPatchSection(const Common::IniFile& ini)
static bool IsWC24Channel()
{
const auto& sconfig = SConfig::GetInstance();
const auto found =
std::find(s_wc24_channels.begin(), s_wc24_channels.end(), sconfig.GetTitleID());
return found != s_wc24_channels.end();
return Common::Contains(s_wc24_channels, sconfig.GetTitleID());
}
static void LoadPatches()

View file

@ -21,6 +21,7 @@
#include "Common/Align.h"
#include "Common/Assert.h"
#include "Common/CommonTypes.h"
#include "Common/Contains.h"
#include "Common/EnumUtils.h"
#include "Common/FileUtil.h"
#include "Common/HttpRequest.h"
@ -590,10 +591,8 @@ UpdateResult OnlineSystemUpdater::InstallTitleFromNUS(const std::string& prefix_
const UpdateResult import_result = [&]() {
for (const IOS::ES::Content& content : tmd.first.GetContents())
{
const bool is_already_installed = std::find_if(stored_contents.begin(), stored_contents.end(),
[&content](const auto& stored_content) {
return stored_content.id == content.id;
}) != stored_contents.end();
const bool is_already_installed =
Common::Contains(stored_contents, content.id, &IOS::ES::Content::id);
// Do skip what is already installed on the NAND.
if (is_already_installed)

View file

@ -21,6 +21,7 @@
#include "Common/CPUDetect.h"
#include "Common/CommonPaths.h"
#include "Common/CommonTypes.h"
#include "Common/Contains.h"
#include "Common/Crypto/SHA1.h"
#include "Common/FileUtil.h"
#include "Common/Hash.h"
@ -143,11 +144,8 @@ RedumpVerifier::DownloadStatus RedumpVerifier::DownloadDatfile(const std::string
if (File::Exists(output_path))
return DownloadStatus::FailButOldCacheAvailable;
const std::string system_not_available_message = "System \"" + system + "\" doesn't exist.";
const bool system_not_available_match =
result->end() != std::search(result->begin(), result->end(),
system_not_available_message.begin(),
system_not_available_message.end());
Common::ContainsSubrange(*result, "System \"" + system + "\" doesn't exist.");
return system_not_available_match ? DownloadStatus::SystemNotAvailable : DownloadStatus::Fail;
}
@ -453,21 +451,18 @@ std::vector<Partition> VolumeVerifier::CheckPartitions()
types.emplace_back(*type);
}
if (std::find(types.cbegin(), types.cend(), PARTITION_UPDATE) == types.cend())
if (!Common::Contains(types, PARTITION_UPDATE))
AddProblem(Severity::Low, Common::GetStringT("The update partition is missing."));
const bool has_data_partition =
std::find(types.cbegin(), types.cend(), PARTITION_DATA) != types.cend();
const bool has_data_partition = Common::Contains(types, PARTITION_DATA);
if (!m_is_datel && !has_data_partition)
AddProblem(Severity::High, Common::GetStringT("The data partition is missing."));
const bool has_channel_partition =
std::find(types.cbegin(), types.cend(), PARTITION_CHANNEL) != types.cend();
const bool has_channel_partition = Common::Contains(types, PARTITION_CHANNEL);
if (ShouldHaveChannelPartition() && !has_channel_partition)
AddProblem(Severity::Medium, Common::GetStringT("The channel partition is missing."));
const bool has_install_partition =
std::find(types.cbegin(), types.cend(), PARTITION_INSTALL) != types.cend();
const bool has_install_partition = Common::Contains(types, PARTITION_INSTALL);
if (ShouldHaveInstallPartition() && !has_install_partition)
AddProblem(Severity::High, Common::GetStringT("The install partition is missing."));

View file

@ -38,6 +38,7 @@
<ClInclude Include="Common\Config\ConfigInfo.h" />
<ClInclude Include="Common\Config\Enums.h" />
<ClInclude Include="Common\Config\Layer.h" />
<ClInclude Include="Common\Contains.h" />
<ClInclude Include="Common\CPUDetect.h" />
<ClInclude Include="Common\Crypto\AES.h" />
<ClInclude Include="Common\Crypto\bn.h" />

View file

@ -1,6 +1,8 @@
// Copyright 2017 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <cassert>
#include <QFont>
#include "DolphinQt/Config/ConfigControls/ConfigSlider.h"
@ -24,14 +26,58 @@ ConfigSlider::ConfigSlider(int minimum, int maximum, const Config::Info<int>& se
connect(this, &ConfigSlider::valueChanged, this, &ConfigSlider::Update);
}
ConfigSlider::ConfigSlider(std::vector<int> tick_values, const Config::Info<int>& setting,
Config::Layer* layer)
: ConfigControl(Qt::Horizontal, setting.GetLocation(), layer), m_setting(setting),
m_tick_values(std::move(tick_values))
{
assert(!m_tick_values.empty());
setMinimum(0);
setMaximum(static_cast<int>(m_tick_values.size() - 1));
setPageStep(1);
setTickPosition(QSlider::TicksBelow);
OnConfigChanged();
connect(this, &ConfigSlider::valueChanged, this, &ConfigSlider::Update);
}
void ConfigSlider::Update(int value)
{
SaveValue(m_setting, value);
if (!m_tick_values.empty())
{
if (value >= 0 && static_cast<size_t>(value) < m_tick_values.size())
SaveValue(m_setting, m_tick_values[static_cast<size_t>(value)]);
}
else
{
SaveValue(m_setting, value);
}
}
void ConfigSlider::OnConfigChanged()
{
setValue(ReadValue(m_setting));
if (!m_tick_values.empty())
{
// re-enable in case it was disabled
setEnabled(true);
const int config_value = ReadValue(m_setting);
for (size_t i = 0; i < m_tick_values.size(); ++i)
{
if (m_tick_values[i] == config_value)
{
setValue(static_cast<int>(i));
return;
}
}
// if we reach here than none of the options matched, disable the slider
setEnabled(false);
}
else
{
setValue(ReadValue(m_setting));
}
}
ConfigSliderLabel::ConfigSliderLabel(const QString& text, ConfigSlider* slider)

View file

@ -3,6 +3,8 @@
#pragma once
#include <vector>
#include <QLabel>
#include <QPointer>
@ -19,6 +21,11 @@ public:
ConfigSlider(int minimum, int maximum, const Config::Info<int>& setting, Config::Layer* layer,
int tick = 0);
// Generates a slider with tick_values.size() ticks. Each tick corresponds to the integer at that
// index in the vector.
ConfigSlider(std::vector<int> tick_values, const Config::Info<int>& setting,
Config::Layer* layer);
void Update(int value);
protected:
@ -26,6 +33,9 @@ protected:
private:
const Config::Info<int> m_setting;
// Mappings for slider ticks to config values. Identity mapping is assumed if this is empty.
std::vector<int> m_tick_values;
};
class ConfigSliderLabel final : public QLabel

View file

@ -25,23 +25,18 @@
HacksWidget::HacksWidget(GraphicsWindow* parent)
{
CreateWidgets();
LoadSettings();
ConnectWidgets();
AddDescriptions();
connect(parent, &GraphicsWindow::BackendChanged, this, &HacksWidget::OnBackendChanged);
OnBackendChanged(QString::fromStdString(Config::Get(Config::MAIN_GFX_BACKEND)));
connect(&Settings::Instance(), &Settings::ConfigChanged, this, &HacksWidget::LoadSettings);
connect(m_gpu_texture_decoding, &QCheckBox::toggled, [this, parent] {
SaveSettings();
emit parent->UseGPUTextureDecodingChanged();
});
connect(m_gpu_texture_decoding, &QCheckBox::toggled,
[this, parent] { emit parent->UseGPUTextureDecodingChanged(); });
}
HacksWidget::HacksWidget(GameConfigWidget* parent, Config::Layer* layer) : m_game_layer(layer)
{
CreateWidgets();
LoadSettings();
ConnectWidgets();
AddDescriptions();
}
@ -73,18 +68,15 @@ void HacksWidget::CreateWidgets()
auto* texture_cache_layout = new QGridLayout();
texture_cache_box->setLayout(texture_cache_layout);
m_accuracy = new ToolTipSlider(Qt::Horizontal);
m_accuracy->setMinimum(0);
m_accuracy->setMaximum(2);
m_accuracy->setPageStep(1);
m_accuracy->setTickPosition(QSlider::TicksBelow);
m_accuracy =
new ConfigSlider({0, 512, 128}, Config::GFX_SAFE_TEXTURE_CACHE_COLOR_SAMPLES, m_game_layer);
m_gpu_texture_decoding = new ConfigBool(tr("GPU Texture Decoding"),
Config::GFX_ENABLE_GPU_TEXTURE_DECODING, m_game_layer);
auto* safe_label = new QLabel(tr("Safe"));
safe_label->setAlignment(Qt::AlignRight);
m_accuracy_label = new QLabel(tr("Accuracy:"));
m_accuracy_label = new ConfigSliderLabel(tr("Accuracy:"), m_accuracy);
texture_cache_layout->addWidget(m_accuracy_label, 0, 0);
texture_cache_layout->addWidget(safe_label, 0, 1);
@ -158,7 +150,6 @@ void HacksWidget::OnBackendChanged(const QString& backend_name)
void HacksWidget::ConnectWidgets()
{
connect(m_accuracy, &QSlider::valueChanged, [this](int) { SaveSettings(); });
connect(m_store_efb_copies, &QCheckBox::stateChanged,
[this](int) { UpdateDeferEFBCopiesEnabled(); });
connect(m_store_xfb_copies, &QCheckBox::stateChanged,
@ -169,65 +160,6 @@ void HacksWidget::ConnectWidgets()
[this](int) { UpdateSkipPresentingDuplicateFramesEnabled(); });
}
void HacksWidget::LoadSettings()
{
const QSignalBlocker blocker(m_accuracy);
auto samples = Config::Get(Config::GFX_SAFE_TEXTURE_CACHE_COLOR_SAMPLES);
// Re-enable the slider in case it was disabled because of a custom value
m_accuracy->setEnabled(true);
int slider_pos = 0;
switch (samples)
{
case 512:
slider_pos = 1;
break;
case 128:
slider_pos = 2;
break;
case 0:
slider_pos = 0;
break;
// Custom values, ought not to be touched
default:
m_accuracy->setEnabled(false);
}
m_accuracy->setValue(slider_pos);
QFont bf = m_accuracy_label->font();
bf.setBold(Config::GetActiveLayerForConfig(Config::GFX_SAFE_TEXTURE_CACHE_COLOR_SAMPLES) !=
Config::LayerType::Base);
m_accuracy_label->setFont(bf);
}
void HacksWidget::SaveSettings()
{
int slider_pos = m_accuracy->value();
if (m_accuracy->isEnabled())
{
int samples = 0;
switch (slider_pos)
{
case 0:
samples = 0;
break;
case 1:
samples = 512;
break;
case 2:
samples = 128;
}
Config::SetBaseOrCurrent(Config::GFX_SAFE_TEXTURE_CACHE_COLOR_SAMPLES, samples);
}
}
void HacksWidget::AddDescriptions()
{
static const char TR_SKIP_EFB_CPU_ACCESS_DESCRIPTION[] = QT_TR_NOOP(

View file

@ -6,6 +6,8 @@
#include <QWidget>
class ConfigBool;
class ConfigSlider;
class ConfigSliderLabel;
class GameConfigWidget;
class GraphicsWindow;
class QLabel;
@ -24,9 +26,6 @@ public:
HacksWidget(GameConfigWidget* parent, Config::Layer* layer);
private:
void LoadSettings();
void SaveSettings();
void OnBackendChanged(const QString& backend_name);
// EFB
@ -36,8 +35,8 @@ private:
ConfigBool* m_defer_efb_copies;
// Texture Cache
QLabel* m_accuracy_label;
ToolTipSlider* m_accuracy;
ConfigSliderLabel* m_accuracy_label;
ConfigSlider* m_accuracy;
ConfigBool* m_gpu_texture_decoding;
// External Framebuffer

View file

@ -11,6 +11,7 @@
#include <QToolBar>
#include <QVBoxLayout>
#include "Common/Contains.h"
#include "Common/FileUtil.h"
#include "Common/IniFile.h"
#include "Core/ConfigManager.h"
@ -482,10 +483,7 @@ void BreakpointWidget::OnContextMenu(const QPoint& pos)
if (!is_memory_breakpoint)
{
const auto& inst_breakpoints = m_system.GetPowerPC().GetBreakPoints().GetBreakPoints();
const auto bp_iter =
std::find_if(inst_breakpoints.begin(), inst_breakpoints.end(),
[bp_address](const auto& bp) { return bp.address == bp_address; });
if (bp_iter == inst_breakpoints.end())
if (!Common::Contains(inst_breakpoints, bp_address, &TBreakPoint::address))
return;
menu->addAction(tr("Show in Code"), [this, bp_address] { emit ShowCode(bp_address); });
@ -498,10 +496,7 @@ void BreakpointWidget::OnContextMenu(const QPoint& pos)
else
{
const auto& memory_breakpoints = m_system.GetPowerPC().GetMemChecks().GetMemChecks();
const auto mb_iter =
std::find_if(memory_breakpoints.begin(), memory_breakpoints.end(),
[bp_address](const auto& bp) { return bp.start_address == bp_address; });
if (mb_iter == memory_breakpoints.end())
if (!Common::Contains(memory_breakpoints, bp_address, &TMemCheck::start_address))
return;
menu->addAction(tr("Show in Memory"), [this, bp_address] { emit ShowMemory(bp_address); });

View file

@ -43,6 +43,7 @@
#include <QUrl>
#include "Common/CommonPaths.h"
#include "Common/Contains.h"
#include "Common/FileUtil.h"
#include "Core/Config/MainSettings.h"
@ -805,8 +806,7 @@ bool GameList::AddShortcutToDesktop()
// Sanitize the string by removing all characters that cannot be used in NTFS file names
std::erase_if(game_name, [](char ch) {
static constexpr char illegal_characters[] = {'<', '>', ':', '\"', '/', '\\', '|', '?', '*'};
return std::find(std::begin(illegal_characters), std::end(illegal_characters), ch) !=
std::end(illegal_characters);
return Common::Contains(illegal_characters, ch);
});
std::wstring desktop_path = std::wstring(desktop.get()) + UTF8ToTStr("\\" + game_name + ".lnk");

View file

@ -16,6 +16,7 @@
#include <QPushButton>
#include <QVBoxLayout>
#include "Common/Contains.h"
#include "Core/NetPlayClient.h"
#include "Core/NetPlayServer.h"
@ -108,7 +109,7 @@ void ChunkedProgressDialog::show(const QString& title, const u64 data_size,
for (const auto* player : client->GetPlayers())
{
if (std::find(players.begin(), players.end(), player->pid) == players.end())
if (!Common::Contains(players, player->pid))
continue;
m_progress_bars[player->pid] = new QProgressBar;

View file

@ -22,6 +22,7 @@
#include "AudioCommon/AudioCommon.h"
#include "Common/Config/Config.h"
#include "Common/Contains.h"
#include "Common/FileUtil.h"
#include "Common/StringUtil.h"
@ -297,7 +298,7 @@ void Settings::AddPath(const QString& qpath)
std::string path = qpath.toStdString();
std::vector<std::string> paths = Config::GetIsoPaths();
if (std::find(paths.begin(), paths.end(), path) != paths.end())
if (Common::Contains(paths, path))
return;
paths.emplace_back(path);

View file

@ -18,6 +18,7 @@
#include <jni.h>
#include "Common/Assert.h"
#include "Common/Contains.h"
#include "Common/Logging/Log.h"
#include "Common/StringUtil.h"
@ -1132,8 +1133,7 @@ Java_org_dolphinemu_dolphinemu_features_input_model_ControllerInterface_notifySe
for (ciface::Core::Device::Input* input : device->Inputs())
{
const std::string input_name = input->GetName();
if (std::find(axis_names.begin(), axis_names.end(), input_name) != axis_names.end())
if (Common::Contains(axis_names, input->GetName()))
{
auto casted_input = static_cast<ciface::Android::AndroidSensorAxis*>(input);
casted_input->NotifyIsSuspended(static_cast<bool>(suspended));

View file

@ -10,6 +10,7 @@
#include <mz_os.h>
#include "Common/CommonPaths.h"
#include "Common/Contains.h"
#include "Common/FileSearch.h"
#include "Common/FileUtil.h"
#include "Common/IOFile.h"
@ -181,8 +182,7 @@ bool ResourcePack::Install(const std::string& path)
bool provided_by_other_pack = false;
for (const auto& pack : GetHigherPriorityPacks(*this))
{
if (std::find(pack->GetTextures().begin(), pack->GetTextures().end(), texture) !=
pack->GetTextures().end())
if (Common::Contains(pack->GetTextures(), texture))
{
provided_by_other_pack = true;
break;
@ -246,9 +246,7 @@ bool ResourcePack::Uninstall(const std::string& path)
// Check if a higher priority pack already provides a given texture, don't delete it
for (const auto& pack : GetHigherPriorityPacks(*this))
{
if (::ResourcePack::IsInstalled(*pack) &&
std::find(pack->GetTextures().begin(), pack->GetTextures().end(), texture) !=
pack->GetTextures().end())
if (::ResourcePack::IsInstalled(*pack) && Common::Contains(pack->GetTextures(), texture))
{
provided_by_other_pack = true;
break;
@ -261,9 +259,7 @@ bool ResourcePack::Uninstall(const std::string& path)
// Check if a lower priority pack provides a given texture - if so, install it.
for (auto& pack : lower)
{
if (::ResourcePack::IsInstalled(*pack) &&
std::find(pack->GetTextures().rbegin(), pack->GetTextures().rend(), texture) !=
pack->GetTextures().rend())
if (::ResourcePack::IsInstalled(*pack) && Common::Contains(pack->GetTextures(), texture))
{
pack->Install(path);

View file

@ -14,6 +14,7 @@
#include <fmt/format.h>
#include "Common/Contains.h"
#include "Common/Logging/Log.h"
#include "Common/StringUtil.h"
#include "Core/Config/MainSettings.h"
@ -244,7 +245,7 @@ void XRRConfiguration::AddResolutions(std::vector<std::string>& resos)
std::string(screenResources->modes[k].name) +
(interlaced ? "i" : "");
// Only add unique resolutions
if (std::find(resos.begin(), resos.end(), strRes) == resos.end())
if (!Common::Contains(resos, strRes))
{
resos.push_back(strRes);
}

View file

@ -8,6 +8,7 @@
#include "Common/Assert.h"
#include "Common/CommonFuncs.h"
#include "Common/Contains.h"
#include "Common/Logging/Log.h"
#include "Common/MsgHandler.h"
@ -243,31 +244,24 @@ bool SwapChain::SelectPresentMode()
&mode_count, present_modes.data());
ASSERT(res == VK_SUCCESS);
// Checks if a particular mode is supported, if it is, returns that mode.
auto CheckForMode = [&present_modes](VkPresentModeKHR check_mode) {
auto it = std::find_if(present_modes.begin(), present_modes.end(),
[check_mode](VkPresentModeKHR mode) { return check_mode == mode; });
return it != present_modes.end();
};
// If vsync is enabled, use VK_PRESENT_MODE_FIFO_KHR.
// This check should not fail with conforming drivers, as the FIFO present mode is mandated by
// the specification (VK_KHR_swapchain). In case it isn't though, fall through to any other mode.
if (m_vsync_enabled && CheckForMode(VK_PRESENT_MODE_FIFO_KHR))
if (m_vsync_enabled && Common::Contains(present_modes, VK_PRESENT_MODE_FIFO_KHR))
{
m_present_mode = VK_PRESENT_MODE_FIFO_KHR;
return true;
}
// Prefer screen-tearing, if possible, for lowest latency.
if (CheckForMode(VK_PRESENT_MODE_IMMEDIATE_KHR))
if (Common::Contains(present_modes, VK_PRESENT_MODE_IMMEDIATE_KHR))
{
m_present_mode = VK_PRESENT_MODE_IMMEDIATE_KHR;
return true;
}
// Use optimized-vsync above vsync.
if (CheckForMode(VK_PRESENT_MODE_MAILBOX_KHR))
if (Common::Contains(present_modes, VK_PRESENT_MODE_MAILBOX_KHR))
{
m_present_mode = VK_PRESENT_MODE_MAILBOX_KHR;
return true;

View file

@ -9,6 +9,7 @@
#include "Common/Assert.h"
#include "Common/CommonFuncs.h"
#include "Common/Contains.h"
#include "Common/Logging/Log.h"
#include "Common/MsgHandler.h"
#include "Common/StringUtil.h"
@ -170,15 +171,12 @@ bool VulkanContext::CheckValidationLayerAvailablility()
res = vkEnumerateInstanceLayerProperties(&layer_count, layer_list.data());
ASSERT(res == VK_SUCCESS);
bool supports_validation_layers =
std::find_if(layer_list.begin(), layer_list.end(), [](const auto& it) {
return strcmp(it.layerName, VALIDATION_LAYER_NAME) == 0;
}) != layer_list.end();
bool supports_validation_layers = Common::Contains(
layer_list, std::string_view{VALIDATION_LAYER_NAME}, &VkLayerProperties::layerName);
bool supports_debug_utils =
std::find_if(extension_list.begin(), extension_list.end(), [](const auto& it) {
return strcmp(it.extensionName, VK_EXT_DEBUG_UTILS_EXTENSION_NAME) == 0;
}) != extension_list.end();
Common::Contains(extension_list, std::string_view{VK_EXT_DEBUG_UTILS_EXTENSION_NAME},
&VkExtensionProperties::extensionName);
if (!supports_debug_utils && supports_validation_layers)
{
@ -197,9 +195,8 @@ bool VulkanContext::CheckValidationLayerAvailablility()
extension_list.data());
ASSERT(res == VK_SUCCESS);
supports_debug_utils =
std::find_if(extension_list.begin(), extension_list.end(), [](const auto& it) {
return strcmp(it.extensionName, VK_EXT_DEBUG_UTILS_EXTENSION_NAME) == 0;
}) != extension_list.end();
Common::Contains(extension_list, std::string_view{VK_EXT_DEBUG_UTILS_EXTENSION_NAME},
&VkExtensionProperties::extensionName);
}
// Check for both VK_EXT_debug_utils and VK_LAYER_KHRONOS_validation
@ -330,16 +327,10 @@ bool VulkanContext::SelectInstanceExtensions(std::vector<const char*>* extension
auto AddExtension = [&](const char* name, bool required) {
bool extension_supported =
std::find_if(available_extension_list.begin(), available_extension_list.end(),
[&](const VkExtensionProperties& properties) {
return !strcmp(name, properties.extensionName);
}) != available_extension_list.end();
extension_supported =
extension_supported ||
std::find_if(validation_layer_extension_list.begin(), validation_layer_extension_list.end(),
[&](const VkExtensionProperties& properties) {
return !strcmp(name, properties.extensionName);
}) != validation_layer_extension_list.end();
Common::Contains(available_extension_list, std::string_view{name},
&VkExtensionProperties::extensionName) ||
Common::Contains(validation_layer_extension_list, std::string_view{name},
&VkExtensionProperties::extensionName);
if (extension_supported)
{
@ -648,10 +639,8 @@ bool VulkanContext::SelectDeviceExtensions(bool enable_surface)
INFO_LOG_FMT(VIDEO, "Available extension: {}", extension_properties.extensionName);
auto AddExtension = [&](const char* name, bool required) {
if (std::find_if(available_extension_list.begin(), available_extension_list.end(),
[&](const VkExtensionProperties& properties) {
return !strcmp(name, properties.extensionName);
}) != available_extension_list.end())
if (Common::Contains(available_extension_list, std::string_view{name},
&VkExtensionProperties::extensionName))
{
INFO_LOG_FMT(VIDEO, "Enabling extension: {}", name);
m_device_extensions.push_back(name);

View file

@ -7,6 +7,7 @@
#include <array>
#include <variant>
#include "Common/Contains.h"
#include "Common/Logging/Log.h"
#include "Common/VariantUtil.h"
@ -20,7 +21,7 @@ bool IsQualifier(std::string_view value)
static constexpr std::array<std::string_view, 7> qualifiers = {
"attribute", "const", "highp", "lowp", "mediump", "uniform", "varying",
};
return std::find(qualifiers.begin(), qualifiers.end(), value) != qualifiers.end();
return Common::Contains(qualifiers, value);
}
bool IsBuiltInMacro(std::string_view value)
@ -28,7 +29,7 @@ bool IsBuiltInMacro(std::string_view value)
static constexpr std::array<std::string_view, 5> built_in = {
"__LINE__", "__FILE__", "__VERSION__", "GL_core_profile", "GL_compatibility_profile",
};
return std::find(built_in.begin(), built_in.end(), value) != built_in.end();
return Common::Contains(built_in, value);
}
std::vector<std::string> GlobalConflicts(std::string_view source)

View file

@ -9,6 +9,7 @@
#include "Common/ChunkFile.h"
#include "Common/CommonTypes.h"
#include "Common/Contains.h"
#include "Common/EnumMap.h"
#include "Common/Logging/Log.h"
#include "Common/MathUtil.h"
@ -585,8 +586,7 @@ void VertexManagerBase::Flush()
const auto cache_entry = g_texture_cache->Load(TextureInfo::FromStage(i));
if (cache_entry)
{
if (std::find(texture_names.begin(), texture_names.end(),
cache_entry->texture_info_name) == texture_names.end())
if (!Common::Contains(texture_names, cache_entry->texture_info_name))
{
texture_names.push_back(cache_entry->texture_info_name);
texture_units.push_back(i);

View file

@ -7,6 +7,7 @@
#include "Common/CPUDetect.h"
#include "Common/CommonTypes.h"
#include "Common/Contains.h"
#include "Common/StringUtil.h"
#include "Core/CPUThreadConfigCallback.h"
@ -214,8 +215,7 @@ void VideoConfig::VerifyValidity()
if (iAdapter < 0 || iAdapter > ((int)backend_info.Adapters.size() - 1))
iAdapter = 0;
if (std::find(backend_info.AAModes.begin(), backend_info.AAModes.end(), iMultisamples) ==
backend_info.AAModes.end())
if (!Common::Contains(backend_info.AAModes, iMultisamples))
iMultisamples = 1;
if (stereo_mode != StereoMode::Off)

View file

@ -81,3 +81,114 @@ TEST(StringUtil, GetEscapedHtml)
EXPECT_EQ(Common::GetEscapedHtml("&<>'\""), "&amp;&lt;&gt;&apos;&quot;");
EXPECT_EQ(Common::GetEscapedHtml("&&&"), "&amp;&amp;&amp;");
}
TEST(StringUtil, SplitPath)
{
std::string path;
std::string filename;
std::string extension;
EXPECT_TRUE(SplitPath("/usr/lib/some_file.txt", &path, &filename, &extension));
EXPECT_EQ(path, "/usr/lib/");
EXPECT_EQ(filename, "some_file");
EXPECT_EQ(extension, ".txt");
}
TEST(StringUtil, SplitPathNullOutputPathAllowed)
{
std::string filename;
std::string extension;
EXPECT_TRUE(SplitPath("/usr/lib/some_file.txt", /*path=*/nullptr, &filename, &extension));
EXPECT_EQ(filename, "some_file");
EXPECT_EQ(extension, ".txt");
}
TEST(StringUtil, SplitPathNullOutputFilenameAllowed)
{
std::string path;
std::string extension;
EXPECT_TRUE(SplitPath("/usr/lib/some_file.txt", &path, /*filename=*/nullptr, &extension));
EXPECT_EQ(path, "/usr/lib/");
EXPECT_EQ(extension, ".txt");
}
TEST(StringUtil, SplitPathNullOutputExtensionAllowed)
{
std::string path;
std::string filename;
EXPECT_TRUE(SplitPath("/usr/lib/some_file.txt", &path, &filename, /*extension=*/nullptr));
EXPECT_EQ(path, "/usr/lib/");
EXPECT_EQ(filename, "some_file");
}
TEST(StringUtil, SplitPathReturnsFalseIfFullPathIsEmpty)
{
std::string path;
std::string filename;
std::string extension;
EXPECT_FALSE(SplitPath(/*full_path=*/"", &path, &filename, &extension));
EXPECT_EQ(path, "");
EXPECT_EQ(filename, "");
EXPECT_EQ(extension, "");
}
TEST(StringUtil, SplitPathNoPath)
{
std::string path;
std::string filename;
std::string extension;
EXPECT_TRUE(SplitPath("some_file.txt", &path, &filename, &extension));
EXPECT_EQ(path, "");
EXPECT_EQ(filename, "some_file");
EXPECT_EQ(extension, ".txt");
}
TEST(StringUtil, SplitPathNoFileName)
{
std::string path;
std::string filename;
std::string extension;
EXPECT_TRUE(SplitPath("/usr/lib/.txt", &path, &filename, &extension));
EXPECT_EQ(path, "/usr/lib/");
EXPECT_EQ(filename, "");
EXPECT_EQ(extension, ".txt");
}
TEST(StringUtil, SplitPathNoExtension)
{
std::string path;
std::string filename;
std::string extension;
EXPECT_TRUE(SplitPath("/usr/lib/some_file", &path, &filename, &extension));
EXPECT_EQ(path, "/usr/lib/");
EXPECT_EQ(filename, "some_file");
EXPECT_EQ(extension, "");
}
TEST(StringUtil, SplitPathDifferentPathLengths)
{
std::string path;
std::string filename;
std::string extension;
EXPECT_TRUE(SplitPath("/usr/some_file.txt", &path, &filename, &extension));
EXPECT_EQ(path, "/usr/");
EXPECT_EQ(filename, "some_file");
EXPECT_EQ(extension, ".txt");
EXPECT_TRUE(SplitPath("/usr/lib/foo/some_file.txt", &path, &filename, &extension));
EXPECT_EQ(path, "/usr/lib/foo/");
EXPECT_EQ(filename, "some_file");
EXPECT_EQ(extension, ".txt");
}
TEST(StringUtil, SplitPathBackslashesNotRecognizedAsSeparators)
{
std::string path;
std::string filename;
std::string extension;
EXPECT_TRUE(SplitPath("\\usr\\some_file.txt", &path, &filename, &extension));
EXPECT_EQ(path, "");
EXPECT_EQ(filename, "\\usr\\some_file");
EXPECT_EQ(extension, ".txt");
}
// TODO: add `SplitPath` test coverage for paths containing Windows drives, e.g., "C:".