Compare commits

..

1 Commits

Author SHA1 Message Date
Jordan Woyak a4a65a5368 Core/Common/VideoCommon: Fix some weird (!eof) logic. 2024-12-04 17:30:47 -06:00
121 changed files with 1173 additions and 1769 deletions

2
.gitignore vendored
View File

@ -41,5 +41,3 @@ CMakeLists.txt.user
.idea/
# Ignore Visual Studio Code's working dir
/.vscode/
# Ignore flatpak-builder's cache dir
.flatpak-builder

View File

@ -2,6 +2,7 @@
[Core]
# Values set here will override the main Dolphin settings.
CPUThread = False
[OnFrame]
# Add memory patches to be applied every frame here.

View File

@ -10,6 +10,3 @@ MMU = True
[ActionReplay]
# Add action replay cheats here.
[Video_Hacks]
# Needed for loading screens to show up.
EFBAccessEnable = True

View File

@ -62,7 +62,7 @@ bool IsPathAndroidContent(std::string_view uri)
std::string OpenModeToAndroid(std::string mode)
{
// The 'b' specifier is not supported by Android. Since we're on POSIX, it's fine to just skip it.
std::erase(mode, 'b');
mode.erase(std::remove(mode.begin(), mode.end(), 'b'));
if (mode == "r")
return "r";

View File

@ -51,9 +51,10 @@ Java_org_dolphinemu_dolphinemu_features_cheats_model_GraphicsModGroup_getMods(JN
for (GraphicsModConfig& mod : mod_group->GetMods())
{
// If no group matches the mod's features, or if the mod has no features, skip it
if (std::ranges::none_of(mod.m_features, [&groups](const GraphicsModFeatureConfig& feature) {
return groups.contains(feature.m_group);
}))
if (std::none_of(mod.m_features.begin(), mod.m_features.end(),
[&groups](const GraphicsModFeatureConfig& feature) {
return groups.contains(feature.m_group);
}))
{
continue;
}

View File

@ -24,7 +24,7 @@ struct Elt
{
bool IsZero() const
{
return std::ranges::all_of(data, [](u8 b) { return b == 0; });
return std::all_of(data.begin(), data.end(), [](u8 b) { return b == 0; });
}
void MulX()

View File

@ -91,7 +91,7 @@ void MemoryPatches::DisablePatch(const Core::CPUThreadGuard& guard, std::size_t
bool MemoryPatches::HasEnabledPatch(u32 address) const
{
return std::ranges::any_of(m_patches, [address](const MemoryPatch& patch) {
return std::any_of(m_patches.begin(), m_patches.end(), [address](const MemoryPatch& patch) {
return patch.address == address && patch.is_enabled == MemoryPatch::State::Enabled;
});
}

View File

@ -79,7 +79,7 @@ void Watches::DisableWatch(std::size_t index)
bool Watches::HasEnabledWatch(u32 address) const
{
return std::ranges::any_of(m_watches, [address](const auto& watch) {
return std::any_of(m_watches.begin(), m_watches.end(), [address](const auto& watch) {
return watch.address == address && watch.is_enabled == Watch::State::Enabled;
});
}

View File

@ -729,7 +729,7 @@ static bool Unpack(const std::function<bool()>& cancelled, const std::string pat
const bool is_path_traversal_attack =
(childname.find("\\") != std::string_view::npos) ||
(childname.find('/') != std::string_view::npos) ||
std::ranges::all_of(childname, [](char c) { return c == '.'; });
std::all_of(childname.begin(), childname.end(), [](char c) { return c == '.'; });
if (is_path_traversal_attack)
{
ERROR_LOG_FMT(

View File

@ -41,7 +41,7 @@ std::vector<std::string> DoFileSearch(const std::vector<std::string>& directorie
// N.B. This avoids doing any copies
auto ext_matches = [&native_exts](const fs::path& path) {
const std::basic_string_view<fs::path::value_type> native_path = path.native();
return std::ranges::any_of(native_exts, [&native_path](const auto& ext) {
return std::any_of(native_exts.cbegin(), native_exts.cend(), [&native_path](const auto& ext) {
const auto compare_len = ext.native().length();
if (native_path.length() < compare_len)
return false;
@ -98,8 +98,7 @@ std::vector<std::string> DoFileSearch(const std::vector<std::string>& directorie
// not because std::filesystem returns duplicates). Also note that this pathname-based uniqueness
// isn't as thorough as std::filesystem::equivalent.
std::ranges::sort(result);
const auto unique_result = std::ranges::unique(result);
result.erase(unique_result.begin(), unique_result.end());
result.erase(std::unique(result.begin(), result.end()), result.end());
// Dolphin expects to be able to use "/" (DIR_SEP) everywhere.
// std::filesystem uses the OS separator.

View File

@ -250,17 +250,9 @@ bool IniFile::Load(const std::string& filename, bool keep_current_data)
Section* current_section = nullptr;
bool first_line = true;
while (!in.eof())
std::string line_str;
while (std::getline(in, line_str))
{
std::string line_str;
if (!std::getline(in, line_str))
{
if (in.eof())
return true;
else
return false;
}
std::string_view line = line_str;
// Skips the UTF-8 BOM at the start of files. Notepad likes to add this.
@ -311,8 +303,7 @@ bool IniFile::Load(const std::string& filename, bool keep_current_data)
}
}
in.close();
return true;
return in.good();
}
bool IniFile::Save(const std::string& filename)

View File

@ -113,7 +113,7 @@ static bool IsIllegalCharacter(char c)
std::string EscapeFileName(const std::string& filename)
{
// Prevent paths from containing special names like ., .., ..., ...., and so on
if (std::ranges::all_of(filename, [](char c) { return c == '.'; }))
if (std::all_of(filename.begin(), filename.end(), [](char c) { return c == '.'; }))
return ReplaceAll(filename, ".", "__2e__");
// Escape all double underscores since we will use double underscores for our escape sequences
@ -170,7 +170,8 @@ std::string UnescapeFileName(const std::string& filename)
bool IsFileNameSafe(const std::string_view filename)
{
return !filename.empty() && !std::ranges::all_of(filename, [](char c) { return c == '.'; }) &&
std::ranges::none_of(filename, IsIllegalCharacter);
return !filename.empty() &&
!std::all_of(filename.begin(), filename.end(), [](char c) { return c == '.'; }) &&
std::none_of(filename.begin(), filename.end(), IsIllegalCharacter);
}
} // namespace Common

View File

@ -275,21 +275,6 @@ inline bool IsAlpha(char c)
return std::isalpha(c, std::locale::classic());
}
inline bool IsAlnum(char c)
{
return std::isalnum(c, std::locale::classic());
}
inline bool IsUpper(char c)
{
return std::isupper(c, std::locale::classic());
}
inline bool IsXDigit(char c)
{
return std::isxdigit(c /* no locale needed */) != 0;
}
inline char ToLower(char ch)
{
return std::tolower(ch, std::locale::classic());

View File

@ -44,7 +44,6 @@ struct Symbol
std::string name;
std::string function_name; // stripped function name
std::string object_name; // name of object/source file symbol belongs to
std::vector<SCall> callers; // addresses of functions that call this function
std::vector<SCall> calls; // addresses of functions that are called by this function
u32 hash = 0; // use for HLE function finding

View File

@ -132,6 +132,7 @@ public:
void DoIdle();
std::recursive_mutex& GetLock();
void SetHardcoreMode();
bool IsHardcoreModeActive() const;
void SetGameIniId(const std::string& game_ini_id) { m_game_ini_id = game_ini_id; }
@ -198,8 +199,6 @@ private:
void* userdata);
void DisplayWelcomeMessage();
void SetHardcoreMode();
template <typename T>
void FilterApprovedIni(std::vector<T>& codes, const std::string& game_ini_id) const;
template <typename T>
@ -276,21 +275,11 @@ private:
#include <string>
namespace ActionReplay
{
struct ARCode;
}
namespace DiscIO
{
class Volume;
}
namespace Gecko
{
class GeckoCode;
}
class AchievementManager
{
public:

View File

@ -605,9 +605,7 @@ bool CBoot::BootUp(Core::System& system, const Core::CPUThreadGuard& guard,
ppc_state.pc = executable.reader->GetEntryPoint();
const std::string filename = PathToFileName(executable.path);
if (executable.reader->LoadSymbols(guard, system.GetPPCSymbolDB(), filename))
if (executable.reader->LoadSymbols(guard, system.GetPPCSymbolDB()))
{
Host_PPCSymbolsChanged();
HLE::PatchFunctions(system);

View File

@ -215,8 +215,7 @@ public:
virtual bool IsValid() const = 0;
virtual bool IsWii() const = 0;
virtual bool LoadIntoMemory(Core::System& system, bool only_in_mem1 = false) const = 0;
virtual bool LoadSymbols(const Core::CPUThreadGuard& guard, PPCSymbolDB& ppc_symbol_db,
const std::string& filename) const = 0;
virtual bool LoadSymbols(const Core::CPUThreadGuard& guard, PPCSymbolDB& ppc_symbol_db) const = 0;
protected:
std::vector<u8> m_bytes;

View File

@ -27,8 +27,7 @@ public:
bool IsAncast() const { return m_is_ancast; }
u32 GetEntryPoint() const override { return m_dolheader.entryPoint; }
bool LoadIntoMemory(Core::System& system, bool only_in_mem1 = false) const override;
bool LoadSymbols(const Core::CPUThreadGuard& guard, PPCSymbolDB& ppc_symbol_db,
const std::string& filename) const override
bool LoadSymbols(const Core::CPUThreadGuard& guard, PPCSymbolDB& ppc_symbol_db) const override
{
return false;
}

View File

@ -180,8 +180,7 @@ SectionID ElfReader::GetSectionByName(const char* name, int firstSection) const
return -1;
}
bool ElfReader::LoadSymbols(const Core::CPUThreadGuard& guard, PPCSymbolDB& ppc_symbol_db,
const std::string& filename) const
bool ElfReader::LoadSymbols(const Core::CPUThreadGuard& guard, PPCSymbolDB& ppc_symbol_db) const
{
bool hasSymbols = false;
SectionID sec = GetSectionByName(".symtab");
@ -219,7 +218,7 @@ bool ElfReader::LoadSymbols(const Core::CPUThreadGuard& guard, PPCSymbolDB& ppc_
default:
continue;
}
ppc_symbol_db.AddKnownSymbol(guard, value, size, name, filename, symtype);
ppc_symbol_db.AddKnownSymbol(guard, value, size, name, symtype);
hasSymbols = true;
}
}

View File

@ -36,8 +36,7 @@ public:
u32 GetEntryPoint() const override { return entryPoint; }
u32 GetFlags() const { return (u32)(header->e_flags); }
bool LoadIntoMemory(Core::System& system, bool only_in_mem1 = false) const override;
bool LoadSymbols(const Core::CPUThreadGuard& guard, PPCSymbolDB& ppc_symbol_db,
const std::string& filename) const override;
bool LoadSymbols(const Core::CPUThreadGuard& guard, PPCSymbolDB& ppc_symbol_db) const override;
// TODO: actually check for validity.
bool IsValid() const override { return true; }
bool IsWii() const override;

View File

@ -79,9 +79,11 @@ static DiscIO::Language ComputeDefaultLanguage()
static std::optional<std::string> TryParseCountryCode(const std::string& locale)
{
const auto is_upper = [](char c) { return std::isupper(c, std::locale::classic()); };
for (const std::string& part : SplitString(locale, '-'))
{
if (part.size() == 2 && Common::IsUpper(part[0]) && Common::IsUpper(part[1]))
if (part.size() == 2 && is_upper(part[0]) && is_upper(part[1]))
return part;
}

View File

@ -114,8 +114,9 @@ public:
for (const auto& value : section_map)
{
const Config::Location location{system.first, section_name, value.first};
const bool load_disallowed = std::ranges::any_of(
s_setting_disallowed, [&location](const auto* l) { return *l == location; });
const bool load_disallowed =
std::any_of(begin(s_setting_disallowed), end(s_setting_disallowed),
[&location](const Config::Location* l) { return *l == location; });
if (load_disallowed)
continue;

View File

@ -27,8 +27,9 @@ bool IsSettingSaveable(const Config::Location& config_location)
&Config::WIIMOTE_BB_SOURCE.GetLocation(),
};
return std::ranges::any_of(s_setting_saveable, [&config_location](const auto* location) {
return *location == config_location;
});
return std::any_of(begin(s_setting_saveable), end(s_setting_saveable),
[&config_location](const Config::Location* location) {
return *location == config_location;
});
}
} // namespace ConfigLoaders

View File

@ -194,7 +194,7 @@ void DisplayMessage(std::string message, int time_in_ms)
return;
// Actually displaying non-ASCII could cause things to go pear-shaped
if (!std::ranges::all_of(message, Common::IsPrintableCharacter))
if (!std::all_of(message.begin(), message.end(), Common::IsPrintableCharacter))
return;
OSD::AddMessage(std::move(message), time_in_ms);

View File

@ -267,8 +267,8 @@ HitType CodeTrace::TraceLogic(const TraceOutput& current_instr, bool first_hit)
// Checks if the intstruction is a type that needs special handling.
const auto CompareInstruction = [](std::string_view instruction, const auto& type_compare) {
return std::ranges::any_of(
type_compare, [&instruction](std::string_view s) { return instruction.starts_with(s); });
return std::any_of(type_compare.begin(), type_compare.end(),
[&instruction](std::string_view s) { return instruction.starts_with(s); });
};
// Exclusions from updating tracking logic. mt operations are too complex and specialized.

View File

@ -375,7 +375,6 @@ void RSOView::LoadAll(const Core::CPUThreadGuard& guard, u32 address)
void RSOView::Apply(const Core::CPUThreadGuard& guard, PPCSymbolDB* symbol_db) const
{
const std::string rso_name = GetName();
for (const RSOExport& rso_export : GetExports())
{
u32 address = GetExportAddress(rso_export);
@ -390,17 +389,15 @@ void RSOView::Apply(const Core::CPUThreadGuard& guard, PPCSymbolDB* symbol_db) c
{
// Function symbol
symbol->Rename(export_name);
symbol->object_name = rso_name;
}
else
{
// Data symbol
symbol_db->AddKnownSymbol(guard, address, 0, export_name, rso_name,
Common::Symbol::Type::Data);
symbol_db->AddKnownSymbol(guard, address, 0, export_name, Common::Symbol::Type::Data);
}
}
}
DEBUG_LOG_FMT(SYMBOLS, "RSO({}): {} symbols applied", rso_name, GetExportsCount());
DEBUG_LOG_FMT(SYMBOLS, "RSO({}): {} symbols applied", GetName(), GetExportsCount());
}
u32 RSOView::GetNextEntry() const

View File

@ -101,8 +101,8 @@ std::pair<GCMemcardErrorCode, std::optional<GCMemcard>> GCMemcard::Open(std::str
MBIT_SIZE_MEMORY_CARD_2043,
}};
if (!std::ranges::any_of(valid_megabits,
[filesize_megabits](u64 mbits) { return mbits == filesize_megabits; }))
if (!std::any_of(valid_megabits.begin(), valid_megabits.end(),
[filesize_megabits](u64 mbits) { return mbits == filesize_megabits; }))
{
error_code.Set(GCMemcardValidityIssues::INVALID_CARD_SIZE);
return std::make_pair(error_code, std::nullopt);
@ -1296,8 +1296,8 @@ GCMemcardErrorCode Header::CheckForErrors(u16 card_size_mbits) const
error_code.Set(GCMemcardValidityIssues::MISMATCHED_CARD_SIZE);
// unused areas, should always be filled with 0xFF
if (std::ranges::any_of(m_unused_1, [](u8 val) { return val != 0xFF; }) ||
std::ranges::any_of(m_unused_2, [](u8 val) { return val != 0xFF; }))
if (std::any_of(m_unused_1.begin(), m_unused_1.end(), [](u8 val) { return val != 0xFF; }) ||
std::any_of(m_unused_2.begin(), m_unused_2.end(), [](u8 val) { return val != 0xFF; }))
{
error_code.Set(GCMemcardValidityIssues::DATA_IN_UNUSED_AREA);
}
@ -1361,7 +1361,7 @@ GCMemcardErrorCode Directory::CheckForErrors() const
error_code.Set(GCMemcardValidityIssues::INVALID_CHECKSUM);
// unused area, should always be filled with 0xFF
if (std::ranges::any_of(m_padding, [](u8 val) { return val != 0xFF; }))
if (std::any_of(m_padding.begin(), m_padding.end(), [](u8 val) { return val != 0xFF; }))
error_code.Set(GCMemcardValidityIssues::DATA_IN_UNUSED_AREA);
return error_code;

View File

@ -613,7 +613,8 @@ void WiimoteScanner::SetScanMode(WiimoteScanMode scan_mode)
bool WiimoteScanner::IsReady() const
{
std::lock_guard lg(m_backends_mutex);
return std::ranges::any_of(m_backends, &WiimoteScannerBackend::IsReady);
return std::any_of(m_backends.begin(), m_backends.end(),
[](const auto& backend) { return backend->IsReady(); });
}
static void CheckForDisconnectedWiimotes()

View File

@ -98,8 +98,8 @@ bool IOCtlVRequest::HasNumberOfValidVectors(const size_t in_count, const size_t
return false;
auto IsValidVector = [](const auto& vector) { return vector.size == 0 || vector.address != 0; };
return std::ranges::all_of(in_vectors, IsValidVector) &&
std::ranges::all_of(io_vectors, IsValidVector);
return std::all_of(in_vectors.begin(), in_vectors.end(), IsValidVector) &&
std::all_of(io_vectors.begin(), io_vectors.end(), IsValidVector);
}
void IOCtlRequest::Log(std::string_view device_name, Common::Log::LogType type,

View File

@ -298,7 +298,7 @@ std::string TMDReader::GetGameID() const
std::memcpy(game_id, m_bytes.data() + offsetof(TMDHeader, title_id) + 4, 4);
std::memcpy(game_id + 4, m_bytes.data() + offsetof(TMDHeader, group_id), 2);
if (std::ranges::all_of(game_id, Common::IsPrintableCharacter))
if (std::all_of(std::begin(game_id), std::end(game_id), Common::IsPrintableCharacter))
return std::string(game_id, sizeof(game_id));
return fmt::format("{:016x}", GetTitleId());

View File

@ -79,7 +79,8 @@ static bool IsValidPartOfTitleID(const std::string& string)
{
if (string.length() != 8)
return false;
return std::ranges::all_of(string, Common::IsXDigit);
return std::all_of(string.begin(), string.end(),
[](const auto character) { return std::isxdigit(character) != 0; });
}
static std::vector<u64> GetTitlesInTitleOrImport(FS::FileSystem* fs, const std::string& titles_dir)

View File

@ -464,7 +464,7 @@ static bool HasAllRequiredContents(Kernel& ios, const ES::TMDReader& tmd)
const u64 title_id = tmd.GetTitleId();
const std::vector<ES::Content> contents = tmd.GetContents();
const ES::SharedContentMap shared_content_map{ios.GetFSCore()};
return std::ranges::all_of(contents, [&](const ES::Content& content) {
return std::all_of(contents.cbegin(), contents.cend(), [&](const ES::Content& content) {
if (content.IsOptional())
return true;
@ -878,7 +878,7 @@ ReturnCode ESCore::DeleteSharedContent(const std::array<u8, 20>& sha1) const
// Check whether the shared content is used by a system title.
const std::vector<u64> titles = GetInstalledTitles();
const bool is_used_by_system_title = std::ranges::any_of(titles, [&](u64 id) {
const bool is_used_by_system_title = std::any_of(titles.begin(), titles.end(), [&](u64 id) {
if (!ES::IsTitleType(id, ES::TitleType::System))
return false;
@ -887,8 +887,8 @@ ReturnCode ESCore::DeleteSharedContent(const std::array<u8, 20>& sha1) const
return true;
const auto contents = tmd.GetContents();
return std::ranges::any_of(contents,
[&sha1](const auto& content) { return content.sha1 == sha1; });
return std::any_of(contents.begin(), contents.end(),
[&sha1](const auto& content) { return content.sha1 == sha1; });
});
// Any shared content used by a system title cannot be deleted.

View File

@ -26,7 +26,7 @@ bool IsValidNonRootPath(std::string_view path)
bool IsValidFilename(std::string_view filename)
{
return filename.length() <= MaxFilenameLength &&
!std::ranges::any_of(filename, [](char c) { return c == '/'; });
!std::any_of(filename.begin(), filename.end(), [](char c) { return c == '/'; });
}
SplitPathResult SplitPathAndBasename(std::string_view path)

View File

@ -461,7 +461,8 @@ ResultCode HostFileSystem::Format(Uid uid)
ResultCode HostFileSystem::CreateFileOrDirectory(Uid uid, Gid gid, const std::string& path,
FileAttribute attr, Modes modes, bool is_file)
{
if (!IsValidNonRootPath(path) || !std::ranges::all_of(path, Common::IsPrintableCharacter))
if (!IsValidNonRootPath(path) ||
!std::all_of(path.begin(), path.end(), Common::IsPrintableCharacter))
{
return ResultCode::Invalid;
}
@ -515,14 +516,14 @@ ResultCode HostFileSystem::CreateDirectory(Uid uid, Gid gid, const std::string&
bool HostFileSystem::IsFileOpened(const std::string& path) const
{
return std::ranges::any_of(m_handles, [&path](const Handle& handle) {
return std::any_of(m_handles.begin(), m_handles.end(), [&path](const Handle& handle) {
return handle.opened && handle.wii_path == path;
});
}
bool HostFileSystem::IsDirectoryInUse(const std::string& path) const
{
return std::ranges::any_of(m_handles, [&path](const Handle& handle) {
return std::any_of(m_handles.begin(), m_handles.end(), [&path](const Handle& handle) {
return handle.opened && handle.wii_path.starts_with(path);
});
}

View File

@ -58,8 +58,8 @@ bool WC24FriendList::CheckFriendList() const
bool WC24FriendList::DoesFriendExist(u64 friend_id) const
{
return std::ranges::any_of(m_data.friend_codes,
[&friend_id](const u64 v) { return v == friend_id; });
return std::any_of(m_data.friend_codes.cbegin(), m_data.friend_codes.cend(),
[&friend_id](const u64 v) { return v == friend_id; });
}
std::vector<u64> WC24FriendList::GetUnconfirmedFriends() const

View File

@ -1085,10 +1085,10 @@ void WiiSockMan::UpdatePollCommands()
std::vector<int> original_order(pfds.size());
std::iota(original_order.begin(), original_order.end(), 0);
// Select indices with valid fds
const auto partition_result = std::ranges::partition(original_order, [&](auto i) {
auto mid = std::partition(original_order.begin(), original_order.end(), [&](auto i) {
return GetHostSocket(memory.Read_U32(pcmd.buffer_out + 0xc * i)) >= 0;
});
const auto n_valid = std::distance(original_order.begin(), partition_result.begin());
const auto n_valid = std::distance(original_order.begin(), mid);
// Move all the valid pollfds to the front of the vector
for (auto i = 0; i < n_valid; ++i)

View File

@ -74,7 +74,7 @@ bool Device::HasClass(const u8 device_class) const
if (GetDeviceDescriptor().bDeviceClass == device_class)
return true;
const auto interfaces = GetInterfaces(0);
return std::ranges::any_of(interfaces, [device_class](const auto& interface) {
return std::any_of(interfaces.begin(), interfaces.end(), [device_class](const auto& interface) {
return interface.bInterfaceClass == device_class;
});
}

View File

@ -234,7 +234,7 @@ std::optional<IPCReply> OH0::RegisterClassChangeHook(const IOCtlVRequest& reques
bool OH0::HasDeviceWithVidPid(const u16 vid, const u16 pid) const
{
return std::ranges::any_of(m_devices, [=](const auto& device) {
return std::any_of(m_devices.begin(), m_devices.end(), [=](const auto& device) {
return device.second->GetVid() == vid && device.second->GetPid() == pid;
});
}

View File

@ -380,9 +380,9 @@ bool IsEmulated(u32 major_version)
if (major_version == static_cast<u32>(Titles::BC & 0xffffffff))
return true;
return std::ranges::any_of(ios_memory_values, [major_version](const MemoryValues& values) {
return values.ios_number == major_version;
});
return std::any_of(
ios_memory_values.begin(), ios_memory_values.end(),
[major_version](const MemoryValues& values) { return values.ios_number == major_version; });
}
bool IsEmulated(u64 title_id)

View File

@ -375,8 +375,8 @@ s32 WFSSRVDevice::Rename(std::string source, std::string dest) const
INFO_LOG_FMT(IOS_WFS, "IOCTL_WFS_RENAME: {} to {}", source, dest);
const bool opened =
std::ranges::any_of(m_fds, [&](const auto& fd) { return fd.in_use && fd.path == source; });
const bool opened = std::any_of(m_fds.begin(), m_fds.end(),
[&](const auto& fd) { return fd.in_use && fd.path == source; });
if (opened)
return WFS_FILE_IS_OPENED;

View File

@ -93,7 +93,7 @@ static std::array<u8, 20> ConvertGitRevisionToBytes(const std::string& revision)
{
std::array<u8, 20> revision_bytes{};
if (revision.size() % 2 == 0 && std::ranges::all_of(revision, Common::IsXDigit))
if (revision.size() % 2 == 0 && std::all_of(revision.begin(), revision.end(), ::isxdigit))
{
// The revision string normally contains a git commit hash,
// which is 40 hexadecimal digits long. In DTM files, each pair of
@ -1081,11 +1081,11 @@ void MovieManager::LoadInput(const std::string& movie_path)
std::vector<u8> movInput(m_current_byte);
t_record.ReadArray(movInput.data(), movInput.size());
const auto mismatch_result = std::ranges::mismatch(movInput, m_temp_input);
const auto result = std::mismatch(movInput.begin(), movInput.end(), m_temp_input.begin());
if (mismatch_result.in1 != movInput.end())
if (result.first != movInput.end())
{
const ptrdiff_t mismatch_index = std::distance(movInput.begin(), mismatch_result.in1);
const ptrdiff_t mismatch_index = std::distance(movInput.begin(), result.first);
// this is a "you did something wrong" alert for the user's benefit.
// we'll try to say what's going on in excruciating detail, otherwise the user might not

View File

@ -2486,8 +2486,8 @@ bool NetPlayClient::PlayerHasControllerMapped(const PlayerId pid) const
{
const auto mapping_matches_player_id = [pid](const PlayerId& mapping) { return mapping == pid; };
return std::ranges::any_of(m_pad_map, mapping_matches_player_id) ||
std::ranges::any_of(m_wiimote_map, mapping_matches_player_id);
return std::any_of(m_pad_map.begin(), m_pad_map.end(), mapping_matches_player_id) ||
std::any_of(m_wiimote_map.begin(), m_wiimote_map.end(), mapping_matches_player_id);
}
bool NetPlayClient::IsLocalPlayer(const PlayerId pid) const
@ -2543,7 +2543,7 @@ bool NetPlayClient::DoAllPlayersHaveGame()
{
std::lock_guard lkp(m_crit.players);
return std::ranges::all_of(m_players, [](const auto& entry) {
return std::all_of(std::begin(m_players), std::end(m_players), [](auto entry) {
return entry.second.game_status == SyncIdentifierComparison::SameGame;
});
}

View File

@ -237,7 +237,7 @@ static bool DecompressPacketIntoFolderInternal(sf::Packet& packet, const std::st
if (name.find('\\') != std::string::npos)
return false;
#endif
if (std::ranges::all_of(name, [](char c) { return c == '.'; }))
if (std::all_of(name.begin(), name.end(), [](char c) { return c == '.'; }))
return false;
bool is_folder;

View File

@ -1060,14 +1060,14 @@ unsigned int NetPlayServer::OnData(sf::Packet& packet, Client& player)
{
// we have all records for this frame
if (!std::ranges::all_of(timebases, [&](std::pair<PlayerId, u64> pair) {
if (!std::all_of(timebases.begin(), timebases.end(), [&](std::pair<PlayerId, u64> pair) {
return pair.second == timebases[0].second;
}))
{
int pid_to_blame = 0;
for (auto pair : timebases)
{
if (std::ranges::all_of(timebases, [&](std::pair<PlayerId, u64> other) {
if (std::all_of(timebases.begin(), timebases.end(), [&](std::pair<PlayerId, u64> other) {
return other.first == pair.first || other.second != pair.second;
}))
{
@ -1467,12 +1467,14 @@ bool NetPlayServer::SetupNetSettings()
bool NetPlayServer::DoAllPlayersHaveIPLDump() const
{
return std::ranges::all_of(m_players, [](const auto& p) { return p.second.has_ipl_dump; });
return std::all_of(m_players.begin(), m_players.end(),
[](const auto& p) { return p.second.has_ipl_dump; });
}
bool NetPlayServer::DoAllPlayersHaveHardwareFMA() const
{
return std::ranges::all_of(m_players, [](const auto& p) { return p.second.has_hardware_fma; });
return std::all_of(m_players.begin(), m_players.end(),
[](const auto& p) { return p.second.has_hardware_fma; });
}
struct SaveSyncInfo
@ -2232,8 +2234,8 @@ bool NetPlayServer::PlayerHasControllerMapped(const PlayerId pid) const
{
const auto mapping_matches_player_id = [pid](const PlayerId& mapping) { return mapping == pid; };
return std::ranges::any_of(m_pad_map, mapping_matches_player_id) ||
std::ranges::any_of(m_wiimote_map, mapping_matches_player_id);
return std::any_of(m_pad_map.begin(), m_pad_map.end(), mapping_matches_player_id) ||
std::any_of(m_wiimote_map.begin(), m_wiimote_map.end(), mapping_matches_player_id);
}
void NetPlayServer::AssignNewUserAPad(const Client& player)

View File

@ -371,7 +371,7 @@ bool MemChecks::OverlapsMemcheck(u32 address, u32 length) const
const u32 page_end_suffix = length - 1;
const u32 page_end_address = address | page_end_suffix;
return std::ranges::any_of(m_mem_checks, [&](const auto& mc) {
return std::any_of(m_mem_checks.cbegin(), m_mem_checks.cend(), [&](const auto& mc) {
return ((mc.start_address | page_end_suffix) == page_end_address ||
(mc.end_address | page_end_suffix) == page_end_address) ||
((mc.start_address | page_end_suffix) < page_end_address &&

View File

@ -136,14 +136,15 @@ static double CallstackFunc(expr_func* f, vec_expr_t* args, void* c)
if (!std::isnan(num))
{
u32 address = static_cast<u32>(num);
return std::ranges::any_of(stack, [address](const auto& s) { return s.vAddress == address; });
return std::any_of(stack.begin(), stack.end(),
[address](const auto& s) { return s.vAddress == address; });
}
const char* cstr = expr_get_str(&vec_nth(args, 0));
if (cstr != nullptr)
{
return std::ranges::any_of(
stack, [cstr](const auto& s) { return s.Name.find(cstr) != std::string::npos; });
return std::any_of(stack.begin(), stack.end(),
[cstr](const auto& s) { return s.Name.find(cstr) != std::string::npos; });
}
return 0;

View File

@ -350,8 +350,8 @@ void Jit64::Shutdown()
void Jit64::FallBackToInterpreter(UGeckoInstruction inst)
{
gpr.Flush(BitSet32(0xFFFFFFFF), RegCache::IgnoreDiscardedRegisters::Yes);
fpr.Flush(BitSet32(0xFFFFFFFF), RegCache::IgnoreDiscardedRegisters::Yes);
gpr.Flush();
fpr.Flush();
if (js.op->canEndBlock)
{

View File

@ -644,20 +644,6 @@ void Jit64::fselx(UGeckoInstruction inst)
if (cpu_info.bAVX)
{
// Prefer BLENDVPD over VBLENDVPD if the latter doesn't save any
// instructions.
//
// VBLENDVPD allows separate source and destination registers, which can
// eliminate a MOVAPD/MOVSD. However, on Intel since Skylake, VBLENDVPD
// takes additional uops to execute compared to BLENDVPD (according to
// https://uops.info). On AMD and older Intel microarchitectures there is no
// difference.
if (d == c)
{
BLENDVPD(Rd, Rb);
return;
}
X64Reg src1 = XMM1;
if (Rc.IsSimpleReg())
{
@ -668,7 +654,7 @@ void Jit64::fselx(UGeckoInstruction inst)
MOVAPD(XMM1, Rc);
}
if (packed)
if (d == c || packed)
{
VBLENDVPD(Rd, src1, Rb, XMM0);
return;

View File

@ -369,8 +369,10 @@ RCForkGuard RegCache::Fork()
void RegCache::Discard(BitSet32 pregs)
{
ASSERT_MSG(DYNA_REC, std::ranges::none_of(m_xregs, &X64CachedReg::IsLocked),
"Someone forgot to unlock a X64 reg");
ASSERT_MSG(
DYNA_REC,
std::none_of(m_xregs.begin(), m_xregs.end(), [](const auto& x) { return x.IsLocked(); }),
"Someone forgot to unlock a X64 reg");
for (preg_t i : pregs)
{
@ -389,10 +391,12 @@ void RegCache::Discard(BitSet32 pregs)
}
}
void RegCache::Flush(BitSet32 pregs, IgnoreDiscardedRegisters ignore_discarded_registers)
void RegCache::Flush(BitSet32 pregs)
{
ASSERT_MSG(DYNA_REC, std::ranges::none_of(m_xregs, &X64CachedReg::IsLocked),
"Someone forgot to unlock a X64 reg");
ASSERT_MSG(
DYNA_REC,
std::none_of(m_xregs.begin(), m_xregs.end(), [](const auto& x) { return x.IsLocked(); }),
"Someone forgot to unlock a X64 reg");
for (preg_t i : pregs)
{
@ -406,8 +410,7 @@ void RegCache::Flush(BitSet32 pregs, IgnoreDiscardedRegisters ignore_discarded_r
case PPCCachedReg::LocationType::Default:
break;
case PPCCachedReg::LocationType::Discarded:
ASSERT_MSG(DYNA_REC, ignore_discarded_registers != IgnoreDiscardedRegisters::No,
"Attempted to flush discarded PPC reg {}", i);
ASSERT_MSG(DYNA_REC, false, "Attempted to flush discarded PPC reg {}", i);
break;
case PPCCachedReg::LocationType::SpeculativeImmediate:
// We can have a cached value without a host register through speculative constants.
@ -455,8 +458,9 @@ void RegCache::Commit()
bool RegCache::IsAllUnlocked() const
{
return std::ranges::none_of(m_regs, &PPCCachedReg::IsLocked) &&
std::ranges::none_of(m_xregs, &X64CachedReg::IsLocked) && !IsAnyConstraintActive();
return std::none_of(m_regs.begin(), m_regs.end(), [](const auto& r) { return r.IsLocked(); }) &&
std::none_of(m_xregs.begin(), m_xregs.end(), [](const auto& x) { return x.IsLocked(); }) &&
!IsAnyConstraintActive();
}
void RegCache::PreloadRegisters(BitSet32 to_preload)
@ -749,5 +753,6 @@ void RegCache::Realize(preg_t preg)
bool RegCache::IsAnyConstraintActive() const
{
return std::ranges::any_of(m_constraints, &RCConstraint::IsActive);
return std::any_of(m_constraints.begin(), m_constraints.end(),
[](const auto& c) { return c.IsActive(); });
}

View File

@ -126,12 +126,6 @@ public:
MaintainState,
};
enum class IgnoreDiscardedRegisters
{
No,
Yes,
};
explicit RegCache(Jit64& jit);
virtual ~RegCache() = default;
@ -174,8 +168,7 @@ public:
RCForkGuard Fork();
void Discard(BitSet32 pregs);
void Flush(BitSet32 pregs = BitSet32::AllTrue(32),
IgnoreDiscardedRegisters ignore_discarded_registers = IgnoreDiscardedRegisters::No);
void Flush(BitSet32 pregs = BitSet32::AllTrue(32));
void Reset(BitSet32 pregs);
void Revert();
void Commit();

View File

@ -256,8 +256,8 @@ void JitArm64::Shutdown()
void JitArm64::FallBackToInterpreter(UGeckoInstruction inst)
{
FlushCarry();
gpr.Flush(FlushMode::All, ARM64Reg::INVALID_REG, IgnoreDiscardedRegisters::Yes);
fpr.Flush(FlushMode::All, ARM64Reg::INVALID_REG, IgnoreDiscardedRegisters::Yes);
gpr.Flush(FlushMode::All, ARM64Reg::INVALID_REG);
fpr.Flush(FlushMode::All, ARM64Reg::INVALID_REG);
if (js.op->canEndBlock)
{

View File

@ -1394,34 +1394,23 @@ void JitArm64::subfic(UGeckoInstruction inst)
else
{
const bool will_read = d == a;
const bool is_zero = imm == 0;
gpr.BindToRegister(d, will_read);
// d = imm - a
ARM64Reg RD = gpr.R(d);
if (imm == -1)
{
// d = -1 - a = ~a
MVN(RD, gpr.R(a));
// CA is always set in this case
ComputeCarry(true);
}
else
{
const bool is_zero = imm == 0;
// d = imm - a
Arm64GPRCache::ScopedARM64Reg WA(ARM64Reg::WZR);
if (!is_zero)
{
Arm64GPRCache::ScopedARM64Reg WA(ARM64Reg::WZR);
if (!is_zero)
{
WA = will_read ? gpr.GetScopedReg() : Arm64GPRCache::ScopedARM64Reg(RD);
MOVI2R(WA, imm);
}
CARRY_IF_NEEDED(SUB, SUBS, RD, WA, gpr.R(a));
WA = will_read ? gpr.GetScopedReg() : Arm64GPRCache::ScopedARM64Reg(RD);
MOVI2R(WA, imm);
}
ComputeCarry();
CARRY_IF_NEEDED(SUB, SUBS, RD, WA, gpr.R(a));
}
ComputeCarry();
}
}

View File

@ -181,8 +181,7 @@ void JitArm64::SafeStoreFromReg(s32 dest, u32 value, s32 regOffset, u32 flags, s
if (!jo.fastmem)
gpr.Lock(ARM64Reg::W0);
// Don't materialize zero.
ARM64Reg RS = gpr.IsImm(value, 0) ? ARM64Reg::WZR : gpr.R(value);
ARM64Reg RS = gpr.R(value);
ARM64Reg reg_dest = ARM64Reg::INVALID_REG;
ARM64Reg reg_off = ARM64Reg::INVALID_REG;

View File

@ -7,7 +7,6 @@
#include "Common/CommonTypes.h"
#include "Common/Config/Config.h"
#include "Common/StringUtil.h"
#include "Common/Unreachable.h"
#include "Core/Config/SessionSettings.h"
#include "Core/ConfigManager.h"
@ -338,12 +337,8 @@ void JitArm64::ps_sel(UGeckoInstruction inst)
const auto V0Q = fpr.GetScopedReg();
const ARM64Reg V0 = reg_encoder(V0Q);
m_float_emit.FCMGE(size, V0, VA);
if (d == b)
m_float_emit.BIT(VD, VC, V0);
else if (d == c)
m_float_emit.BIF(VD, VB, V0);
else
Common::Unreachable();
m_float_emit.BSL(V0, VC, VB);
m_float_emit.MOV(VD, V0);
}
ASSERT_MSG(DYNA_REC, singles == (fpr.IsSingle(a) && fpr.IsSingle(b) && fpr.IsSingle(c)),

View File

@ -241,16 +241,12 @@ void Arm64GPRCache::FlushRegister(size_t index, FlushMode mode, ARM64Reg tmp_reg
}
}
void Arm64GPRCache::FlushRegisters(BitSet32 regs, FlushMode mode, ARM64Reg tmp_reg,
IgnoreDiscardedRegisters ignore_discarded_registers)
void Arm64GPRCache::FlushRegisters(BitSet32 regs, FlushMode mode, ARM64Reg tmp_reg)
{
for (auto iter = regs.begin(); iter != regs.end(); ++iter)
{
const int i = *iter;
ASSERT_MSG(DYNA_REC,
ignore_discarded_registers != IgnoreDiscardedRegisters::No ||
m_guest_registers[GUEST_GPR_OFFSET + i].GetType() != RegType::Discarded,
ASSERT_MSG(DYNA_REC, m_guest_registers[GUEST_GPR_OFFSET + i].GetType() != RegType::Discarded,
"Attempted to flush discarded register");
if (i + 1 < int(GUEST_GPR_COUNT) && regs[i + 1])
@ -292,14 +288,11 @@ void Arm64GPRCache::FlushRegisters(BitSet32 regs, FlushMode mode, ARM64Reg tmp_r
}
}
void Arm64GPRCache::FlushCRRegisters(BitSet8 regs, FlushMode mode, ARM64Reg tmp_reg,
IgnoreDiscardedRegisters ignore_discarded_registers)
void Arm64GPRCache::FlushCRRegisters(BitSet8 regs, FlushMode mode, ARM64Reg tmp_reg)
{
for (int i : regs)
{
ASSERT_MSG(DYNA_REC,
ignore_discarded_registers != IgnoreDiscardedRegisters::No ||
m_guest_registers[GUEST_CR_OFFSET + i].GetType() != RegType::Discarded,
ASSERT_MSG(DYNA_REC, m_guest_registers[GUEST_CR_OFFSET + i].GetType() != RegType::Discarded,
"Attempted to flush discarded register");
FlushRegister(GUEST_CR_OFFSET + i, mode, tmp_reg);
@ -325,11 +318,10 @@ void Arm64GPRCache::ResetCRRegisters(BitSet8 regs)
}
}
void Arm64GPRCache::Flush(FlushMode mode, ARM64Reg tmp_reg,
IgnoreDiscardedRegisters ignore_discarded_registers)
void Arm64GPRCache::Flush(FlushMode mode, ARM64Reg tmp_reg)
{
FlushRegisters(BitSet32(0xFFFFFFFF), mode, tmp_reg, ignore_discarded_registers);
FlushCRRegisters(BitSet8(0xFF), mode, tmp_reg, ignore_discarded_registers);
FlushRegisters(BitSet32(0xFFFFFFFF), mode, tmp_reg);
FlushCRRegisters(BitSet8(0xFF), mode, tmp_reg);
}
ARM64Reg Arm64GPRCache::R(const GuestRegInfo& guest_reg)
@ -506,19 +498,14 @@ Arm64FPRCache::Arm64FPRCache() : Arm64RegCache(GUEST_FPR_COUNT)
{
}
void Arm64FPRCache::Flush(FlushMode mode, ARM64Reg tmp_reg,
IgnoreDiscardedRegisters ignore_discarded_registers)
void Arm64FPRCache::Flush(FlushMode mode, ARM64Reg tmp_reg)
{
for (size_t i = 0; i < m_guest_registers.size(); ++i)
{
const RegType reg_type = m_guest_registers[i].GetType();
if (reg_type == RegType::Discarded)
{
ASSERT_MSG(DYNA_REC, ignore_discarded_registers != IgnoreDiscardedRegisters::No,
"Attempted to flush discarded register");
}
else if (reg_type != RegType::NotLoaded && reg_type != RegType::Immediate)
if (reg_type != RegType::NotLoaded && reg_type != RegType::Discarded &&
reg_type != RegType::Immediate)
{
FlushRegister(i, mode, tmp_reg);
}

View File

@ -81,12 +81,6 @@ enum class FlushMode : bool
MaintainState,
};
enum class IgnoreDiscardedRegisters
{
No,
Yes,
};
class OpArg
{
public:
@ -175,8 +169,7 @@ public:
// Flushes the register cache in different ways depending on the mode.
// A temporary register must be supplied when flushing GPRs with FlushMode::MaintainState,
// but in other cases it can be set to ARM64Reg::INVALID_REG when convenient for the caller.
virtual void Flush(FlushMode mode, Arm64Gen::ARM64Reg tmp_reg,
IgnoreDiscardedRegisters ignore_discarded_registers) = 0;
virtual void Flush(FlushMode mode, Arm64Gen::ARM64Reg tmp_reg) = 0;
virtual BitSet32 GetCallerSavedUsed() const = 0;
@ -322,9 +315,7 @@ public:
// Flushes the register cache in different ways depending on the mode.
// A temporary register must be supplied when flushing GPRs with FlushMode::MaintainState,
// but in other cases it can be set to ARM64Reg::INVALID_REG when convenient for the caller.
void Flush(
FlushMode mode, Arm64Gen::ARM64Reg tmp_reg,
IgnoreDiscardedRegisters ignore_discarded_registers = IgnoreDiscardedRegisters::No) override;
void Flush(FlushMode mode, Arm64Gen::ARM64Reg tmp_reg) override;
// Returns a guest GPR inside of a host register.
// Will dump an immediate to the host register as well.
@ -390,12 +381,12 @@ public:
void StoreRegisters(BitSet32 regs, Arm64Gen::ARM64Reg tmp_reg = Arm64Gen::ARM64Reg::INVALID_REG)
{
FlushRegisters(regs, FlushMode::All, tmp_reg, IgnoreDiscardedRegisters::No);
FlushRegisters(regs, FlushMode::All, tmp_reg);
}
void StoreCRRegisters(BitSet8 regs, Arm64Gen::ARM64Reg tmp_reg = Arm64Gen::ARM64Reg::INVALID_REG)
{
FlushCRRegisters(regs, FlushMode::All, tmp_reg, IgnoreDiscardedRegisters::No);
FlushCRRegisters(regs, FlushMode::All, tmp_reg);
}
void DiscardCRRegisters(BitSet8 regs);
@ -430,10 +421,8 @@ private:
void SetImmediate(const GuestRegInfo& guest_reg, u32 imm, bool dirty);
void BindToRegister(const GuestRegInfo& guest_reg, bool will_read, bool will_write = true);
void FlushRegisters(BitSet32 regs, FlushMode mode, Arm64Gen::ARM64Reg tmp_reg,
IgnoreDiscardedRegisters ignore_discarded_registers);
void FlushCRRegisters(BitSet8 regs, FlushMode mode, Arm64Gen::ARM64Reg tmp_reg,
IgnoreDiscardedRegisters ignore_discarded_registers);
void FlushRegisters(BitSet32 regs, FlushMode mode, Arm64Gen::ARM64Reg tmp_reg);
void FlushCRRegisters(BitSet8 regs, FlushMode mode, Arm64Gen::ARM64Reg tmp_reg);
};
class Arm64FPRCache : public Arm64RegCache
@ -443,9 +432,7 @@ public:
// Flushes the register cache in different ways depending on the mode.
// The temporary register can be set to ARM64Reg::INVALID_REG when convenient for the caller.
void Flush(
FlushMode mode, Arm64Gen::ARM64Reg tmp_reg,
IgnoreDiscardedRegisters ignore_discarded_registers = IgnoreDiscardedRegisters::No) override;
void Flush(FlushMode mode, Arm64Gen::ARM64Reg tmp_reg) override;
// Returns a guest register inside of a host register
// Will dump an immediate to the host register as well

View File

@ -257,12 +257,6 @@ void ByteswapAfterLoad(ARM64XEmitter* emit, ARM64FloatEmitter* float_emit, ARM64
ARM64Reg ByteswapBeforeStore(ARM64XEmitter* emit, ARM64FloatEmitter* float_emit, ARM64Reg tmp_reg,
ARM64Reg src_reg, u32 flags, bool want_reversed)
{
// Byteswapping zero is still zero.
// We'd typically expect a writable register to be passed in, but recognize
// WZR for optimization purposes.
if ((flags & BackPatchInfo::FLAG_FLOAT) == 0 && src_reg == ARM64Reg::WZR)
return ARM64Reg::WZR;
ARM64Reg dst_reg = src_reg;
if (want_reversed == !(flags & BackPatchInfo::FLAG_REVERSE))

View File

@ -112,7 +112,7 @@ JitBase::~JitBase()
bool JitBase::DoesConfigNeedRefresh()
{
return std::ranges::any_of(JIT_SETTINGS, [this](const auto& pair) {
return std::any_of(JIT_SETTINGS.begin(), JIT_SETTINGS.end(), [this](const auto& pair) {
return this->*pair.first != Config::Get(*pair.second);
});
}

View File

@ -191,7 +191,7 @@ static void AnalyzeFunction2(PPCSymbolDB* func_db, Common::Symbol* func)
{
u32 flags = func->flags;
bool nonleafcall = std::ranges::any_of(func->calls, [&](const auto& call) {
bool nonleafcall = std::any_of(func->calls.begin(), func->calls.end(), [&](const auto& call) {
const Common::Symbol* const called_func = func_db->GetSymbolFromAddr(call.function);
return called_func && (called_func->flags & Common::FFLAG_LEAF) == 0;
});

View File

@ -49,8 +49,7 @@ Common::Symbol* PPCSymbolDB::AddFunction(const Core::CPUThreadGuard& guard, u32
}
void PPCSymbolDB::AddKnownSymbol(const Core::CPUThreadGuard& guard, u32 startAddr, u32 size,
const std::string& name, const std::string& object_name,
Common::Symbol::Type type)
const std::string& name, Common::Symbol::Type type)
{
auto iter = m_functions.find(startAddr);
if (iter != m_functions.end())
@ -58,7 +57,6 @@ void PPCSymbolDB::AddKnownSymbol(const Core::CPUThreadGuard& guard, u32 startAdd
// already got it, let's just update name, checksum & size to be sure.
Common::Symbol* tempfunc = &iter->second;
tempfunc->Rename(name);
tempfunc->object_name = object_name;
tempfunc->hash = HashSignatureDB::ComputeCodeChecksum(guard, startAddr, startAddr + size - 4);
tempfunc->type = type;
tempfunc->size = size;
@ -67,7 +65,6 @@ void PPCSymbolDB::AddKnownSymbol(const Core::CPUThreadGuard& guard, u32 startAdd
{
// new symbol. run analyze.
auto& new_symbol = m_functions.emplace(startAddr, name).first->second;
new_symbol.object_name = object_name;
new_symbol.type = type;
new_symbol.address = startAddr;
@ -402,13 +399,6 @@ bool PPCSymbolDB::LoadMap(const Core::CPUThreadGuard& guard, const std::string&
if (name[strlen(name) - 1] == '\r')
name[strlen(name) - 1] = 0;
// Split the current name string into separate parts, and get the object name
// if it exists.
const std::vector<std::string> parts = SplitString(name, '\t');
const std::string name_string(StripWhitespace(parts[0]));
const std::string object_filename_string =
parts.size() > 1 ? std::string(StripWhitespace(parts[1])) : "";
// Check if this is a valid entry.
if (strlen(name) > 0)
{
@ -445,7 +435,7 @@ bool PPCSymbolDB::LoadMap(const Core::CPUThreadGuard& guard, const std::string&
if (good)
{
++good_count;
AddKnownSymbol(guard, vaddress, size, name_string, object_filename_string, type);
AddKnownSymbol(guard, vaddress, size, name, type);
}
else
{
@ -483,13 +473,8 @@ bool PPCSymbolDB::SaveSymbolMap(const std::string& filename) const
for (const auto& symbol : function_symbols)
{
// Write symbol address, size, virtual address, alignment, name
std::string line = fmt::format("{0:08x} {1:06x} {2:08x} {3} {4}", symbol->address, symbol->size,
symbol->address, 0, symbol->name);
// Also write the object name if it exists
if (!symbol->object_name.empty())
line += fmt::format(" \t{0}", symbol->object_name);
line += "\n";
f.WriteString(line);
f.WriteString(fmt::format("{0:08x} {1:08x} {2:08x} {3} {4}\n", symbol->address, symbol->size,
symbol->address, 0, symbol->name));
}
// Write .data section
@ -497,13 +482,8 @@ bool PPCSymbolDB::SaveSymbolMap(const std::string& filename) const
for (const auto& symbol : data_symbols)
{
// Write symbol address, size, virtual address, alignment, name
std::string line = fmt::format("{0:08x} {1:06x} {2:08x} {3} {4}", symbol->address, symbol->size,
symbol->address, 0, symbol->name);
// Also write the object name if it exists
if (!symbol->object_name.empty())
line += fmt::format(" \t{0}", symbol->object_name);
line += "\n";
f.WriteString(line);
f.WriteString(fmt::format("{0:08x} {1:08x} {2:08x} {3} {4}\n", symbol->address, symbol->size,
symbol->address, 0, symbol->name));
}
return true;

View File

@ -23,7 +23,7 @@ public:
Common::Symbol* AddFunction(const Core::CPUThreadGuard& guard, u32 start_addr) override;
void AddKnownSymbol(const Core::CPUThreadGuard& guard, u32 startAddr, u32 size,
const std::string& name, const std::string& object_name,
const std::string& name,
Common::Symbol::Type type = Common::Symbol::Type::Function);
Common::Symbol* GetSymbolFromAddr(u32 addr) override;

View File

@ -223,14 +223,15 @@ bool IsTitleInstalled(u64 title_id)
// Since this isn't IOS and we only need a simple way to figure out if a title is installed,
// we make the (reasonable) assumption that having more than just the TMD in the content
// directory means that the title is installed.
return std::ranges::any_of(*entries, [](const std::string& file) { return file != "title.tmd"; });
return std::any_of(entries->begin(), entries->end(),
[](const std::string& file) { return file != "title.tmd"; });
}
bool IsTMDImported(IOS::HLE::FS::FileSystem& fs, u64 title_id)
{
const auto entries = fs.ReadDirectory(0, 0, Common::GetTitleContentPath(title_id));
return entries &&
std::ranges::any_of(*entries, [](const std::string& file) { return file == "title.tmd"; });
return entries && std::any_of(entries->begin(), entries->end(),
[](const std::string& file) { return file == "title.tmd"; });
}
IOS::ES::TMDReader FindBackupTMD(IOS::HLE::FS::FileSystem& fs, u64 title_id)
@ -946,8 +947,8 @@ static NANDCheckResult CheckNAND(IOS::HLE::Kernel& ios, bool repair)
}
const auto installed_contents = es.GetStoredContentsFromTMD(tmd);
const bool is_installed = std::ranges::any_of(
installed_contents, [](const auto& content) { return !content.IsShared(); });
const bool is_installed = std::any_of(installed_contents.begin(), installed_contents.end(),
[](const auto& content) { return !content.IsShared(); });
if (is_installed && installed_contents != tmd.GetContents() &&
(tmd.GetTitleFlags() & IOS::ES::TitleFlags::TITLE_TYPE_DATA) == 0)

View File

@ -13,7 +13,6 @@
#include "Common/CommonTypes.h"
#include "Common/MathUtil.h"
#include "Common/StringUtil.h"
#include "DiscIO/Blob.h"
#include "DiscIO/Filesystem.h"
#include "DiscIO/Volume.h"
@ -40,7 +39,8 @@ std::string NameForPartitionType(u32 partition_type, bool include_prefix)
static_cast<char>((partition_type >> 16) & 0xFF),
static_cast<char>((partition_type >> 8) & 0xFF),
static_cast<char>(partition_type & 0xFF)};
if (std::ranges::all_of(type_as_game_id, Common::IsAlnum))
if (std::all_of(type_as_game_id.cbegin(), type_as_game_id.cend(),
[](char c) { return std::isalnum(c, std::locale::classic()); }))
{
return include_prefix ? "P-" + type_as_game_id : type_as_game_id;
}

View File

@ -240,9 +240,11 @@ bool NANDImporter::ExtractCertificates()
for (const PEMCertificate& certificate : certificates)
{
const auto search_result = std::ranges::search(content_bytes, certificate.search_bytes);
const auto search_result =
std::search(content_bytes.begin(), content_bytes.end(), certificate.search_bytes.begin(),
certificate.search_bytes.end());
if (search_result.empty())
if (search_result == content_bytes.end())
{
ERROR_LOG_FMT(DISCIO, "ExtractCertificates: Could not find offset for certficate '{}'",
certificate.filename);
@ -250,8 +252,7 @@ bool NANDImporter::ExtractCertificates()
}
const std::string pem_file_path = m_nand_root + std::string(certificate.filename);
const ptrdiff_t certificate_offset =
std::distance(content_bytes.begin(), search_result.begin());
const ptrdiff_t certificate_offset = std::distance(content_bytes.begin(), search_result);
constexpr int min_offset = 2;
if (certificate_offset < min_offset)
{

View File

@ -104,7 +104,7 @@ FileDataLoaderHostFS::MakeAbsoluteFromRelative(std::string_view external_relativ
result.pop_back();
result.pop_back();
}
else if (std::ranges::all_of(element, [](char c) { return c == '.'; }))
else if (std::all_of(element.begin(), element.end(), [](char c) { return c == '.'; }))
{
// This is a triple, quadruple, etc. dot.
// Some file systems treat this as several 'up' path traversals, but Riivolution does not.

View File

@ -729,15 +729,16 @@ bool VolumeVerifier::ShouldHaveInstallPartition() const
static constexpr std::array<std::string_view, 4> dragon_quest_x = {"S4MJGD", "S4SJGD", "S6TJGD",
"SDQJGD"};
const std::string& game_id = m_volume.GetGameID();
return std::ranges::any_of(dragon_quest_x,
[&game_id](std::string_view x) { return x == game_id; });
return std::any_of(dragon_quest_x.cbegin(), dragon_quest_x.cend(),
[&game_id](std::string_view x) { return x == game_id; });
}
bool VolumeVerifier::ShouldHaveMasterpiecePartitions() const
{
static constexpr std::array<std::string_view, 4> ssbb = {"RSBE01", "RSBJ01", "RSBK01", "RSBP01"};
const std::string& game_id = m_volume.GetGameID();
return std::ranges::any_of(ssbb, [&game_id](std::string_view x) { return x == game_id; });
return std::any_of(ssbb.cbegin(), ssbb.cend(),
[&game_id](std::string_view x) { return x == game_id; });
}
bool VolumeVerifier::ShouldBeDualLayer() const
@ -1038,7 +1039,7 @@ void VolumeVerifier::CheckSuperPaperMario()
if (!m_volume.Read(offset, length, data.data(), partition))
return;
if (std::ranges::any_of(data, [](u8 x) { return x != 0; }))
if (std::any_of(data.cbegin(), data.cend(), [](u8 x) { return x != 0; }))
{
AddProblem(Severity::High,
Common::GetStringT("Some padding data that should be zero is not zero. "

View File

@ -176,7 +176,7 @@ IOS::ES::TicketReader VolumeWAD::GetTicketWithFixedCommonKey() const
return m_ticket;
const std::vector<u8> sig = m_ticket.GetSignatureData();
if (!std::ranges::all_of(sig, [](u8 a) { return a == 0; }))
if (!std::all_of(sig.cbegin(), sig.cend(), [](u8 a) { return a == 0; }))
{
// This does not look like a typical "invalid common key index" ticket, so let's assume
// the index is correct. This saves some time when reading properly signed titles.

View File

@ -1126,7 +1126,7 @@ bool WIARVZFileReader<RVZ>::TryReuse(std::map<ReuseID, GroupEntry>* reusable_gro
static bool AllAre(const std::vector<u8>& data, u8 x)
{
return std::ranges::all_of(data, [x](u8 y) { return x == y; });
return std::all_of(data.begin(), data.end(), [x](u8 y) { return x == y; });
}
static bool AllAre(const u8* begin, const u8* end, u8 x)
@ -1379,8 +1379,8 @@ WIARVZFileReader<RVZ>::ProcessAndCompress(CompressThreadState* state, CompressPa
}
}
if (!std::ranges::all_of(output_entries,
[](const auto& entry) { return entry.reused_group.has_value(); }))
if (!std::all_of(output_entries.begin(), output_entries.end(),
[](const OutputParametersEntry& entry) { return entry.reused_group; }))
{
const u64 number_of_exception_lists =
chunks_per_wii_group == 1 ? exception_lists_per_chunk : chunks;

View File

@ -52,7 +52,6 @@ add_executable(dolphin-emu
Config/ConfigControls/ConfigBool.h
Config/ConfigControls/ConfigChoice.cpp
Config/ConfigControls/ConfigChoice.h
Config/ConfigControls/ConfigControl.h
Config/ConfigControls/ConfigInteger.cpp
Config/ConfigControls/ConfigInteger.h
Config/ConfigControls/ConfigRadio.cpp

View File

@ -3,28 +3,31 @@
#include "DolphinQt/Config/ConfigControls/ConfigBool.h"
#include <QEvent>
#include <QFont>
#include <QSignalBlocker>
#include "Common/Config/Config.h"
#include "DolphinQt/Settings.h"
ConfigBool::ConfigBool(const QString& label, const Config::Info<bool>& setting, bool reverse)
: ConfigBool(label, setting, nullptr, reverse)
: ToolTipCheckBox(label), m_setting(setting), m_reverse(reverse)
{
}
ConfigBool::ConfigBool(const QString& label, const Config::Info<bool>& setting,
Config::Layer* layer, bool reverse)
: ConfigControl(label, setting.GetLocation(), layer), m_setting(setting), m_reverse(reverse)
{
setChecked(ReadValue(setting) ^ reverse);
connect(this, &QCheckBox::toggled, this, &ConfigBool::Update);
setChecked(Config::Get(m_setting) ^ reverse);
connect(&Settings::Instance(), &Settings::ConfigChanged, this, [this] {
QFont bf = font();
bf.setBold(Config::GetActiveLayerForConfig(m_setting) != Config::LayerType::Base);
setFont(bf);
const QSignalBlocker blocker(this);
setChecked(Config::Get(m_setting) ^ m_reverse);
});
}
void ConfigBool::Update()
{
const bool value = static_cast<bool>(isChecked() ^ m_reverse);
SaveValue(m_setting, value);
}
void ConfigBool::OnConfigChanged()
{
setChecked(ReadValue(m_setting) ^ m_reverse);
Config::SetBaseOrCurrent(m_setting, static_cast<bool>(isChecked() ^ m_reverse));
}

View File

@ -3,25 +3,23 @@
#pragma once
#include "DolphinQt/Config/ConfigControls/ConfigControl.h"
#include "DolphinQt/Config/ToolTipControls/ToolTipCheckBox.h"
#include "Common/Config/ConfigInfo.h"
namespace Config
{
template <typename T>
class Info;
}
class ConfigBool final : public ConfigControl<ToolTipCheckBox>
class ConfigBool : public ToolTipCheckBox
{
Q_OBJECT
public:
ConfigBool(const QString& label, const Config::Info<bool>& setting, bool reverse = false);
ConfigBool(const QString& label, const Config::Info<bool>& setting, Config::Layer* layer,
bool reverse = false);
protected:
void OnConfigChanged() override;
private:
void Update();
const Config::Info<bool> m_setting;
const Config::Info<bool>& m_setting;
bool m_reverse;
};

View File

@ -5,168 +5,85 @@
#include <QSignalBlocker>
ConfigChoice::ConfigChoice(const QStringList& options, const Config::Info<int>& setting,
Config::Layer* layer)
: ConfigControl(setting.GetLocation(), layer), m_setting(setting)
#include "Common/Config/Config.h"
#include "DolphinQt/Settings.h"
ConfigChoice::ConfigChoice(const QStringList& options, const Config::Info<int>& setting)
: m_setting(setting)
{
addItems(options);
setCurrentIndex(ReadValue(setting));
connect(this, &QComboBox::currentIndexChanged, this, &ConfigChoice::Update);
setCurrentIndex(Config::Get(m_setting));
connect(&Settings::Instance(), &Settings::ConfigChanged, this, [this] {
QFont bf = font();
bf.setBold(Config::GetActiveLayerForConfig(m_setting) != Config::LayerType::Base);
setFont(bf);
const QSignalBlocker blocker(this);
setCurrentIndex(Config::Get(m_setting));
});
}
void ConfigChoice::Update(int choice)
{
SaveValue(m_setting, choice);
}
void ConfigChoice::OnConfigChanged()
{
setCurrentIndex(ReadValue(m_setting));
Config::SetBaseOrCurrent(m_setting, choice);
}
ConfigStringChoice::ConfigStringChoice(const std::vector<std::string>& options,
const Config::Info<std::string>& setting,
Config::Layer* layer)
: ConfigControl(setting.GetLocation(), layer), m_setting(setting), m_text_is_data(true)
const Config::Info<std::string>& setting)
: m_setting(setting), m_text_is_data(true)
{
for (const auto& op : options)
addItem(QString::fromStdString(op));
Connect();
Load();
connect(this, &QComboBox::currentIndexChanged, this, &ConfigStringChoice::Update);
}
ConfigStringChoice::ConfigStringChoice(const std::vector<std::pair<QString, QString>>& options,
const Config::Info<std::string>& setting,
Config::Layer* layer)
: ConfigControl(setting.GetLocation(), layer), m_setting(setting), m_text_is_data(false)
const Config::Info<std::string>& setting)
: m_setting(setting), m_text_is_data(false)
{
for (const auto& [option_text, option_data] : options)
addItem(option_text, option_data);
connect(this, &QComboBox::currentIndexChanged, this, &ConfigStringChoice::Update);
Connect();
Load();
}
void ConfigStringChoice::Connect()
{
const auto on_config_changed = [this]() {
QFont bf = font();
bf.setBold(Config::GetActiveLayerForConfig(m_setting) != Config::LayerType::Base);
setFont(bf);
Load();
};
connect(&Settings::Instance(), &Settings::ConfigChanged, this, on_config_changed);
connect(this, &QComboBox::currentIndexChanged, this, &ConfigStringChoice::Update);
}
void ConfigStringChoice::Update(int index)
{
if (m_text_is_data)
SaveValue(m_setting, itemText(index).toStdString());
{
Config::SetBaseOrCurrent(m_setting, itemText(index).toStdString());
}
else
SaveValue(m_setting, itemData(index).toString().toStdString());
{
Config::SetBaseOrCurrent(m_setting, itemData(index).toString().toStdString());
}
}
void ConfigStringChoice::Load()
{
const QString setting_value = QString::fromStdString(ReadValue(m_setting));
const QString setting_value = QString::fromStdString(Config::Get(m_setting));
const int index = m_text_is_data ? findText(setting_value) : findData(setting_value);
// This can be called publicly.
const QSignalBlocker block(this);
setCurrentIndex(index);
}
void ConfigStringChoice::OnConfigChanged()
{
Load();
}
ConfigComplexChoice::ConfigComplexChoice(const InfoVariant setting1, const InfoVariant setting2,
Config::Layer* layer)
: m_setting1(setting1), m_setting2(setting2), m_layer(layer)
{
connect(&Settings::Instance(), &Settings::ConfigChanged, this, &ConfigComplexChoice::Refresh);
connect(this, &QComboBox::currentIndexChanged, this, &ConfigComplexChoice::SaveValue);
}
void ConfigComplexChoice::Refresh()
{
auto& location = GetLocation();
QFont bf = font();
if (m_layer != nullptr)
{
bf.setBold(m_layer->Exists(location.first) || m_layer->Exists(location.second));
}
else
{
bf.setBold(Config::GetActiveLayerForConfig(location.first) != Config::LayerType::Base ||
Config::GetActiveLayerForConfig(location.second) != Config::LayerType::Base);
}
setFont(bf);
UpdateComboIndex();
}
void ConfigComplexChoice::Add(const QString& name, const OptionVariant option1,
const OptionVariant option2)
{
const QSignalBlocker blocker(this);
addItem(name);
m_options.push_back(std::make_pair(option1, option2));
}
void ConfigComplexChoice::Reset()
{
clear();
m_options.clear();
}
void ConfigComplexChoice::SaveValue(int choice)
{
auto Set = [this, choice](auto& setting, auto& value) {
if (m_layer != nullptr)
{
m_layer->Set(setting.GetLocation(), value);
Config::OnConfigChanged();
return;
}
Config::SetBaseOrCurrent(setting, value);
};
std::visit(Set, m_setting1, m_options[choice].first);
std::visit(Set, m_setting2, m_options[choice].second);
}
void ConfigComplexChoice::UpdateComboIndex()
{
auto Get = [this](auto& setting) {
if (m_layer != nullptr)
return static_cast<OptionVariant>(m_layer->Get(setting));
return static_cast<OptionVariant>(Config::Get(setting));
};
std::pair<OptionVariant, OptionVariant> values =
std::make_pair(std::visit(Get, m_setting1), std::visit(Get, m_setting2));
auto it = std::find(m_options.begin(), m_options.end(), values);
int index = static_cast<int>(std::distance(m_options.begin(), it));
const QSignalBlocker blocker(this);
setCurrentIndex(index);
}
const std::pair<Config::Location, Config::Location> ConfigComplexChoice::GetLocation() const
{
auto visit = [](auto& v) { return v.GetLocation(); };
return {std::visit(visit, m_setting1), std::visit(visit, m_setting2)};
}
void ConfigComplexChoice::mousePressEvent(QMouseEvent* event)
{
if (event->button() == Qt::RightButton && m_layer != nullptr)
{
auto& location = GetLocation();
m_layer->DeleteKey(location.first);
m_layer->DeleteKey(location.second);
Config::OnConfigChanged();
}
else
{
QComboBox::mousePressEvent(event);
}
};

View File

@ -7,20 +7,15 @@
#include <utility>
#include <vector>
#include "DolphinQt/Config/ConfigControls/ConfigControl.h"
#include "DolphinQt/Config/ToolTipControls/ToolTipComboBox.h"
#include "Common/Config/ConfigInfo.h"
#include "Common/Config/Config.h"
class ConfigChoice final : public ConfigControl<ToolTipComboBox>
class ConfigChoice : public ToolTipComboBox
{
Q_OBJECT
public:
ConfigChoice(const QStringList& options, const Config::Info<int>& setting,
Config::Layer* layer = nullptr);
protected:
void OnConfigChanged() override;
ConfigChoice(const QStringList& options, const Config::Info<int>& setting);
private:
void Update(int choice);
@ -28,49 +23,20 @@ private:
Config::Info<int> m_setting;
};
class ConfigStringChoice final : public ConfigControl<ToolTipComboBox>
class ConfigStringChoice : public ToolTipComboBox
{
Q_OBJECT
public:
ConfigStringChoice(const std::vector<std::string>& options,
const Config::Info<std::string>& setting, Config::Layer* layer = nullptr);
const Config::Info<std::string>& setting);
ConfigStringChoice(const std::vector<std::pair<QString, QString>>& options,
const Config::Info<std::string>& setting, Config::Layer* layer = nullptr);
const Config::Info<std::string>& setting);
private:
void Connect();
void Update(int index);
void Load();
protected:
void OnConfigChanged() override;
private:
void Update(int index);
const Config::Info<std::string> m_setting;
Config::Info<std::string> m_setting;
bool m_text_is_data = false;
};
class ConfigComplexChoice final : public ToolTipComboBox
{
Q_OBJECT
using InfoVariant = std::variant<Config::Info<u32>, Config::Info<int>, Config::Info<bool>>;
using OptionVariant = std::variant<u32, int, bool>;
public:
ConfigComplexChoice(const InfoVariant setting1, const InfoVariant setting2,
Config::Layer* layer = nullptr);
void Add(const QString& name, const OptionVariant option1, const OptionVariant option2);
void Refresh();
void Reset();
const std::pair<Config::Location, Config::Location> GetLocation() const;
private:
void SaveValue(int choice);
void UpdateComboIndex();
void mousePressEvent(QMouseEvent* event) override;
Config::Layer* m_layer;
const InfoVariant m_setting1;
const InfoVariant m_setting2;
std::vector<std::pair<OptionVariant, OptionVariant>> m_options;
};

View File

@ -1,105 +0,0 @@
// Copyright 2024 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <QFont>
#include <QMouseEvent>
#include <QSignalBlocker>
#include "Common/Config/Enums.h"
#include "Common/Config/Layer.h"
#include "DolphinQt/Settings.h"
namespace Config
{
template <typename T>
class Info;
struct Location;
} // namespace Config
template <class Derived>
class ConfigControl : public Derived
{
public:
ConfigControl(const Config::Location& location, Config::Layer* layer)
: m_location(location), m_layer(layer)
{
ConnectConfig();
}
ConfigControl(const QString& label, const Config::Location& location, Config::Layer* layer)
: Derived(label), m_location(location), m_layer(layer)
{
ConnectConfig();
}
ConfigControl(const Qt::Orientation& orient, const Config::Location& location,
Config::Layer* layer)
: Derived(orient), m_location(location), m_layer(layer)
{
ConnectConfig();
}
const Config::Location GetLocation() const { return m_location; }
protected:
void ConnectConfig()
{
Derived::connect(&Settings::Instance(), &Settings::ConfigChanged, this, [this] {
QFont bf = Derived::font();
bf.setBold(IsConfigLocal());
Derived::setFont(bf);
const QSignalBlocker blocker(this);
OnConfigChanged();
});
}
template <typename T>
void SaveValue(const Config::Info<T>& setting, const T& value)
{
if (m_layer != nullptr)
{
m_layer->Set(m_location, value);
Config::OnConfigChanged();
return;
}
Config::SetBaseOrCurrent(setting, value);
}
template <typename T>
const T ReadValue(const Config::Info<T>& setting) const
{
if (m_layer != nullptr)
return m_layer->Get(setting);
return Config::Get(setting);
}
virtual void OnConfigChanged(){};
private:
bool IsConfigLocal() const
{
if (m_layer != nullptr)
return m_layer->Exists(m_location);
else
return Config::GetActiveLayerForConfig(m_location) != Config::LayerType::Base;
}
void mousePressEvent(QMouseEvent* event) override
{
if (m_layer != nullptr && event->button() == Qt::RightButton)
{
m_layer->DeleteKey(m_location);
Config::OnConfigChanged();
}
else
{
Derived::mousePressEvent(event);
}
}
const Config::Location m_location;
Config::Layer* m_layer;
};

View File

@ -3,16 +3,20 @@
#include "DolphinQt/Config/ConfigControls/ConfigFloatSlider.h"
#include <QSignalBlocker>
#include "Common/Config/Config.h"
#include "DolphinQt/Settings.h"
ConfigFloatSlider::ConfigFloatSlider(float minimum, float maximum,
const Config::Info<float>& setting, float step,
Config::Layer* layer)
: ConfigControl(Qt::Horizontal, setting.GetLocation(), layer), m_minimum(minimum), m_step(step),
m_setting(setting)
const Config::Info<float>& setting, float step)
: ToolTipSlider(Qt::Horizontal), m_minimum(minimum), m_step(step), m_setting(setting)
{
const float range = maximum - minimum;
const int steps = std::round(range / step);
const int interval = std::round(range / steps);
const int current_value = std::round((ReadValue(setting) - minimum) / step);
const int current_value = std::round((Config::Get(m_setting) - minimum) / step);
setMinimum(0);
setMaximum(steps);
@ -20,21 +24,25 @@ ConfigFloatSlider::ConfigFloatSlider(float minimum, float maximum,
setValue(current_value);
connect(this, &ConfigFloatSlider::valueChanged, this, &ConfigFloatSlider::Update);
connect(&Settings::Instance(), &Settings::ConfigChanged, this, [this] {
QFont bf = font();
bf.setBold(Config::GetActiveLayerForConfig(m_setting) != Config::LayerType::Base);
setFont(bf);
const QSignalBlocker blocker(this);
const int value = std::round((Config::Get(m_setting) - m_minimum) / m_step);
setValue(value);
});
}
void ConfigFloatSlider::Update(int value)
{
const float current_value = (m_step * value) + m_minimum;
SaveValue(m_setting, current_value);
Config::SetBaseOrCurrent(m_setting, current_value);
}
float ConfigFloatSlider::GetValue() const
{
return (m_step * value()) + m_minimum;
}
void ConfigFloatSlider::OnConfigChanged()
{
setValue(std::round((ReadValue(m_setting) - m_minimum) / m_step));
}

View File

@ -3,29 +3,28 @@
#pragma once
#include "DolphinQt/Config/ConfigControls/ConfigControl.h"
#include "DolphinQt/Config/ToolTipControls/ToolTipSlider.h"
#include "Common/Config/ConfigInfo.h"
namespace Config
{
template <typename T>
class Info;
}
// Automatically converts an int slider into a float one.
// Do not read the int values or ranges directly from it.
class ConfigFloatSlider final : public ConfigControl<ToolTipSlider>
class ConfigFloatSlider : public ToolTipSlider
{
Q_OBJECT
public:
ConfigFloatSlider(float minimum, float maximum, const Config::Info<float>& setting, float step,
Config::Layer* layer = nullptr);
ConfigFloatSlider(float minimum, float maximum, const Config::Info<float>& setting, float step);
void Update(int value);
// Returns the adjusted float value
float GetValue() const;
protected:
void OnConfigChanged() override;
private:
float m_minimum;
float m_step;
const Config::Info<float> m_setting;
const Config::Info<float>& m_setting;
};

View File

@ -3,39 +3,33 @@
#include "DolphinQt/Config/ConfigControls/ConfigInteger.h"
ConfigInteger::ConfigInteger(int minimum, int maximum, const Config::Info<int>& setting, int step)
: ConfigInteger(minimum, maximum, setting, nullptr, step)
{
}
#include <QSignalBlocker>
ConfigInteger::ConfigInteger(int minimum, int maximum, const Config::Info<int>& setting,
Config::Layer* layer, int step)
: ConfigControl(setting.GetLocation(), layer), m_setting(setting)
#include "Common/Config/Config.h"
#include "DolphinQt/Settings.h"
ConfigInteger::ConfigInteger(int minimum, int maximum, const Config::Info<int>& setting, int step)
: ToolTipSpinBox(), m_setting(setting)
{
setMinimum(minimum);
setMaximum(maximum);
setSingleStep(step);
setValue(ReadValue(setting));
setValue(Config::Get(setting));
connect(this, &ConfigInteger::valueChanged, this, &ConfigInteger::Update);
connect(&Settings::Instance(), &Settings::ConfigChanged, this, [this] {
QFont bf = font();
bf.setBold(Config::GetActiveLayerForConfig(m_setting) != Config::LayerType::Base);
setFont(bf);
const QSignalBlocker blocker(this);
setValue(Config::Get(m_setting));
});
}
void ConfigInteger::Update(int value)
{
SaveValue(m_setting, value);
}
void ConfigInteger::OnConfigChanged()
{
setValue(ReadValue(m_setting));
}
ConfigIntegerLabel::ConfigIntegerLabel(const QString& text, ConfigInteger* widget)
: QLabel(text), m_widget(QPointer<ConfigInteger>(widget))
{
connect(&Settings::Instance(), &Settings::ConfigChanged, this, [this]() {
// Label shares font changes with ConfigInteger to mark game ini settings.
if (m_widget)
setFont(m_widget->font());
});
Config::SetBaseOrCurrent(m_setting, value);
}

View File

@ -3,38 +3,21 @@
#pragma once
#include <QLabel>
#include <QPointer>
#include "DolphinQt/Config/ConfigControls/ConfigControl.h"
#include "DolphinQt/Config/ToolTipControls/ToolTipSpinBox.h"
#include "Common/Config/ConfigInfo.h"
namespace Config
{
template <typename T>
class Info;
}
class ConfigInteger final : public ConfigControl<ToolTipSpinBox>
class ConfigInteger : public ToolTipSpinBox
{
Q_OBJECT
public:
ConfigInteger(int minimum, int maximum, const Config::Info<int>& setting, int step = 1);
ConfigInteger(int minimum, int maximum, const Config::Info<int>& setting, Config::Layer* layer,
int step = 1);
void Update(int value);
protected:
void OnConfigChanged() override;
private:
const Config::Info<int> m_setting;
};
class ConfigIntegerLabel final : public QLabel
{
Q_OBJECT
public:
ConfigIntegerLabel(const QString& text, ConfigInteger* widget);
private:
QPointer<ConfigInteger> m_widget;
const Config::Info<int>& m_setting;
};

View File

@ -3,21 +3,33 @@
#include "DolphinQt/Config/ConfigControls/ConfigRadio.h"
ConfigRadioInt::ConfigRadioInt(const QString& label, const Config::Info<int>& setting, int value,
Config::Layer* layer)
: ConfigControl(label, setting.GetLocation(), layer), m_setting(setting), m_value(value)
{
setChecked(ReadValue(setting) == value);
#include <QSignalBlocker>
#include "Common/Config/Config.h"
#include "DolphinQt/Settings.h"
ConfigRadioInt::ConfigRadioInt(const QString& label, const Config::Info<int>& setting, int value)
: ToolTipRadioButton(label), m_setting(setting), m_value(value)
{
setChecked(Config::Get(m_setting) == m_value);
connect(this, &QRadioButton::toggled, this, &ConfigRadioInt::Update);
connect(&Settings::Instance(), &Settings::ConfigChanged, this, [this] {
QFont bf = font();
bf.setBold(Config::GetActiveLayerForConfig(m_setting) != Config::LayerType::Base);
setFont(bf);
const QSignalBlocker blocker(this);
setChecked(Config::Get(m_setting) == m_value);
});
}
void ConfigRadioInt::Update()
{
if (isChecked())
{
SaveValue(m_setting, m_value);
Config::SetBaseOrCurrent(m_setting, m_value);
emit OnSelected(m_value);
}
else
@ -25,8 +37,3 @@ void ConfigRadioInt::Update()
emit OnDeselected(m_value);
}
}
void ConfigRadioInt::OnConfigChanged()
{
setChecked(ReadValue(m_setting) == m_value);
}

View File

@ -3,17 +3,15 @@
#pragma once
#include "DolphinQt/Config/ConfigControls/ConfigControl.h"
#include "DolphinQt/Config/ToolTipControls/ToolTipRadioButton.h"
#include "Common/Config/ConfigInfo.h"
#include "Common/Config/Config.h"
class ConfigRadioInt final : public ConfigControl<ToolTipRadioButton>
class ConfigRadioInt : public ToolTipRadioButton
{
Q_OBJECT
public:
ConfigRadioInt(const QString& label, const Config::Info<int>& setting, int value,
Config::Layer* layer = nullptr);
ConfigRadioInt(const QString& label, const Config::Info<int>& setting, int value);
signals:
// Since selecting a new radio button deselects the old one, ::toggled will generate two signals.
@ -21,12 +19,9 @@ signals:
void OnSelected(int new_value);
void OnDeselected(int old_value);
protected:
void OnConfigChanged() override;
private:
void Update();
const Config::Info<int> m_setting;
Config::Info<int> m_setting;
int m_value;
};

View File

@ -1,45 +1,36 @@
// Copyright 2017 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <QFont>
#include "DolphinQt/Config/ConfigControls/ConfigSlider.h"
#include <QSignalBlocker>
#include "Common/Config/Config.h"
#include "DolphinQt/Settings.h"
ConfigSlider::ConfigSlider(int minimum, int maximum, const Config::Info<int>& setting, int tick)
: ConfigSlider(minimum, maximum, setting, nullptr, tick)
{
}
ConfigSlider::ConfigSlider(int minimum, int maximum, const Config::Info<int>& setting,
Config::Layer* layer, int tick)
: ConfigControl(Qt::Horizontal, setting.GetLocation(), layer), m_setting(setting)
: ToolTipSlider(Qt::Horizontal), m_setting(setting)
{
setMinimum(minimum);
setMaximum(maximum);
setTickInterval(tick);
setValue(ReadValue(setting));
setValue(Config::Get(setting));
connect(this, &ConfigSlider::valueChanged, this, &ConfigSlider::Update);
connect(&Settings::Instance(), &Settings::ConfigChanged, this, [this] {
QFont bf = font();
bf.setBold(Config::GetActiveLayerForConfig(m_setting) != Config::LayerType::Base);
setFont(bf);
const QSignalBlocker blocker(this);
setValue(Config::Get(m_setting));
});
}
void ConfigSlider::Update(int value)
{
SaveValue(m_setting, value);
}
void ConfigSlider::OnConfigChanged()
{
setValue(ReadValue(m_setting));
}
ConfigSliderLabel::ConfigSliderLabel(const QString& text, ConfigSlider* slider)
: QLabel(text), m_slider(QPointer<ConfigSlider>(slider))
{
connect(&Settings::Instance(), &Settings::ConfigChanged, this, [this]() {
// Label shares font changes with slider to mark game ini settings.
if (m_slider)
setFont(m_slider->font());
});
Config::SetBaseOrCurrent(m_setting, value);
}

View File

@ -3,38 +3,21 @@
#pragma once
#include <QLabel>
#include <QPointer>
#include "DolphinQt/Config/ConfigControls/ConfigControl.h"
#include "DolphinQt/Config/ToolTipControls/ToolTipSlider.h"
#include "Common/Config/ConfigInfo.h"
namespace Config
{
template <typename T>
class Info;
}
class ConfigSlider final : public ConfigControl<ToolTipSlider>
class ConfigSlider : public ToolTipSlider
{
Q_OBJECT
public:
ConfigSlider(int minimum, int maximum, const Config::Info<int>& setting, int tick = 0);
ConfigSlider(int minimum, int maximum, const Config::Info<int>& setting, Config::Layer* layer,
int tick = 0);
void Update(int value);
protected:
void OnConfigChanged() override;
private:
const Config::Info<int> m_setting;
};
class ConfigSliderLabel final : public QLabel
{
Q_OBJECT
public:
ConfigSliderLabel(const QString& text, ConfigSlider* slider);
private:
QPointer<ConfigSlider> m_slider;
const Config::Info<int>& m_setting;
};

View File

@ -3,39 +3,37 @@
#include "DolphinQt/Config/GameConfigWidget.h"
#include <QFont>
#include <QCheckBox>
#include <QComboBox>
#include <QGroupBox>
#include <QHBoxLayout>
#include <QIcon>
#include <QLabel>
#include <QPushButton>
#include <QSlider>
#include <QSpinBox>
#include <QTabWidget>
#include <QTimer>
#include <QToolTip>
#include <QVBoxLayout>
#include "Common/CommonPaths.h"
#include "Common/Config/Config.h"
#include "Common/Config/Layer.h"
#include "Common/FileUtil.h"
#include "Core/Config/GraphicsSettings.h"
#include "Core/Config/MainSettings.h"
#include "Core/ConfigLoaders/GameConfigLoader.h"
#include "Core/ConfigManager.h"
#include "DolphinQt/Config/ConfigControls/ConfigBool.h"
#include "DolphinQt/Config/ConfigControls/ConfigChoice.h"
#include "DolphinQt/Config/ConfigControls/ConfigInteger.h"
#include "DolphinQt/Config/ConfigControls/ConfigRadio.h"
#include "DolphinQt/Config/ConfigControls/ConfigSlider.h"
#include "DolphinQt/Config/GameConfigEdit.h"
#include "DolphinQt/Config/Graphics/AdvancedWidget.h"
#include "DolphinQt/Config/Graphics/EnhancementsWidget.h"
#include "DolphinQt/Config/Graphics/GeneralWidget.h"
#include "DolphinQt/Config/Graphics/HacksWidget.h"
#include "DolphinQt/QtUtils/WrapInScrollArea.h"
#include "UICommon/GameFile.h"
constexpr int DETERMINISM_NOT_SET_INDEX = 0;
constexpr int DETERMINISM_AUTO_INDEX = 1;
constexpr int DETERMINISM_NONE_INDEX = 2;
constexpr int DETERMINISM_FAKE_COMPLETION_INDEX = 3;
constexpr const char* DETERMINISM_NOT_SET_STRING = "";
constexpr const char* DETERMINISM_AUTO_STRING = "auto";
constexpr const char* DETERMINISM_NONE_STRING = "none";
constexpr const char* DETERMINISM_FAKE_COMPLETION_STRING = "fake-completion";
static void PopulateTab(QTabWidget* tab, const std::string& path, std::string& game_id,
u16 revision, bool read_only)
{
@ -57,62 +55,46 @@ GameConfigWidget::GameConfigWidget(const UICommon::GameFile& game) : m_game(game
m_gameini_local_path =
QString::fromStdString(File::GetUserPath(D_GAMESETTINGS_IDX) + m_game_id + ".ini");
m_layer = std::make_unique<Config::Layer>(
ConfigLoaders::GenerateLocalGameConfigLoader(m_game_id, m_game.GetRevision()));
m_global_layer = std::make_unique<Config::Layer>(
ConfigLoaders::GenerateGlobalGameConfigLoader(m_game_id, m_game.GetRevision()));
CreateWidgets();
connect(&Settings::Instance(), &Settings::ConfigChanged, this, &GameConfigWidget::LoadSettings);
LoadSettings();
ConnectWidgets();
PopulateTab(m_default_tab, File::GetSysDirectory() + GAMESETTINGS_DIR DIR_SEP, m_game_id,
m_game.GetRevision(), true);
PopulateTab(m_local_tab, File::GetUserPath(D_GAMESETTINGS_IDX), m_game_id, m_game.GetRevision(),
false);
bool game_id_tab = false;
for (int i = 0; i < m_local_tab->count(); i++)
// Always give the user the opportunity to create a new INI
if (m_local_tab->count() == 0)
{
if (m_local_tab->tabText(i).toStdString() == m_game_id + ".ini")
game_id_tab = true;
}
if (game_id_tab == false)
{
// Create new local game ini tab if none exists.
auto* edit = new GameConfigEdit(
nullptr, QString::fromStdString(File::GetUserPath(D_GAMESETTINGS_IDX) + m_game_id + ".ini"),
false);
m_local_tab->addTab(edit, QString::fromStdString(m_game_id + ".ini"));
}
// Fails to change font if it's directly called at this time. Is there a better workaround?
QTimer::singleShot(100, this, [this]() {
SetItalics();
Config::OnConfigChanged();
});
}
void GameConfigWidget::CreateWidgets()
{
Config::Layer* layer = m_layer.get();
// General
m_refresh_config = new QPushButton(tr("Refresh"));
// Core
auto* core_box = new QGroupBox(tr("Core"));
auto* core_layout = new QGridLayout;
core_box->setLayout(core_layout);
m_enable_dual_core = new ConfigBool(tr("Enable Dual Core"), Config::MAIN_CPU_THREAD, layer);
m_enable_mmu = new ConfigBool(tr("Enable MMU"), Config::MAIN_MMU, layer);
m_enable_fprf = new ConfigBool(tr("Enable FPRF"), Config::MAIN_FPRF, layer);
m_sync_gpu = new ConfigBool(tr("Synchronize GPU thread"), Config::MAIN_SYNC_GPU, layer);
m_emulate_disc_speed =
new ConfigBool(tr("Emulate Disc Speed"), Config::MAIN_FAST_DISC_SPEED, layer, true);
m_use_dsp_hle = new ConfigBool(tr("DSP HLE (fast)"), Config::MAIN_DSP_HLE, layer);
m_enable_dual_core = new QCheckBox(tr("Enable Dual Core"));
m_enable_mmu = new QCheckBox(tr("Enable MMU"));
m_enable_fprf = new QCheckBox(tr("Enable FPRF"));
m_sync_gpu = new QCheckBox(tr("Synchronize GPU thread"));
m_emulate_disc_speed = new QCheckBox(tr("Emulate Disc Speed"));
m_use_dsp_hle = new QCheckBox(tr("DSP HLE (fast)"));
m_manual_texture_sampling = new QCheckBox(tr("Manual Texture Sampling"));
m_deterministic_dual_core = new QComboBox;
const std::vector<std::string> choice{tr("auto").toStdString(), tr("none").toStdString(),
tr("fake-completion").toStdString()};
m_deterministic_dual_core =
new ConfigStringChoice(choice, Config::MAIN_GPU_DETERMINISM_MODE, layer);
for (const auto& item : {tr("Not Set"), tr("auto"), tr("none"), tr("fake-completion")})
m_deterministic_dual_core->addItem(item);
m_enable_mmu->setToolTip(tr(
"Enables the Memory Management Unit, needed for some games. (ON = Compatible, OFF = Fast)"));
@ -132,18 +114,24 @@ void GameConfigWidget::CreateWidgets()
core_layout->addWidget(m_sync_gpu, 3, 0);
core_layout->addWidget(m_emulate_disc_speed, 4, 0);
core_layout->addWidget(m_use_dsp_hle, 5, 0);
core_layout->addWidget(new QLabel(tr("Deterministic dual core:")), 6, 0);
core_layout->addWidget(m_deterministic_dual_core, 6, 1);
core_layout->addWidget(m_manual_texture_sampling, 6, 0);
core_layout->addWidget(new QLabel(tr("Deterministic dual core:")), 7, 0);
core_layout->addWidget(m_deterministic_dual_core, 7, 1);
// Stereoscopy
auto* stereoscopy_box = new QGroupBox(tr("Stereoscopy"));
auto* stereoscopy_layout = new QGridLayout;
stereoscopy_box->setLayout(stereoscopy_layout);
m_depth_slider = new ConfigSlider(100, 200, Config::GFX_STEREO_DEPTH_PERCENTAGE, layer);
m_convergence_spin = new ConfigInteger(0, INT32_MAX, Config::GFX_STEREO_CONVERGENCE, layer);
m_use_monoscopic_shadows =
new ConfigBool(tr("Monoscopic Shadows"), Config::GFX_STEREO_EFB_MONO_DEPTH, layer);
m_depth_slider = new QSlider(Qt::Horizontal);
m_depth_slider->setMinimum(100);
m_depth_slider->setMaximum(200);
m_convergence_spin = new QSpinBox;
m_convergence_spin->setMinimum(0);
m_convergence_spin->setMaximum(INT32_MAX);
m_use_monoscopic_shadows = new QCheckBox(tr("Monoscopic Shadows"));
m_depth_slider->setToolTip(
tr("This value is multiplied with the depth set in the graphics configuration."));
@ -152,23 +140,37 @@ void GameConfigWidget::CreateWidgets()
m_use_monoscopic_shadows->setToolTip(
tr("Use a single depth buffer for both eyes. Needed for a few games."));
stereoscopy_layout->addWidget(new ConfigSliderLabel(tr("Depth Percentage:"), m_depth_slider), 0,
0);
stereoscopy_layout->addWidget(new QLabel(tr("Depth Percentage:")), 0, 0);
stereoscopy_layout->addWidget(m_depth_slider, 0, 1);
stereoscopy_layout->addWidget(new ConfigIntegerLabel(tr("Convergence:"), m_convergence_spin), 1,
0);
stereoscopy_layout->addWidget(new QLabel(tr("Convergence:")), 1, 0);
stereoscopy_layout->addWidget(m_convergence_spin, 1, 1);
stereoscopy_layout->addWidget(m_use_monoscopic_shadows, 2, 0);
auto* general_layout = new QVBoxLayout;
general_layout->addWidget(core_box);
general_layout->addWidget(stereoscopy_box);
general_layout->addStretch();
auto* settings_box = new QGroupBox(tr("Game-Specific Settings"));
auto* settings_layout = new QVBoxLayout;
settings_box->setLayout(settings_layout);
settings_layout->addWidget(
new QLabel(tr("These settings override core Dolphin settings.\nUndetermined means the game "
"uses Dolphin's setting.")));
settings_layout->addWidget(core_box);
settings_layout->addWidget(stereoscopy_box);
auto* general_layout = new QGridLayout;
general_layout->addWidget(settings_box, 0, 0, 1, -1);
general_layout->addWidget(m_refresh_config, 1, 0, 1, -1);
for (QCheckBox* item :
{m_enable_dual_core, m_enable_mmu, m_enable_fprf, m_sync_gpu, m_emulate_disc_speed,
m_use_dsp_hle, m_manual_texture_sampling, m_use_monoscopic_shadows})
item->setTristate(true);
auto* general_widget = new QWidget;
general_widget->setLayout(general_layout);
// Editor tab
// Advanced
auto* advanced_layout = new QVBoxLayout;
auto* default_group = new QGroupBox(tr("Default Config (Read Only)"));
@ -194,186 +196,207 @@ void GameConfigWidget::CreateWidgets()
auto* layout = new QVBoxLayout;
auto* tab_widget = new QTabWidget;
tab_widget->addTab(general_widget, tr("General"));
tab_widget->addTab(advanced_widget, tr("Editor"));
// GFX settings tabs. Placed in a QWidget for consistent margins.
auto* gfx_tab_holder = new QWidget;
auto* gfx_layout = new QVBoxLayout;
gfx_tab_holder->setLayout(gfx_layout);
tab_widget->addTab(gfx_tab_holder, tr("Graphics"));
auto* gfx_tabs = new QTabWidget;
gfx_tabs->addTab(GetWrappedWidget(new GeneralWidget(this, m_layer.get()), this, 125, 100),
tr("General"));
gfx_tabs->addTab(GetWrappedWidget(new EnhancementsWidget(this, m_layer.get()), this, 125, 100),
tr("Enhancements"));
gfx_tabs->addTab(GetWrappedWidget(new HacksWidget(this, m_layer.get()), this, 125, 100),
tr("Hacks"));
gfx_tabs->addTab(GetWrappedWidget(new AdvancedWidget(this, m_layer.get()), this, 125, 100),
tr("Advanced"));
const int editor_index = tab_widget->addTab(advanced_widget, tr("Editor"));
gfx_layout->addWidget(gfx_tabs);
connect(tab_widget, &QTabWidget::currentChanged, this, [this, editor_index](int index) {
// Update the ini editor after editing other tabs.
if (index == editor_index)
{
// Layer only auto-saves when it is destroyed.
m_layer->Save();
// There can be multiple ini loaded for a game, only replace the one related to the game
// ini being edited.
for (int i = 0; i < m_local_tab->count(); i++)
{
if (m_local_tab->tabText(i).toStdString() == m_game_id + ".ini")
{
m_local_tab->removeTab(i);
auto* edit = new GameConfigEdit(
nullptr,
QString::fromStdString(File::GetUserPath(D_GAMESETTINGS_IDX) + m_game_id + ".ini"),
false);
m_local_tab->insertTab(i, edit, QString::fromStdString(m_game_id + ".ini"));
break;
}
}
}
// Update other tabs after using ini editor.
if (m_prev_tab_index == editor_index)
{
// Load won't clear deleted keys, so everything is wiped before loading.
m_layer->DeleteAllKeys();
m_layer->Load();
Config::OnConfigChanged();
}
m_prev_tab_index = index;
});
const QString help_msg = tr(
"Italics mark default game settings, bold marks user settings.\nRight-click to remove user "
"settings.\nGraphics tabs don't display the value of a default game setting.\nAnti-Aliasing "
"settings are disabled when the global graphics backend doesn't "
"match the game setting.");
auto help_icon = style()->standardIcon(QStyle::SP_MessageBoxQuestion);
auto* help_label = new QLabel(tr("These settings override core Dolphin settings."));
help_label->setToolTip(help_msg);
auto help_label_icon = new QLabel();
help_label_icon->setPixmap(help_icon.pixmap(12, 12));
help_label_icon->setToolTip(help_msg);
auto* help_layout = new QHBoxLayout();
help_layout->addWidget(help_label);
help_layout->addWidget(help_label_icon);
help_layout->addStretch();
layout->addLayout(help_layout);
layout->addWidget(tab_widget);
setLayout(layout);
}
GameConfigWidget::~GameConfigWidget()
void GameConfigWidget::ConnectWidgets()
{
// Destructor saves the layer to file.
m_layer.reset();
// Buttons
connect(m_refresh_config, &QPushButton::clicked, this, &GameConfigWidget::LoadSettings);
// If a game is running and the game properties window is closed, update local game layer with
// any new changes. Not sure if doing it more frequently is safe.
auto local_layer = Config::GetLayer(Config::LayerType::LocalGame);
if (local_layer && SConfig::GetInstance().GetGameID() == m_game_id)
for (QCheckBox* box :
{m_enable_dual_core, m_enable_mmu, m_enable_fprf, m_sync_gpu, m_emulate_disc_speed,
m_use_dsp_hle, m_manual_texture_sampling, m_use_monoscopic_shadows})
connect(box, &QCheckBox::stateChanged, this, &GameConfigWidget::SaveSettings);
connect(m_deterministic_dual_core, &QComboBox::currentIndexChanged, this,
&GameConfigWidget::SaveSettings);
connect(m_depth_slider, &QSlider::valueChanged, this, &GameConfigWidget::SaveSettings);
connect(m_convergence_spin, &QSpinBox::valueChanged, this, &GameConfigWidget::SaveSettings);
}
void GameConfigWidget::LoadCheckBox(QCheckBox* checkbox, const std::string& section,
const std::string& key, bool reverse)
{
bool checked;
if (m_gameini_local.GetOrCreateSection(section)->Get(key, &checked))
return checkbox->setCheckState(checked ^ reverse ? Qt::Checked : Qt::Unchecked);
if (m_gameini_default.GetOrCreateSection(section)->Get(key, &checked))
return checkbox->setCheckState(checked ^ reverse ? Qt::Checked : Qt::Unchecked);
checkbox->setCheckState(Qt::PartiallyChecked);
}
void GameConfigWidget::SaveCheckBox(QCheckBox* checkbox, const std::string& section,
const std::string& key, bool reverse)
{
// Delete any existing entries from the local gameini if checkbox is undetermined.
// Otherwise, write the current value to the local gameini if the value differs from the default
// gameini values.
// Delete any existing entry from the local gameini if the value does not differ from the default
// gameini value.
if (checkbox->checkState() == Qt::PartiallyChecked)
{
local_layer->DeleteAllKeys();
local_layer->Load();
Config::OnConfigChanged();
m_gameini_local.DeleteKey(section, key);
return;
}
// Delete empty configs
if (File::GetSize(m_gameini_local_path.toStdString()) == 0)
File::Delete(m_gameini_local_path.toStdString());
bool checked = (checkbox->checkState() == Qt::Checked) ^ reverse;
if (m_gameini_default.Exists(section, key))
{
bool default_value;
m_gameini_default.GetOrCreateSection(section)->Get(key, &default_value);
if (default_value != checked)
m_gameini_local.GetOrCreateSection(section)->Set(key, checked);
else
m_gameini_local.DeleteKey(section, key);
return;
}
m_gameini_local.GetOrCreateSection(section)->Set(key, checked);
}
void GameConfigWidget::LoadSettings()
{
// Load globals
auto update_bool = [this](auto config, bool reverse = false) {
const Config::Location& setting = config->GetLocation();
// Reload config
m_gameini_local = SConfig::LoadLocalGameIni(m_game_id, m_game.GetRevision());
m_gameini_default = SConfig::LoadDefaultGameIni(m_game_id, m_game.GetRevision());
// Don't overwrite local with global
if (m_layer->Exists(setting) || !m_global_layer->Exists(setting))
return;
// Load game-specific settings
std::optional<bool> value = m_global_layer->Get<bool>(config->GetLocation());
// Core
LoadCheckBox(m_enable_dual_core, "Core", "CPUThread");
LoadCheckBox(m_enable_mmu, "Core", "MMU");
LoadCheckBox(m_enable_fprf, "Core", "FPRF");
LoadCheckBox(m_sync_gpu, "Core", "SyncGPU");
LoadCheckBox(m_emulate_disc_speed, "Core", "FastDiscSpeed", true);
LoadCheckBox(m_use_dsp_hle, "Core", "DSPHLE");
LoadCheckBox(m_manual_texture_sampling, "Video_Hacks", "FastTextureSampling", true);
if (value.has_value())
{
const QSignalBlocker blocker(config);
config->setChecked(value.value() ^ reverse);
}
};
std::string determinism_mode;
auto update_int = [this](auto config) {
const Config::Location& setting = config->GetLocation();
int determinism_index = DETERMINISM_NOT_SET_INDEX;
if (m_layer->Exists(setting) || !m_global_layer->Exists(setting))
return;
m_gameini_default.GetIfExists("Core", "GPUDeterminismMode", &determinism_mode);
m_gameini_local.GetIfExists("Core", "GPUDeterminismMode", &determinism_mode);
std::optional<int> value = m_global_layer->Get<int>(setting);
if (value.has_value())
{
const QSignalBlocker blocker(config);
config->setValue(value.value());
}
};
for (ConfigBool* config : {m_enable_dual_core, m_enable_mmu, m_enable_fprf, m_sync_gpu,
m_use_dsp_hle, m_use_monoscopic_shadows})
if (determinism_mode == DETERMINISM_AUTO_STRING)
{
update_bool(config);
determinism_index = DETERMINISM_AUTO_INDEX;
}
else if (determinism_mode == DETERMINISM_NONE_STRING)
{
determinism_index = DETERMINISM_NONE_INDEX;
}
else if (determinism_mode == DETERMINISM_FAKE_COMPLETION_STRING)
{
determinism_index = DETERMINISM_FAKE_COMPLETION_INDEX;
}
update_bool(m_emulate_disc_speed, true);
m_deterministic_dual_core->setCurrentIndex(determinism_index);
update_int(m_depth_slider);
update_int(m_convergence_spin);
// Stereoscopy
int depth_percentage = 100;
m_gameini_default.GetIfExists("Video_Stereoscopy", "StereoDepthPercentage", &depth_percentage);
m_gameini_local.GetIfExists("Video_Stereoscopy", "StereoDepthPercentage", &depth_percentage);
m_depth_slider->setValue(depth_percentage);
int convergence = 0;
m_gameini_default.GetIfExists("Video_Stereoscopy", "StereoConvergence", &convergence);
m_gameini_local.GetIfExists("Video_Stereoscopy", "StereoConvergence", &convergence);
m_convergence_spin->setValue(convergence);
LoadCheckBox(m_use_monoscopic_shadows, "Video_Stereoscopy", "StereoEFBMonoDepth");
}
void GameConfigWidget::SetItalics()
void GameConfigWidget::SaveSettings()
{
// Mark system game settings with italics. Called once because it should never change.
auto italics = [this](auto config) {
if (!m_global_layer->Exists(config->GetLocation()))
return;
// Core
SaveCheckBox(m_enable_dual_core, "Core", "CPUThread");
SaveCheckBox(m_enable_mmu, "Core", "MMU");
SaveCheckBox(m_enable_fprf, "Core", "FPRF");
SaveCheckBox(m_sync_gpu, "Core", "SyncGPU");
SaveCheckBox(m_emulate_disc_speed, "Core", "FastDiscSpeed", true);
SaveCheckBox(m_use_dsp_hle, "Core", "DSPHLE");
SaveCheckBox(m_manual_texture_sampling, "Video_Hacks", "FastTextureSampling", true);
QFont ifont = config->font();
ifont.setItalic(true);
config->setFont(ifont);
};
int determinism_num = m_deterministic_dual_core->currentIndex();
for (auto* config : findChildren<ConfigBool*>())
italics(config);
for (auto* config : findChildren<ConfigSlider*>())
italics(config);
for (auto* config : findChildren<ConfigInteger*>())
italics(config);
for (auto* config : findChildren<ConfigRadioInt*>())
italics(config);
for (auto* config : findChildren<ConfigChoice*>())
italics(config);
for (auto* config : findChildren<ConfigStringChoice*>())
italics(config);
std::string determinism_mode = DETERMINISM_NOT_SET_STRING;
for (auto* config : findChildren<ConfigComplexChoice*>())
switch (determinism_num)
{
std::pair<Config::Location, Config::Location> location = config->GetLocation();
if (m_global_layer->Exists(location.first) || m_global_layer->Exists(location.second))
case DETERMINISM_AUTO_INDEX:
determinism_mode = DETERMINISM_AUTO_STRING;
break;
case DETERMINISM_NONE_INDEX:
determinism_mode = DETERMINISM_NONE_STRING;
break;
case DETERMINISM_FAKE_COMPLETION_INDEX:
determinism_mode = DETERMINISM_FAKE_COMPLETION_STRING;
break;
}
if (determinism_mode != DETERMINISM_NOT_SET_STRING)
{
std::string default_mode = DETERMINISM_NOT_SET_STRING;
if (!(m_gameini_default.GetIfExists("Core", "GPUDeterminismMode", &default_mode) &&
default_mode == determinism_mode))
{
QFont ifont = config->font();
ifont.setItalic(true);
config->setFont(ifont);
m_gameini_local.GetOrCreateSection("Core")->Set("GPUDeterminismMode", determinism_mode);
}
}
else
{
m_gameini_local.DeleteKey("Core", "GPUDeterminismMode");
}
// Stereoscopy
int depth_percentage = m_depth_slider->value();
if (depth_percentage != 100)
{
int default_value = 0;
if (!(m_gameini_default.GetIfExists("Video_Stereoscopy", "StereoDepthPercentage",
&default_value) &&
default_value == depth_percentage))
{
m_gameini_local.GetOrCreateSection("Video_Stereoscopy")
->Set("StereoDepthPercentage", depth_percentage);
}
}
int convergence = m_convergence_spin->value();
if (convergence != 0)
{
int default_value = 0;
if (!(m_gameini_default.GetIfExists("Video_Stereoscopy", "StereoConvergence", &default_value) &&
default_value == convergence))
{
m_gameini_local.GetOrCreateSection("Video_Stereoscopy")
->Set("StereoConvergence", convergence);
}
}
SaveCheckBox(m_use_monoscopic_shadows, "Video_Stereoscopy", "StereoEFBMonoDepth");
bool success = m_gameini_local.Save(m_gameini_local_path.toStdString());
// If the resulting file is empty, delete it. Kind of a hack, but meh.
if (success && File::GetSize(m_gameini_local_path.toStdString()) == 0)
File::Delete(m_gameini_local_path.toStdString());
}

View File

@ -7,21 +7,19 @@
#include <QString>
#include <QWidget>
#include "Common/IniFile.h"
namespace UICommon
{
class GameFile;
}
namespace Config
{
class Layer;
} // namespace Config
class ConfigBool;
class ConfigInteger;
class ConfigSlider;
class ConfigStringChoice;
class QCheckBox;
class QComboBox;
class QPushButton;
class QSlider;
class QSpinBox;
class QTabWidget;
class GameConfigWidget : public QWidget
@ -29,33 +27,45 @@ class GameConfigWidget : public QWidget
Q_OBJECT
public:
explicit GameConfigWidget(const UICommon::GameFile& game);
~GameConfigWidget();
private:
void CreateWidgets();
void LoadSettings();
void SetItalics();
void ConnectWidgets();
void LoadSettings();
void SaveSettings();
void SaveCheckBox(QCheckBox* checkbox, const std::string& section, const std::string& key,
bool reverse = false);
void LoadCheckBox(QCheckBox* checkbox, const std::string& section, const std::string& key,
bool reverse = false);
QString m_gameini_sys_path;
QString m_gameini_local_path;
QTabWidget* m_default_tab;
QTabWidget* m_local_tab;
ConfigBool* m_enable_dual_core;
ConfigBool* m_enable_mmu;
ConfigBool* m_enable_fprf;
ConfigBool* m_sync_gpu;
ConfigBool* m_emulate_disc_speed;
ConfigBool* m_use_dsp_hle;
ConfigBool* m_use_monoscopic_shadows;
QCheckBox* m_enable_dual_core;
QCheckBox* m_enable_mmu;
QCheckBox* m_enable_fprf;
QCheckBox* m_sync_gpu;
QCheckBox* m_emulate_disc_speed;
QCheckBox* m_use_dsp_hle;
QCheckBox* m_use_monoscopic_shadows;
QCheckBox* m_manual_texture_sampling;
ConfigStringChoice* m_deterministic_dual_core;
ConfigSlider* m_depth_slider;
ConfigInteger* m_convergence_spin;
QPushButton* m_refresh_config;
QComboBox* m_deterministic_dual_core;
QSlider* m_depth_slider;
QSpinBox* m_convergence_spin;
const UICommon::GameFile& m_game;
std::string m_game_id;
std::unique_ptr<Config::Layer> m_layer;
std::unique_ptr<Config::Layer> m_global_layer;
int m_prev_tab_index = 0;
Common::IniFile m_gameini_local;
Common::IniFile m_gameini_default;
};

View File

@ -3,9 +3,11 @@
#include "DolphinQt/Config/Graphics/AdvancedWidget.h"
#include <QCheckBox>
#include <QGridLayout>
#include <QGroupBox>
#include <QLabel>
#include <QSpinBox>
#include <QVBoxLayout>
#include "Core/Config/GraphicsSettings.h"
@ -17,7 +19,6 @@
#include "DolphinQt/Config/ConfigControls/ConfigBool.h"
#include "DolphinQt/Config/ConfigControls/ConfigChoice.h"
#include "DolphinQt/Config/ConfigControls/ConfigInteger.h"
#include "DolphinQt/Config/GameConfigWidget.h"
#include "DolphinQt/Config/Graphics/GraphicsWindow.h"
#include "DolphinQt/Config/ToolTipControls/ToolTipCheckBox.h"
#include "DolphinQt/QtUtils/SignalBlocking.h"
@ -28,6 +29,7 @@
AdvancedWidget::AdvancedWidget(GraphicsWindow* parent)
{
CreateWidgets();
LoadSettings();
ConnectWidgets();
AddDescriptions();
@ -35,30 +37,17 @@ AdvancedWidget::AdvancedWidget(GraphicsWindow* parent)
connect(&Settings::Instance(), &Settings::EmulationStateChanged, this, [this](Core::State state) {
OnEmulationStateChanged(state != Core::State::Uninitialized);
});
connect(m_manual_texture_sampling, &QCheckBox::toggled,
[this, parent] { emit parent->UseFastTextureSamplingChanged(); });
connect(m_manual_texture_sampling, &QCheckBox::toggled, [this, parent] {
SaveSettings();
emit parent->UseFastTextureSamplingChanged();
});
OnBackendChanged();
OnEmulationStateChanged(!Core::IsUninitialized(Core::System::GetInstance()));
}
AdvancedWidget::AdvancedWidget(GameConfigWidget* parent, Config::Layer* layer) : m_game_layer(layer)
{
CreateWidgets();
ConnectWidgets();
AddDescriptions();
connect(&Settings::Instance(), &Settings::EmulationStateChanged, this, [this](Core::State state) {
OnEmulationStateChanged(state != Core::State::Uninitialized);
});
OnEmulationStateChanged(Core::GetState(Core::System::GetInstance()) !=
Core::State::Uninitialized);
}
void AdvancedWidget::CreateWidgets()
{
const bool local_edit = m_game_layer != nullptr;
auto* main_layout = new QVBoxLayout;
// Performance
@ -66,19 +55,17 @@ void AdvancedWidget::CreateWidgets()
auto* performance_layout = new QGridLayout();
performance_box->setLayout(performance_layout);
m_show_fps = new ConfigBool(tr("Show FPS"), Config::GFX_SHOW_FPS, m_game_layer);
m_show_ftimes = new ConfigBool(tr("Show Frame Times"), Config::GFX_SHOW_FTIMES, m_game_layer);
m_show_vps = new ConfigBool(tr("Show VPS"), Config::GFX_SHOW_VPS, m_game_layer);
m_show_vtimes = new ConfigBool(tr("Show VBlank Times"), Config::GFX_SHOW_VTIMES, m_game_layer);
m_show_graphs =
new ConfigBool(tr("Show Performance Graphs"), Config::GFX_SHOW_GRAPHS, m_game_layer);
m_show_speed = new ConfigBool(tr("Show % Speed"), Config::GFX_SHOW_SPEED, m_game_layer);
m_show_speed_colors =
new ConfigBool(tr("Show Speed Colors"), Config::GFX_SHOW_SPEED_COLORS, m_game_layer);
m_perf_samp_window = new ConfigInteger(0, 10000, Config::GFX_PERF_SAMP_WINDOW, m_game_layer, 100);
m_show_fps = new ConfigBool(tr("Show FPS"), Config::GFX_SHOW_FPS);
m_show_ftimes = new ConfigBool(tr("Show Frame Times"), Config::GFX_SHOW_FTIMES);
m_show_vps = new ConfigBool(tr("Show VPS"), Config::GFX_SHOW_VPS);
m_show_vtimes = new ConfigBool(tr("Show VBlank Times"), Config::GFX_SHOW_VTIMES);
m_show_graphs = new ConfigBool(tr("Show Performance Graphs"), Config::GFX_SHOW_GRAPHS);
m_show_speed = new ConfigBool(tr("Show % Speed"), Config::GFX_SHOW_SPEED);
m_show_speed_colors = new ConfigBool(tr("Show Speed Colors"), Config::GFX_SHOW_SPEED_COLORS);
m_perf_samp_window = new ConfigInteger(0, 10000, Config::GFX_PERF_SAMP_WINDOW, 100);
m_perf_samp_window->SetTitle(tr("Performance Sample Window (ms)"));
m_log_render_time = new ConfigBool(tr("Log Render Time to File"),
Config::GFX_LOG_RENDER_TIME_TO_FILE, m_game_layer);
m_log_render_time =
new ConfigBool(tr("Log Render Time to File"), Config::GFX_LOG_RENDER_TIME_TO_FILE);
performance_layout->addWidget(m_show_fps, 0, 0);
performance_layout->addWidget(m_show_ftimes, 0, 1);
@ -96,16 +83,14 @@ void AdvancedWidget::CreateWidgets()
auto* debugging_layout = new QGridLayout();
debugging_box->setLayout(debugging_layout);
m_enable_wireframe =
new ConfigBool(tr("Enable Wireframe"), Config::GFX_ENABLE_WIREFRAME, m_game_layer);
m_show_statistics =
new ConfigBool(tr("Show Statistics"), Config::GFX_OVERLAY_STATS, m_game_layer);
m_show_proj_statistics = new ConfigBool(tr("Show Projection Statistics"),
Config::GFX_OVERLAY_PROJ_STATS, m_game_layer);
m_enable_wireframe = new ConfigBool(tr("Enable Wireframe"), Config::GFX_ENABLE_WIREFRAME);
m_show_statistics = new ConfigBool(tr("Show Statistics"), Config::GFX_OVERLAY_STATS);
m_show_proj_statistics =
new ConfigBool(tr("Show Projection Statistics"), Config::GFX_OVERLAY_PROJ_STATS);
m_enable_format_overlay =
new ConfigBool(tr("Texture Format Overlay"), Config::GFX_TEXFMT_OVERLAY_ENABLE, m_game_layer);
m_enable_api_validation = new ConfigBool(tr("Enable API Validation Layers"),
Config::GFX_ENABLE_VALIDATION_LAYER, m_game_layer);
new ConfigBool(tr("Texture Format Overlay"), Config::GFX_TEXFMT_OVERLAY_ENABLE);
m_enable_api_validation =
new ConfigBool(tr("Enable API Validation Layers"), Config::GFX_ENABLE_VALIDATION_LAYER);
debugging_layout->addWidget(m_enable_wireframe, 0, 0);
debugging_layout->addWidget(m_show_statistics, 0, 1);
@ -118,25 +103,14 @@ void AdvancedWidget::CreateWidgets()
auto* utility_layout = new QGridLayout();
utility_box->setLayout(utility_layout);
m_load_custom_textures =
new ConfigBool(tr("Load Custom Textures"), Config::GFX_HIRES_TEXTURES, m_game_layer);
m_prefetch_custom_textures = new ConfigBool(tr("Prefetch Custom Textures"),
Config::GFX_CACHE_HIRES_TEXTURES, m_game_layer);
m_prefetch_custom_textures->setEnabled(m_load_custom_textures->isChecked());
m_load_custom_textures = new ConfigBool(tr("Load Custom Textures"), Config::GFX_HIRES_TEXTURES);
m_prefetch_custom_textures =
new ConfigBool(tr("Prefetch Custom Textures"), Config::GFX_CACHE_HIRES_TEXTURES);
m_dump_efb_target = new ConfigBool(tr("Dump EFB Target"), Config::GFX_DUMP_EFB_TARGET);
m_dump_xfb_target = new ConfigBool(tr("Dump XFB Target"), Config::GFX_DUMP_XFB_TARGET);
if (local_edit)
{
// It's hazardous to accidentally set these in a game ini.
m_dump_efb_target->setEnabled(false);
m_dump_xfb_target->setEnabled(false);
}
m_disable_vram_copies = new ConfigBool(tr("Disable EFB VRAM Copies"),
Config::GFX_HACK_DISABLE_COPY_TO_VRAM, m_game_layer);
m_enable_graphics_mods =
new ConfigBool(tr("Enable Graphics Mods"), Config::GFX_MODS_ENABLE, m_game_layer);
m_disable_vram_copies =
new ConfigBool(tr("Disable EFB VRAM Copies"), Config::GFX_HACK_DISABLE_COPY_TO_VRAM);
m_enable_graphics_mods = new ToolTipCheckBox(tr("Enable Graphics Mods"));
utility_layout->addWidget(m_load_custom_textures, 0, 0);
utility_layout->addWidget(m_prefetch_custom_textures, 0, 1);
@ -154,16 +128,6 @@ void AdvancedWidget::CreateWidgets()
m_dump_textures = new ConfigBool(tr("Enable"), Config::GFX_DUMP_TEXTURES);
m_dump_base_textures = new ConfigBool(tr("Dump Base Textures"), Config::GFX_DUMP_BASE_TEXTURES);
m_dump_mip_textures = new ConfigBool(tr("Dump Mip Maps"), Config::GFX_DUMP_MIP_TEXTURES);
m_dump_mip_textures->setEnabled(m_dump_textures->isChecked());
m_dump_base_textures->setEnabled(m_dump_textures->isChecked());
if (local_edit)
{
// It's hazardous to accidentally set dumping in a game ini.
m_dump_textures->setEnabled(false);
m_dump_base_textures->setEnabled(false);
m_dump_mip_textures->setEnabled(false);
}
texture_dump_layout->addWidget(m_dump_textures, 0, 0);
@ -178,22 +142,18 @@ void AdvancedWidget::CreateWidgets()
m_frame_dumps_resolution_type =
new ConfigChoice({tr("Window Resolution"), tr("Aspect Ratio Corrected Internal Resolution"),
tr("Raw Internal Resolution")},
Config::GFX_FRAME_DUMPS_RESOLUTION_TYPE, m_game_layer);
m_png_compression_level =
new ConfigInteger(0, 9, Config::GFX_PNG_COMPRESSION_LEVEL, m_game_layer);
Config::GFX_FRAME_DUMPS_RESOLUTION_TYPE);
m_dump_use_ffv1 = new ConfigBool(tr("Use Lossless Codec (FFV1)"), Config::GFX_USE_FFV1);
m_dump_bitrate = new ConfigInteger(0, 1000000, Config::GFX_BITRATE_KBPS, 1000);
m_png_compression_level = new ConfigInteger(0, 9, Config::GFX_PNG_COMPRESSION_LEVEL);
dump_layout->addWidget(new QLabel(tr("Resolution Type:")), 0, 0);
dump_layout->addWidget(m_frame_dumps_resolution_type, 0, 1);
#if defined(HAVE_FFMPEG)
m_dump_use_ffv1 =
new ConfigBool(tr("Use Lossless Codec (FFV1)"), Config::GFX_USE_FFV1, m_game_layer);
m_dump_bitrate = new ConfigInteger(0, 1000000, Config::GFX_BITRATE_KBPS, m_game_layer, 1000);
m_dump_bitrate->setEnabled(!m_dump_use_ffv1->isChecked());
dump_layout->addWidget(m_dump_use_ffv1, 1, 0);
dump_layout->addWidget(new QLabel(tr("Bitrate (kbps):")), 2, 0);
dump_layout->addWidget(m_dump_bitrate, 2, 1);
#endif
dump_layout->addWidget(new QLabel(tr("PNG Compression Level:")), 3, 0);
m_png_compression_level->SetTitle(tr("PNG Compression Level"));
dump_layout->addWidget(m_png_compression_level, 3, 1);
@ -203,16 +163,14 @@ void AdvancedWidget::CreateWidgets()
auto* misc_layout = new QGridLayout();
misc_box->setLayout(misc_layout);
m_enable_cropping = new ConfigBool(tr("Crop"), Config::GFX_CROP, m_game_layer);
m_enable_prog_scan =
new ConfigBool(tr("Enable Progressive Scan"), Config::SYSCONF_PROGRESSIVE_SCAN, m_game_layer);
m_backend_multithreading = new ConfigBool(tr("Backend Multithreading"),
Config::GFX_BACKEND_MULTITHREADING, m_game_layer);
m_enable_cropping = new ConfigBool(tr("Crop"), Config::GFX_CROP);
m_enable_prog_scan = new ToolTipCheckBox(tr("Enable Progressive Scan"));
m_backend_multithreading =
new ConfigBool(tr("Backend Multithreading"), Config::GFX_BACKEND_MULTITHREADING);
m_prefer_vs_for_point_line_expansion = new ConfigBool(
// i18n: VS is short for vertex shaders.
tr("Prefer VS for Point/Line Expansion"), Config::GFX_PREFER_VS_FOR_LINE_POINT_EXPANSION,
m_game_layer);
m_cpu_cull = new ConfigBool(tr("Cull Vertices on the CPU"), Config::GFX_CPU_CULL, m_game_layer);
tr("Prefer VS for Point/Line Expansion"), Config::GFX_PREFER_VS_FOR_LINE_POINT_EXPANSION);
m_cpu_cull = new ConfigBool(tr("Cull Vertices on the CPU"), Config::GFX_CPU_CULL);
misc_layout->addWidget(m_enable_cropping, 0, 0);
misc_layout->addWidget(m_enable_prog_scan, 0, 1);
@ -221,7 +179,7 @@ void AdvancedWidget::CreateWidgets()
misc_layout->addWidget(m_cpu_cull, 2, 0);
#ifdef _WIN32
m_borderless_fullscreen =
new ConfigBool(tr("Borderless Fullscreen"), Config::GFX_BORDERLESS_FULLSCREEN, m_game_layer);
new ConfigBool(tr("Borderless Fullscreen"), Config::GFX_BORDERLESS_FULLSCREEN);
misc_layout->addWidget(m_borderless_fullscreen, 2, 1);
#endif
@ -231,10 +189,10 @@ void AdvancedWidget::CreateWidgets()
auto* experimental_layout = new QGridLayout();
experimental_box->setLayout(experimental_layout);
m_defer_efb_access_invalidation = new ConfigBool(
tr("Defer EFB Cache Invalidation"), Config::GFX_HACK_EFB_DEFER_INVALIDATION, m_game_layer);
m_manual_texture_sampling = new ConfigBool(
tr("Manual Texture Sampling"), Config::GFX_HACK_FAST_TEXTURE_SAMPLING, m_game_layer, true);
m_defer_efb_access_invalidation =
new ConfigBool(tr("Defer EFB Cache Invalidation"), Config::GFX_HACK_EFB_DEFER_INVALIDATION);
m_manual_texture_sampling =
new ConfigBool(tr("Manual Texture Sampling"), Config::GFX_HACK_FAST_TEXTURE_SAMPLING, true);
experimental_layout->addWidget(m_defer_efb_access_invalidation, 0, 0);
experimental_layout->addWidget(m_manual_texture_sampling, 0, 1);
@ -253,19 +211,34 @@ void AdvancedWidget::CreateWidgets()
void AdvancedWidget::ConnectWidgets()
{
connect(m_load_custom_textures, &QCheckBox::toggled, this,
[this](bool checked) { m_prefetch_custom_textures->setEnabled(checked); });
connect(m_dump_textures, &QCheckBox::toggled, this, [this](bool checked) {
m_dump_mip_textures->setEnabled(checked);
m_dump_base_textures->setEnabled(checked);
});
connect(m_enable_graphics_mods, &QCheckBox::toggled, this,
[this](bool checked) { emit Settings::Instance().EnableGfxModsChanged(checked); });
connect(m_load_custom_textures, &QCheckBox::toggled, this, &AdvancedWidget::SaveSettings);
connect(m_dump_use_ffv1, &QCheckBox::toggled, this, &AdvancedWidget::SaveSettings);
connect(m_enable_prog_scan, &QCheckBox::toggled, this, &AdvancedWidget::SaveSettings);
connect(m_dump_textures, &QCheckBox::toggled, this, &AdvancedWidget::SaveSettings);
connect(m_enable_graphics_mods, &QCheckBox::toggled, this, &AdvancedWidget::SaveSettings);
}
#if defined(HAVE_FFMPEG)
connect(m_dump_use_ffv1, &QCheckBox::toggled, this,
[this](bool checked) { m_dump_bitrate->setEnabled(!checked); });
#endif
void AdvancedWidget::LoadSettings()
{
m_prefetch_custom_textures->setEnabled(Config::Get(Config::GFX_HIRES_TEXTURES));
m_dump_bitrate->setEnabled(!Config::Get(Config::GFX_USE_FFV1));
m_enable_prog_scan->setChecked(Config::Get(Config::SYSCONF_PROGRESSIVE_SCAN));
m_dump_mip_textures->setEnabled(Config::Get(Config::GFX_DUMP_TEXTURES));
m_dump_base_textures->setEnabled(Config::Get(Config::GFX_DUMP_TEXTURES));
SignalBlocking(m_enable_graphics_mods)->setChecked(Settings::Instance().GetGraphicModsEnabled());
}
void AdvancedWidget::SaveSettings()
{
m_prefetch_custom_textures->setEnabled(Config::Get(Config::GFX_HIRES_TEXTURES));
m_dump_bitrate->setEnabled(!Config::Get(Config::GFX_USE_FFV1));
Config::SetBase(Config::SYSCONF_PROGRESSIVE_SCAN, m_enable_prog_scan->isChecked());
m_dump_mip_textures->setEnabled(Config::Get(Config::GFX_DUMP_TEXTURES));
m_dump_base_textures->setEnabled(Config::Get(Config::GFX_DUMP_TEXTURES));
Settings::Instance().SetGraphicModsEnabled(m_enable_graphics_mods->isChecked());
}
void AdvancedWidget::OnBackendChanged()

View File

@ -8,22 +8,22 @@
class ConfigBool;
class ConfigChoice;
class ConfigInteger;
class GameConfigWidget;
class GraphicsWindow;
namespace Config
{
class Layer;
} // namespace Config
class QCheckBox;
class QComboBox;
class QSpinBox;
class ToolTipCheckBox;
class AdvancedWidget final : public QWidget
{
Q_OBJECT
public:
explicit AdvancedWidget(GraphicsWindow* parent);
AdvancedWidget(GameConfigWidget* parent, Config::Layer* layer);
private:
void LoadSettings();
void SaveSettings();
void CreateWidgets();
void ConnectWidgets();
void AddDescriptions();
@ -52,7 +52,7 @@ private:
ConfigBool* m_dump_xfb_target;
ConfigBool* m_disable_vram_copies;
ConfigBool* m_load_custom_textures;
ConfigBool* m_enable_graphics_mods;
ToolTipCheckBox* m_enable_graphics_mods;
// Texture dumping
ConfigBool* m_dump_textures;
@ -67,7 +67,7 @@ private:
// Misc
ConfigBool* m_enable_cropping;
ConfigBool* m_enable_prog_scan;
ToolTipCheckBox* m_enable_prog_scan;
ConfigBool* m_backend_multithreading;
ConfigBool* m_prefer_vs_for_point_line_expansion;
ConfigBool* m_cpu_cull;
@ -76,6 +76,4 @@ private:
// Experimental
ConfigBool* m_defer_efb_access_invalidation;
ConfigBool* m_manual_texture_sampling;
Config::Layer* m_game_layer = nullptr;
};

View File

@ -11,8 +11,6 @@
#include <QPushButton>
#include <QVBoxLayout>
#include "Common/CommonTypes.h"
#include "Core/Config/GraphicsSettings.h"
#include "Core/ConfigManager.h"
@ -20,7 +18,6 @@
#include "DolphinQt/Config/ConfigControls/ConfigChoice.h"
#include "DolphinQt/Config/ConfigControls/ConfigRadio.h"
#include "DolphinQt/Config/ConfigControls/ConfigSlider.h"
#include "DolphinQt/Config/GameConfigWidget.h"
#include "DolphinQt/Config/Graphics/ColorCorrectionConfigWindow.h"
#include "DolphinQt/Config/Graphics/GraphicsWindow.h"
#include "DolphinQt/Config/Graphics/PostProcessingConfigWindow.h"
@ -34,43 +31,31 @@
#include "VideoCommon/VideoCommon.h"
#include "VideoCommon/VideoConfig.h"
EnhancementsWidget::EnhancementsWidget(GraphicsWindow* parent)
EnhancementsWidget::EnhancementsWidget(GraphicsWindow* parent) : m_block_save(false)
{
CreateWidgets();
LoadPPShaders();
LoadSettings();
ConnectWidgets();
AddDescriptions();
// BackendChanged is called by parent on window creation.
connect(parent, &GraphicsWindow::BackendChanged, this, &EnhancementsWidget::OnBackendChanged);
connect(parent, &GraphicsWindow::UseFastTextureSamplingChanged, this, [this]() {
m_texture_filtering_combo->setEnabled(ReadSetting(Config::GFX_HACK_FAST_TEXTURE_SAMPLING));
});
connect(parent, &GraphicsWindow::UseGPUTextureDecodingChanged, this, [this]() {
m_arbitrary_mipmap_detection->setEnabled(!ReadSetting(Config::GFX_ENABLE_GPU_TEXTURE_DECODING));
});
connect(parent, &GraphicsWindow::BackendChanged,
[this](const QString& backend) { LoadSettings(); });
connect(parent, &GraphicsWindow::UseFastTextureSamplingChanged, this,
&EnhancementsWidget::LoadSettings);
connect(parent, &GraphicsWindow::UseGPUTextureDecodingChanged, this,
&EnhancementsWidget::LoadSettings);
}
EnhancementsWidget::EnhancementsWidget(GameConfigWidget* parent, Config::Layer* layer)
: m_game_layer(layer)
{
CreateWidgets();
LoadPPShaders();
ConnectWidgets();
AddDescriptions();
connect(&Settings::Instance(), &Settings::ConfigChanged, this,
&EnhancementsWidget::OnConfigChanged);
}
constexpr int ANISO_DEFAULT = 0;
constexpr int ANISO_2X = 1;
constexpr int ANISO_4X = 2;
constexpr int ANISO_8X = 3;
constexpr int ANISO_16X = 4;
constexpr int FILTERING_DEFAULT = 0;
constexpr int FILTERING_NEAREST = 1;
constexpr int FILTERING_LINEAR = 2;
constexpr int TEXTURE_FILTERING_DEFAULT = 0;
constexpr int TEXTURE_FILTERING_ANISO_2X = 1;
constexpr int TEXTURE_FILTERING_ANISO_4X = 2;
constexpr int TEXTURE_FILTERING_ANISO_8X = 3;
constexpr int TEXTURE_FILTERING_ANISO_16X = 4;
constexpr int TEXTURE_FILTERING_FORCE_NEAREST = 5;
constexpr int TEXTURE_FILTERING_FORCE_LINEAR = 6;
constexpr int TEXTURE_FILTERING_FORCE_LINEAR_ANISO_2X = 7;
constexpr int TEXTURE_FILTERING_FORCE_LINEAR_ANISO_4X = 8;
constexpr int TEXTURE_FILTERING_FORCE_LINEAR_ANISO_8X = 9;
constexpr int TEXTURE_FILTERING_FORCE_LINEAR_ANISO_16X = 10;
void EnhancementsWidget::CreateWidgets()
{
@ -98,7 +83,7 @@ void EnhancementsWidget::CreateWidgets()
// If the current scale is greater than the max scale in the ini, add sufficient options so that
// when the settings are saved we don't lose the user-modified value from the ini.
const int max_efb_scale =
std::max(ReadSetting(Config::GFX_EFB_SCALE), ReadSetting(Config::GFX_MAX_EFB_SCALE));
std::max(Config::Get(Config::GFX_EFB_SCALE), Config::Get(Config::GFX_MAX_EFB_SCALE));
for (int scale = static_cast<int>(resolution_options.size()); scale <= max_efb_scale; scale++)
{
const QString scale_text = QString::number(scale);
@ -119,60 +104,61 @@ void EnhancementsWidget::CreateWidgets()
}
}
m_ir_combo = new ConfigChoice(resolution_options, Config::GFX_EFB_SCALE, m_game_layer);
m_ir_combo = new ConfigChoice(resolution_options, Config::GFX_EFB_SCALE);
m_ir_combo->setMaxVisibleItems(visible_resolution_option_count);
m_aa_combo = new ConfigComplexChoice(Config::GFX_MSAA, Config::GFX_SSAA, m_game_layer);
m_aa_combo->Add(tr("None"), (u32)1, false);
m_aa_combo = new ToolTipComboBox();
m_texture_filtering_combo =
new ConfigComplexChoice(Config::GFX_ENHANCE_MAX_ANISOTROPY,
Config::GFX_ENHANCE_FORCE_TEXTURE_FILTERING, m_game_layer);
m_texture_filtering_combo = new ToolTipComboBox();
m_texture_filtering_combo->addItem(tr("Default"), TEXTURE_FILTERING_DEFAULT);
m_texture_filtering_combo->addItem(tr("2x Anisotropic"), TEXTURE_FILTERING_ANISO_2X);
m_texture_filtering_combo->addItem(tr("4x Anisotropic"), TEXTURE_FILTERING_ANISO_4X);
m_texture_filtering_combo->addItem(tr("8x Anisotropic"), TEXTURE_FILTERING_ANISO_8X);
m_texture_filtering_combo->addItem(tr("16x Anisotropic"), TEXTURE_FILTERING_ANISO_16X);
m_texture_filtering_combo->addItem(tr("Force Nearest"), TEXTURE_FILTERING_FORCE_NEAREST);
m_texture_filtering_combo->addItem(tr("Force Linear"), TEXTURE_FILTERING_FORCE_LINEAR);
m_texture_filtering_combo->addItem(tr("Force Linear and 2x Anisotropic"),
TEXTURE_FILTERING_FORCE_LINEAR_ANISO_2X);
m_texture_filtering_combo->addItem(tr("Force Linear and 4x Anisotropic"),
TEXTURE_FILTERING_FORCE_LINEAR_ANISO_4X);
m_texture_filtering_combo->addItem(tr("Force Linear and 8x Anisotropic"),
TEXTURE_FILTERING_FORCE_LINEAR_ANISO_8X);
m_texture_filtering_combo->addItem(tr("Force Linear and 16x Anisotropic"),
TEXTURE_FILTERING_FORCE_LINEAR_ANISO_16X);
m_texture_filtering_combo->Add(tr("Default"), ANISO_DEFAULT, FILTERING_DEFAULT);
m_texture_filtering_combo->Add(tr("2x Anisotropic"), ANISO_2X, FILTERING_DEFAULT);
m_texture_filtering_combo->Add(tr("4x Anisotropic"), ANISO_4X, FILTERING_DEFAULT);
m_texture_filtering_combo->Add(tr("8x Anisotropic"), ANISO_8X, FILTERING_DEFAULT);
m_texture_filtering_combo->Add(tr("16x Anisotropic"), ANISO_16X, FILTERING_DEFAULT);
m_texture_filtering_combo->Add(tr("Force Nearest"), ANISO_DEFAULT, FILTERING_NEAREST);
m_texture_filtering_combo->Add(tr("Force Linear"), ANISO_DEFAULT, FILTERING_LINEAR);
m_texture_filtering_combo->Add(tr("Force Linear and 2x Anisotropic"), ANISO_2X, FILTERING_LINEAR);
m_texture_filtering_combo->Add(tr("Force Linear and 4x Anisotropic"), ANISO_4X, FILTERING_LINEAR);
m_texture_filtering_combo->Add(tr("Force Linear and 8x Anisotropic"), ANISO_8X, FILTERING_LINEAR);
m_texture_filtering_combo->Add(tr("Force Linear and 16x Anisotropic"), ANISO_16X,
FILTERING_LINEAR);
m_texture_filtering_combo->Refresh();
m_texture_filtering_combo->setEnabled(ReadSetting(Config::GFX_HACK_FAST_TEXTURE_SAMPLING));
m_output_resampling_combo = new ConfigChoice(
{tr("Default"), tr("Bilinear"), tr("Bicubic: B-Spline"), tr("Bicubic: Mitchell-Netravali"),
tr("Bicubic: Catmull-Rom"), tr("Sharp Bilinear"), tr("Area Sampling")},
Config::GFX_ENHANCE_OUTPUT_RESAMPLING, m_game_layer);
m_output_resampling_combo = new ToolTipComboBox();
m_output_resampling_combo->addItem(tr("Default"),
static_cast<int>(OutputResamplingMode::Default));
m_output_resampling_combo->addItem(tr("Bilinear"),
static_cast<int>(OutputResamplingMode::Bilinear));
m_output_resampling_combo->addItem(tr("Bicubic: B-Spline"),
static_cast<int>(OutputResamplingMode::BSpline));
m_output_resampling_combo->addItem(tr("Bicubic: Mitchell-Netravali"),
static_cast<int>(OutputResamplingMode::MitchellNetravali));
m_output_resampling_combo->addItem(tr("Bicubic: Catmull-Rom"),
static_cast<int>(OutputResamplingMode::CatmullRom));
m_output_resampling_combo->addItem(tr("Sharp Bilinear"),
static_cast<int>(OutputResamplingMode::SharpBilinear));
m_output_resampling_combo->addItem(tr("Area Sampling"),
static_cast<int>(OutputResamplingMode::AreaSampling));
m_configure_color_correction = new ToolTipPushButton(tr("Configure"));
m_pp_effect = new ConfigStringChoice(VideoCommon::PostProcessing::GetShaderList(),
Config::GFX_ENHANCE_POST_SHADER, m_game_layer);
m_pp_effect = new ToolTipComboBox();
m_configure_pp_effect = new NonDefaultQPushButton(tr("Configure"));
m_configure_pp_effect->setDisabled(true);
m_scaled_efb_copy =
new ConfigBool(tr("Scaled EFB Copy"), Config::GFX_HACK_COPY_EFB_SCALED, m_game_layer);
m_scaled_efb_copy = new ConfigBool(tr("Scaled EFB Copy"), Config::GFX_HACK_COPY_EFB_SCALED);
m_per_pixel_lighting =
new ConfigBool(tr("Per-Pixel Lighting"), Config::GFX_ENABLE_PIXEL_LIGHTING, m_game_layer);
new ConfigBool(tr("Per-Pixel Lighting"), Config::GFX_ENABLE_PIXEL_LIGHTING);
m_widescreen_hack =
new ConfigBool(tr("Widescreen Hack"), Config::GFX_WIDESCREEN_HACK, m_game_layer);
m_disable_fog = new ConfigBool(tr("Disable Fog"), Config::GFX_DISABLE_FOG, m_game_layer);
m_widescreen_hack = new ConfigBool(tr("Widescreen Hack"), Config::GFX_WIDESCREEN_HACK);
m_disable_fog = new ConfigBool(tr("Disable Fog"), Config::GFX_DISABLE_FOG);
m_force_24bit_color =
new ConfigBool(tr("Force 24-Bit Color"), Config::GFX_ENHANCE_FORCE_TRUE_COLOR, m_game_layer);
m_disable_copy_filter = new ConfigBool(tr("Disable Copy Filter"),
Config::GFX_ENHANCE_DISABLE_COPY_FILTER, m_game_layer);
m_arbitrary_mipmap_detection =
new ConfigBool(tr("Arbitrary Mipmap Detection"),
Config::GFX_ENHANCE_ARBITRARY_MIPMAP_DETECTION, m_game_layer);
m_arbitrary_mipmap_detection->setEnabled(!ReadSetting(Config::GFX_ENABLE_GPU_TEXTURE_DECODING));
m_hdr = new ConfigBool(tr("HDR Post-Processing"), Config::GFX_ENHANCE_HDR_OUTPUT, m_game_layer);
new ConfigBool(tr("Force 24-Bit Color"), Config::GFX_ENHANCE_FORCE_TRUE_COLOR);
m_disable_copy_filter =
new ConfigBool(tr("Disable Copy Filter"), Config::GFX_ENHANCE_DISABLE_COPY_FILTER);
m_arbitrary_mipmap_detection = new ConfigBool(tr("Arbitrary Mipmap Detection"),
Config::GFX_ENHANCE_ARBITRARY_MIPMAP_DETECTION);
m_hdr = new ConfigBool(tr("HDR Post-Processing"), Config::GFX_ENHANCE_HDR_OUTPUT);
int row = 0;
enhancements_layout->addWidget(new QLabel(tr("Internal Resolution:")), row, 0);
@ -223,27 +209,26 @@ void EnhancementsWidget::CreateWidgets()
m_3d_mode = new ConfigChoice({tr("Off"), tr("Side-by-Side"), tr("Top-and-Bottom"), tr("Anaglyph"),
tr("HDMI 3D"), tr("Passive")},
Config::GFX_STEREO_MODE, m_game_layer);
m_3d_depth =
new ConfigSlider(0, Config::GFX_STEREO_DEPTH_MAXIMUM, Config::GFX_STEREO_DEPTH, m_game_layer);
Config::GFX_STEREO_MODE);
m_3d_depth = new ConfigSlider(0, Config::GFX_STEREO_DEPTH_MAXIMUM, Config::GFX_STEREO_DEPTH);
m_3d_convergence = new ConfigSlider(0, Config::GFX_STEREO_CONVERGENCE_MAXIMUM,
Config::GFX_STEREO_CONVERGENCE, m_game_layer, 100);
Config::GFX_STEREO_CONVERGENCE, 100);
m_3d_swap_eyes = new ConfigBool(tr("Swap Eyes"), Config::GFX_STEREO_SWAP_EYES, m_game_layer);
m_3d_swap_eyes = new ConfigBool(tr("Swap Eyes"), Config::GFX_STEREO_SWAP_EYES);
m_3d_per_eye_resolution = new ConfigBool(
tr("Use Full Resolution Per Eye"), Config::GFX_STEREO_PER_EYE_RESOLUTION_FULL, m_game_layer);
m_3d_per_eye_resolution =
new ConfigBool(tr("Use Full Resolution Per Eye"), Config::GFX_STEREO_PER_EYE_RESOLUTION_FULL);
stereoscopy_layout->addWidget(new QLabel(tr("Stereoscopic 3D Mode:")), 0, 0);
stereoscopy_layout->addWidget(m_3d_mode, 0, 1);
stereoscopy_layout->addWidget(new ConfigSliderLabel(tr("Depth:"), m_3d_depth), 1, 0);
stereoscopy_layout->addWidget(new QLabel(tr("Depth:")), 1, 0);
stereoscopy_layout->addWidget(m_3d_depth, 1, 1);
stereoscopy_layout->addWidget(new ConfigSliderLabel(tr("Convergence:"), m_3d_convergence), 2, 0);
stereoscopy_layout->addWidget(new QLabel(tr("Convergence:")), 2, 0);
stereoscopy_layout->addWidget(m_3d_convergence, 2, 1);
stereoscopy_layout->addWidget(m_3d_swap_eyes, 3, 0);
stereoscopy_layout->addWidget(m_3d_per_eye_resolution, 4, 0);
auto current_stereo_mode = ReadSetting(Config::GFX_STEREO_MODE);
auto current_stereo_mode = Config::Get(Config::GFX_STEREO_MODE);
if (current_stereo_mode != StereoMode::SBS && current_stereo_mode != StereoMode::TAB)
m_3d_per_eye_resolution->hide();
@ -256,53 +241,58 @@ void EnhancementsWidget::CreateWidgets()
void EnhancementsWidget::ConnectWidgets()
{
connect(m_aa_combo, &QComboBox::currentIndexChanged, [this](int) { SaveSettings(); });
connect(m_texture_filtering_combo, &QComboBox::currentIndexChanged,
[this](int) { SaveSettings(); });
connect(m_output_resampling_combo, &QComboBox::currentIndexChanged,
[this](int) { SaveSettings(); });
connect(m_pp_effect, &QComboBox::currentIndexChanged, [this](int) { SaveSettings(); });
connect(m_3d_mode, &QComboBox::currentIndexChanged, [this] {
auto current_stereo_mode = ReadSetting(Config::GFX_STEREO_MODE);
LoadPPShaders();
m_block_save = true;
m_configure_color_correction->setEnabled(g_Config.backend_info.bSupportsPostProcessing);
auto current_stereo_mode = Config::Get(Config::GFX_STEREO_MODE);
LoadPPShaders(current_stereo_mode);
if (current_stereo_mode == StereoMode::SBS || current_stereo_mode == StereoMode::TAB)
m_3d_per_eye_resolution->show();
else
m_3d_per_eye_resolution->hide();
m_block_save = false;
SaveSettings();
});
connect(m_pp_effect, &QComboBox::currentIndexChanged, this, &EnhancementsWidget::ShaderChanged);
connect(m_configure_color_correction, &QPushButton::clicked, this,
&EnhancementsWidget::ConfigureColorCorrection);
connect(m_configure_pp_effect, &QPushButton::clicked, this,
&EnhancementsWidget::ConfigurePostProcessingShader);
connect(&Settings::Instance(), &Settings::ConfigChanged, this, [this] {
const QSignalBlocker blocker(this);
m_block_save = true;
LoadPPShaders(Config::Get(Config::GFX_STEREO_MODE));
m_block_save = false;
});
}
template <typename T>
T EnhancementsWidget::ReadSetting(const Config::Info<T>& setting) const
void EnhancementsWidget::LoadPPShaders(StereoMode stereo_mode)
{
if (m_game_layer != nullptr)
return m_game_layer->Get(setting);
else
return Config::Get(setting);
}
std::vector<std::string> shaders = VideoCommon::PostProcessing::GetShaderList();
if (stereo_mode == StereoMode::Anaglyph)
{
shaders = VideoCommon::PostProcessing::GetAnaglyphShaderList();
}
else if (stereo_mode == StereoMode::Passive)
{
shaders = VideoCommon::PostProcessing::GetPassiveShaderList();
}
void EnhancementsWidget::LoadPPShaders()
{
auto stereo_mode = ReadSetting(Config::GFX_STEREO_MODE);
const QSignalBlocker blocker(m_pp_effect);
m_pp_effect->clear();
// Get shader list
std::vector<std::string> shaders = VideoCommon::PostProcessing::GetShaderList();
if (stereo_mode == StereoMode::Anaglyph)
shaders = VideoCommon::PostProcessing::GetAnaglyphShaderList();
else if (stereo_mode == StereoMode::Passive)
shaders = VideoCommon::PostProcessing::GetPassiveShaderList();
// Populate widget
if (stereo_mode != StereoMode::Anaglyph && stereo_mode != StereoMode::Passive)
m_pp_effect->addItem(tr("(off)"));
auto selected_shader = ReadSetting(Config::GFX_ENHANCE_POST_SHADER);
auto selected_shader = Config::Get(Config::GFX_ENHANCE_POST_SHADER);
bool found = false;
@ -316,7 +306,6 @@ void EnhancementsWidget::LoadPPShaders()
}
}
// Force a shader for StereoModes that require it.
if (!found)
{
if (stereo_mode == StereoMode::Anaglyph)
@ -332,68 +321,21 @@ void EnhancementsWidget::LoadPPShaders()
else
m_pp_effect->setCurrentIndex(0);
// Save forced shader, but avoid forcing an option into a game ini layer.
if (m_game_layer == nullptr && ReadSetting(Config::GFX_ENHANCE_POST_SHADER) != selected_shader)
Config::SetBaseOrCurrent(Config::GFX_ENHANCE_POST_SHADER, selected_shader);
Config::SetBaseOrCurrent(Config::GFX_ENHANCE_POST_SHADER, selected_shader);
}
m_pp_effect->Load();
ShaderChanged();
}
void EnhancementsWidget::OnBackendChanged()
{
m_output_resampling_combo->setEnabled(g_Config.backend_info.bSupportsPostProcessing);
m_configure_color_correction->setEnabled(g_Config.backend_info.bSupportsPostProcessing);
m_hdr->setEnabled(g_Config.backend_info.bSupportsHDROutput);
// Stereoscopy
const bool supports_stereoscopy = g_Config.backend_info.bSupportsGeometryShaders;
m_3d_mode->setEnabled(supports_stereoscopy);
m_3d_convergence->setEnabled(supports_stereoscopy);
m_3d_depth->setEnabled(supports_stereoscopy);
m_3d_swap_eyes->setEnabled(supports_stereoscopy);
// PostProcessing
const bool supports_postprocessing = g_Config.backend_info.bSupportsPostProcessing;
if (!supports_postprocessing)
m_pp_effect->setEnabled(supports_postprocessing);
m_pp_effect->setToolTip(supports_postprocessing ?
QString{} :
tr("%1 doesn't support this feature.")
.arg(tr(g_video_backend->GetDisplayName().c_str())));
VideoCommon::PostProcessingConfiguration pp_shader;
if (selected_shader != "" && supports_postprocessing)
{
m_configure_pp_effect->setEnabled(false);
m_pp_effect->setEnabled(false);
m_pp_effect->setToolTip(
tr("%1 doesn't support this feature.").arg(tr(g_video_backend->GetDisplayName().c_str())));
}
else if (!m_pp_effect->isEnabled() && supports_postprocessing)
{
m_configure_pp_effect->setEnabled(true);
m_pp_effect->setEnabled(true);
m_pp_effect->setToolTip(QString{});
LoadPPShaders();
}
UpdateAAOptions();
}
void EnhancementsWidget::ShaderChanged()
{
auto shader = ReadSetting(Config::GFX_ENHANCE_POST_SHADER);
if (shader == "(off)" || shader == "")
{
shader = "";
// Setting a shader to null in a game ini could be confusing, as it won't be bolded. Remove it
// instead.
if (m_game_layer != nullptr)
m_game_layer->DeleteKey(Config::GFX_ENHANCE_POST_SHADER.GetLocation());
else
Config::SetBaseOrCurrent(Config::GFX_ENHANCE_POST_SHADER, shader);
}
if (shader != "" && m_pp_effect->isEnabled())
{
VideoCommon::PostProcessingConfiguration pp_shader;
pp_shader.LoadShader(shader);
pp_shader.LoadShader(selected_shader);
m_configure_pp_effect->setEnabled(pp_shader.HasOptions());
}
else
@ -402,50 +344,187 @@ void EnhancementsWidget::ShaderChanged()
}
}
void EnhancementsWidget::OnConfigChanged()
void EnhancementsWidget::LoadSettings()
{
// Only used for the GameConfigWidget. Bypasses graphics window signals and backend info due to it
// being global.
m_texture_filtering_combo->setEnabled(ReadSetting(Config::GFX_HACK_FAST_TEXTURE_SAMPLING));
m_arbitrary_mipmap_detection->setEnabled(!ReadSetting(Config::GFX_ENABLE_GPU_TEXTURE_DECODING));
UpdateAAOptions();
m_block_save = true;
m_texture_filtering_combo->setEnabled(Config::Get(Config::GFX_HACK_FAST_TEXTURE_SAMPLING));
m_arbitrary_mipmap_detection->setEnabled(!Config::Get(Config::GFX_ENABLE_GPU_TEXTURE_DECODING));
// Needs to update after deleting a key for 3d settings.
LoadPPShaders();
}
// Anti-Aliasing
void EnhancementsWidget::UpdateAAOptions()
{
const QSignalBlocker blocker_aa(m_aa_combo);
const u32 aa_selection = Config::Get(Config::GFX_MSAA);
const bool ssaa = Config::Get(Config::GFX_SSAA);
const int aniso = Config::Get(Config::GFX_ENHANCE_MAX_ANISOTROPY);
const TextureFilteringMode tex_filter_mode =
Config::Get(Config::GFX_ENHANCE_FORCE_TEXTURE_FILTERING);
m_aa_combo->Reset();
m_aa_combo->Add(tr("None"), (u32)1, false);
m_aa_combo->clear();
std::vector<u32> aa_modes = g_Config.backend_info.AAModes;
for (const u32 aa_mode : aa_modes)
for (const u32 aa_mode : g_Config.backend_info.AAModes)
{
if (aa_mode > 1)
m_aa_combo->Add(tr("%1x MSAA").arg(aa_mode), aa_mode, false);
}
if (aa_mode == 1)
m_aa_combo->addItem(tr("None"), 1);
else
m_aa_combo->addItem(tr("%1x MSAA").arg(aa_mode), static_cast<int>(aa_mode));
if (aa_mode == aa_selection && !ssaa)
m_aa_combo->setCurrentIndex(m_aa_combo->count() - 1);
}
if (g_Config.backend_info.bSupportsSSAA)
{
for (const u32 aa_mode : aa_modes)
for (const u32 aa_mode : g_Config.backend_info.AAModes)
{
if (aa_mode > 1)
m_aa_combo->Add(tr("%1x SSAA").arg(aa_mode), aa_mode, true);
if (aa_mode != 1) // don't show "None" twice
{
// Mark SSAA using negative values in the variant
m_aa_combo->addItem(tr("%1x SSAA").arg(aa_mode), -static_cast<int>(aa_mode));
if (aa_mode == aa_selection && ssaa)
m_aa_combo->setCurrentIndex(m_aa_combo->count() - 1);
}
}
}
m_aa_combo->Refresh();
m_aa_combo->setEnabled(m_aa_combo->count() > 1);
// Backend info can't be populated in the local game settings window. Only enable local game AA
// edits when the backend info is correct - global and local have the same backend.
const bool good_info =
m_game_layer == nullptr || !m_game_layer->Exists(Config::MAIN_GFX_BACKEND.GetLocation()) ||
Config::Get(Config::MAIN_GFX_BACKEND) == m_game_layer->Get(Config::MAIN_GFX_BACKEND);
switch (tex_filter_mode)
{
case TextureFilteringMode::Default:
if (aniso >= 0 && aniso <= 4)
m_texture_filtering_combo->setCurrentIndex(aniso);
else
m_texture_filtering_combo->setCurrentIndex(TEXTURE_FILTERING_DEFAULT);
break;
case TextureFilteringMode::Nearest:
m_texture_filtering_combo->setCurrentIndex(TEXTURE_FILTERING_FORCE_NEAREST);
break;
case TextureFilteringMode::Linear:
if (aniso >= 0 && aniso <= 4)
m_texture_filtering_combo->setCurrentIndex(TEXTURE_FILTERING_FORCE_LINEAR + aniso);
else
m_texture_filtering_combo->setCurrentIndex(TEXTURE_FILTERING_FORCE_LINEAR);
break;
}
m_aa_combo->setEnabled(m_aa_combo->count() > 1 && good_info);
// Resampling
const OutputResamplingMode output_resampling_mode =
Config::Get(Config::GFX_ENHANCE_OUTPUT_RESAMPLING);
m_output_resampling_combo->setCurrentIndex(
m_output_resampling_combo->findData(static_cast<int>(output_resampling_mode)));
m_output_resampling_combo->setEnabled(g_Config.backend_info.bSupportsPostProcessing);
// Color Correction
m_configure_color_correction->setEnabled(g_Config.backend_info.bSupportsPostProcessing);
// Post Processing Shader
LoadPPShaders(Config::Get(Config::GFX_STEREO_MODE));
// Stereoscopy
const bool supports_stereoscopy = g_Config.backend_info.bSupportsGeometryShaders;
m_3d_mode->setEnabled(supports_stereoscopy);
m_3d_convergence->setEnabled(supports_stereoscopy);
m_3d_depth->setEnabled(supports_stereoscopy);
m_3d_swap_eyes->setEnabled(supports_stereoscopy);
m_hdr->setEnabled(g_Config.backend_info.bSupportsHDROutput);
m_block_save = false;
}
void EnhancementsWidget::SaveSettings()
{
if (m_block_save)
return;
const u32 aa_value = static_cast<u32>(std::abs(m_aa_combo->currentData().toInt()));
const bool is_ssaa = m_aa_combo->currentData().toInt() < 0;
Config::SetBaseOrCurrent(Config::GFX_MSAA, aa_value);
Config::SetBaseOrCurrent(Config::GFX_SSAA, is_ssaa);
const int texture_filtering_selection = m_texture_filtering_combo->currentData().toInt();
switch (texture_filtering_selection)
{
case TEXTURE_FILTERING_DEFAULT:
Config::SetBaseOrCurrent(Config::GFX_ENHANCE_MAX_ANISOTROPY, 0);
Config::SetBaseOrCurrent(Config::GFX_ENHANCE_FORCE_TEXTURE_FILTERING,
TextureFilteringMode::Default);
break;
case TEXTURE_FILTERING_ANISO_2X:
Config::SetBaseOrCurrent(Config::GFX_ENHANCE_MAX_ANISOTROPY, 1);
Config::SetBaseOrCurrent(Config::GFX_ENHANCE_FORCE_TEXTURE_FILTERING,
TextureFilteringMode::Default);
break;
case TEXTURE_FILTERING_ANISO_4X:
Config::SetBaseOrCurrent(Config::GFX_ENHANCE_MAX_ANISOTROPY, 2);
Config::SetBaseOrCurrent(Config::GFX_ENHANCE_FORCE_TEXTURE_FILTERING,
TextureFilteringMode::Default);
break;
case TEXTURE_FILTERING_ANISO_8X:
Config::SetBaseOrCurrent(Config::GFX_ENHANCE_MAX_ANISOTROPY, 3);
Config::SetBaseOrCurrent(Config::GFX_ENHANCE_FORCE_TEXTURE_FILTERING,
TextureFilteringMode::Default);
break;
case TEXTURE_FILTERING_ANISO_16X:
Config::SetBaseOrCurrent(Config::GFX_ENHANCE_MAX_ANISOTROPY, 4);
Config::SetBaseOrCurrent(Config::GFX_ENHANCE_FORCE_TEXTURE_FILTERING,
TextureFilteringMode::Default);
break;
case TEXTURE_FILTERING_FORCE_NEAREST:
Config::SetBaseOrCurrent(Config::GFX_ENHANCE_MAX_ANISOTROPY, 0);
Config::SetBaseOrCurrent(Config::GFX_ENHANCE_FORCE_TEXTURE_FILTERING,
TextureFilteringMode::Nearest);
break;
case TEXTURE_FILTERING_FORCE_LINEAR:
Config::SetBaseOrCurrent(Config::GFX_ENHANCE_MAX_ANISOTROPY, 0);
Config::SetBaseOrCurrent(Config::GFX_ENHANCE_FORCE_TEXTURE_FILTERING,
TextureFilteringMode::Linear);
break;
case TEXTURE_FILTERING_FORCE_LINEAR_ANISO_2X:
Config::SetBaseOrCurrent(Config::GFX_ENHANCE_MAX_ANISOTROPY, 1);
Config::SetBaseOrCurrent(Config::GFX_ENHANCE_FORCE_TEXTURE_FILTERING,
TextureFilteringMode::Linear);
break;
case TEXTURE_FILTERING_FORCE_LINEAR_ANISO_4X:
Config::SetBaseOrCurrent(Config::GFX_ENHANCE_MAX_ANISOTROPY, 2);
Config::SetBaseOrCurrent(Config::GFX_ENHANCE_FORCE_TEXTURE_FILTERING,
TextureFilteringMode::Linear);
break;
case TEXTURE_FILTERING_FORCE_LINEAR_ANISO_8X:
Config::SetBaseOrCurrent(Config::GFX_ENHANCE_MAX_ANISOTROPY, 3);
Config::SetBaseOrCurrent(Config::GFX_ENHANCE_FORCE_TEXTURE_FILTERING,
TextureFilteringMode::Linear);
break;
case TEXTURE_FILTERING_FORCE_LINEAR_ANISO_16X:
Config::SetBaseOrCurrent(Config::GFX_ENHANCE_MAX_ANISOTROPY, 4);
Config::SetBaseOrCurrent(Config::GFX_ENHANCE_FORCE_TEXTURE_FILTERING,
TextureFilteringMode::Linear);
break;
}
const int output_resampling_selection = m_output_resampling_combo->currentData().toInt();
Config::SetBaseOrCurrent(Config::GFX_ENHANCE_OUTPUT_RESAMPLING,
static_cast<OutputResamplingMode>(output_resampling_selection));
const bool anaglyph = g_Config.stereo_mode == StereoMode::Anaglyph;
const bool passive = g_Config.stereo_mode == StereoMode::Passive;
Config::SetBaseOrCurrent(Config::GFX_ENHANCE_POST_SHADER,
(!anaglyph && !passive && m_pp_effect->currentIndex() == 0) ?
"" :
m_pp_effect->currentText().toStdString());
VideoCommon::PostProcessingConfiguration pp_shader;
if (Config::Get(Config::GFX_ENHANCE_POST_SHADER) != "")
{
pp_shader.LoadShader(Config::Get(Config::GFX_ENHANCE_POST_SHADER));
m_configure_pp_effect->setEnabled(pp_shader.HasOptions());
}
else
{
m_configure_pp_effect->setEnabled(false);
}
LoadSettings();
}
void EnhancementsWidget::AddDescriptions()
@ -634,7 +713,7 @@ void EnhancementsWidget::ConfigureColorCorrection()
void EnhancementsWidget::ConfigurePostProcessingShader()
{
const std::string shader = ReadSetting(Config::GFX_ENHANCE_POST_SHADER);
const std::string shader = Config::Get(Config::GFX_ENHANCE_POST_SHADER);
PostProcessingConfigWindow dialog(this, shader);
SetQWidgetWindowDecorations(&dialog);
dialog.exec();

View File

@ -9,52 +9,39 @@
class ConfigBool;
class ConfigChoice;
class ConfigComplexChoice;
class ConfigStringChoice;
class ConfigSlider;
class GameConfigWidget;
class GraphicsWindow;
class QCheckBox;
class QComboBox;
class QPushButton;
class QSlider;
class ToolTipComboBox;
class ToolTipPushButton;
enum class StereoMode : int;
namespace Config
{
template <typename T>
class Info;
class Layer;
} // namespace Config
class EnhancementsWidget final : public QWidget
{
Q_OBJECT
public:
explicit EnhancementsWidget(GraphicsWindow* parent);
EnhancementsWidget(GameConfigWidget* parent, Config::Layer* layer);
private:
template <typename T>
T ReadSetting(const Config::Info<T>& setting) const;
void LoadSettings();
void SaveSettings();
void CreateWidgets();
void ConnectWidgets();
void AddDescriptions();
void OnBackendChanged();
void UpdateAAOptions();
void LoadPPShaders();
void ShaderChanged();
void OnConfigChanged();
void ConfigureColorCorrection();
void ConfigurePostProcessingShader();
void LoadPPShaders(StereoMode stereo_mode);
// Enhancements
ConfigChoice* m_ir_combo;
ConfigComplexChoice* m_aa_combo;
ConfigComplexChoice* m_texture_filtering_combo;
ConfigChoice* m_output_resampling_combo;
ConfigStringChoice* m_pp_effect;
ToolTipComboBox* m_aa_combo;
ToolTipComboBox* m_texture_filtering_combo;
ToolTipComboBox* m_output_resampling_combo;
ToolTipComboBox* m_pp_effect;
ToolTipPushButton* m_configure_color_correction;
QPushButton* m_configure_pp_effect;
ConfigBool* m_scaled_efb_copy;
@ -73,5 +60,6 @@ private:
ConfigBool* m_3d_swap_eyes;
ConfigBool* m_3d_per_eye_resolution;
Config::Layer* m_game_layer = nullptr;
int m_msaa_modes;
bool m_block_save;
};

View File

@ -23,7 +23,6 @@
#include "DolphinQt/Config/ConfigControls/ConfigChoice.h"
#include "DolphinQt/Config/ConfigControls/ConfigInteger.h"
#include "DolphinQt/Config/ConfigControls/ConfigRadio.h"
#include "DolphinQt/Config/GameConfigWidget.h"
#include "DolphinQt/Config/Graphics/GraphicsWindow.h"
#include "DolphinQt/Config/ToolTipControls/ToolTipComboBox.h"
#include "DolphinQt/QtUtils/ModalMessageBox.h"
@ -39,6 +38,7 @@ GeneralWidget::GeneralWidget(GraphicsWindow* parent)
LoadSettings();
ConnectWidgets();
AddDescriptions();
emit BackendChanged(QString::fromStdString(Config::Get(Config::MAIN_GFX_BACKEND)));
connect(parent, &GraphicsWindow::BackendChanged, this, &GeneralWidget::OnBackendChanged);
connect(&Settings::Instance(), &Settings::EmulationStateChanged, this, [this](Core::State state) {
@ -47,14 +47,6 @@ GeneralWidget::GeneralWidget(GraphicsWindow* parent)
OnEmulationStateChanged(!Core::IsUninitialized(Core::System::GetInstance()));
}
GeneralWidget::GeneralWidget(GameConfigWidget* parent, Config::Layer* layer) : m_game_layer(layer)
{
CreateWidgets();
LoadSettings();
ConnectWidgets();
AddDescriptions();
}
void GeneralWidget::CreateWidgets()
{
auto* main_layout = new QVBoxLayout;
@ -63,36 +55,33 @@ void GeneralWidget::CreateWidgets()
auto* m_video_box = new QGroupBox(tr("Basic"));
m_video_layout = new QGridLayout();
std::vector<std::pair<QString, QString>> options;
for (auto& backend : VideoBackendBase::GetAvailableBackends())
{
options.push_back(std::make_pair(tr(backend->GetDisplayName().c_str()),
QString::fromStdString(backend->GetName())));
}
m_backend_combo = new ConfigStringChoice(options, Config::MAIN_GFX_BACKEND, m_game_layer);
m_previous_backend = m_backend_combo->currentIndex();
m_backend_combo = new ToolTipComboBox();
m_aspect_combo = new ConfigChoice({tr("Auto"), tr("Force 16:9"), tr("Force 4:3"),
tr("Stretch to Window"), tr("Custom"), tr("Custom (Stretch)")},
Config::GFX_ASPECT_RATIO, m_game_layer);
Config::GFX_ASPECT_RATIO);
m_custom_aspect_label = new QLabel(tr("Custom Aspect Ratio:"));
m_custom_aspect_label->setHidden(true);
constexpr int MAX_CUSTOM_ASPECT_RATIO_RESOLUTION = 10000;
m_custom_aspect_width = new ConfigInteger(1, MAX_CUSTOM_ASPECT_RATIO_RESOLUTION,
Config::GFX_CUSTOM_ASPECT_RATIO_WIDTH, m_game_layer);
Config::GFX_CUSTOM_ASPECT_RATIO_WIDTH);
m_custom_aspect_width->setEnabled(false);
m_custom_aspect_width->setHidden(true);
m_custom_aspect_height = new ConfigInteger(1, MAX_CUSTOM_ASPECT_RATIO_RESOLUTION,
Config::GFX_CUSTOM_ASPECT_RATIO_HEIGHT, m_game_layer);
Config::GFX_CUSTOM_ASPECT_RATIO_HEIGHT);
m_custom_aspect_height->setEnabled(false);
m_custom_aspect_height->setHidden(true);
m_adapter_combo = new ToolTipComboBox;
m_enable_vsync = new ConfigBool(tr("V-Sync"), Config::GFX_VSYNC, m_game_layer);
m_enable_fullscreen =
new ConfigBool(tr("Start in Fullscreen"), Config::MAIN_FULLSCREEN, m_game_layer);
m_enable_vsync = new ConfigBool(tr("V-Sync"), Config::GFX_VSYNC);
m_enable_fullscreen = new ConfigBool(tr("Start in Fullscreen"), Config::MAIN_FULLSCREEN);
m_video_box->setLayout(m_video_layout);
for (auto& backend : VideoBackendBase::GetAvailableBackends())
{
m_backend_combo->addItem(tr(backend->GetDisplayName().c_str()),
QVariant(QString::fromStdString(backend->GetName())));
}
m_video_layout->addWidget(new QLabel(tr("Backend:")), 0, 0);
m_video_layout->addWidget(m_backend_combo, 0, 1, 1, -1);
@ -113,14 +102,11 @@ void GeneralWidget::CreateWidgets()
auto* m_options_box = new QGroupBox(tr("Other"));
auto* m_options_layout = new QGridLayout();
m_show_ping =
new ConfigBool(tr("Show NetPlay Ping"), Config::GFX_SHOW_NETPLAY_PING, m_game_layer);
m_autoadjust_window_size = new ConfigBool(tr("Auto-Adjust Window Size"),
Config::MAIN_RENDER_WINDOW_AUTOSIZE, m_game_layer);
m_show_messages =
new ConfigBool(tr("Show NetPlay Messages"), Config::GFX_SHOW_NETPLAY_MESSAGES, m_game_layer);
m_render_main_window =
new ConfigBool(tr("Render to Main Window"), Config::MAIN_RENDER_TO_MAIN, m_game_layer);
m_show_ping = new ConfigBool(tr("Show NetPlay Ping"), Config::GFX_SHOW_NETPLAY_PING);
m_autoadjust_window_size =
new ConfigBool(tr("Auto-Adjust Window Size"), Config::MAIN_RENDER_WINDOW_AUTOSIZE);
m_show_messages = new ConfigBool(tr("Show NetPlay Messages"), Config::GFX_SHOW_NETPLAY_MESSAGES);
m_render_main_window = new ConfigBool(tr("Render to Main Window"), Config::MAIN_RENDER_TO_MAIN);
m_options_box->setLayout(m_options_layout);
@ -142,13 +128,13 @@ void GeneralWidget::CreateWidgets()
}};
for (size_t i = 0; i < modes.size(); i++)
{
m_shader_compilation_mode[i] = new ConfigRadioInt(
tr(modes[i]), Config::GFX_SHADER_COMPILATION_MODE, static_cast<int>(i), m_game_layer);
m_shader_compilation_mode[i] =
new ConfigRadioInt(tr(modes[i]), Config::GFX_SHADER_COMPILATION_MODE, static_cast<int>(i));
shader_compilation_layout->addWidget(m_shader_compilation_mode[i], static_cast<int>(i / 2),
static_cast<int>(i % 2));
}
m_wait_for_shaders = new ConfigBool(tr("Compile Shaders Before Starting"),
Config::GFX_WAIT_FOR_SHADERS_BEFORE_STARTING, m_game_layer);
Config::GFX_WAIT_FOR_SHADERS_BEFORE_STARTING);
shader_compilation_layout->addWidget(m_wait_for_shaders);
shader_compilation_box->setLayout(shader_compilation_layout);
@ -163,7 +149,7 @@ void GeneralWidget::CreateWidgets()
void GeneralWidget::ConnectWidgets()
{
// Video Backend
connect(m_backend_combo, &QComboBox::currentIndexChanged, this, &GeneralWidget::BackendWarning);
connect(m_backend_combo, &QComboBox::currentIndexChanged, this, &GeneralWidget::SaveSettings);
connect(m_adapter_combo, &QComboBox::currentIndexChanged, this, [&](int index) {
g_Config.iAdapter = index;
Config::SetBaseOrCurrent(Config::GFX_ADAPTER, index);
@ -182,6 +168,10 @@ void GeneralWidget::ConnectWidgets()
void GeneralWidget::LoadSettings()
{
// Video Backend
m_backend_combo->setCurrentIndex(m_backend_combo->findData(
QVariant(QString::fromStdString(Config::Get(Config::MAIN_GFX_BACKEND)))));
const bool is_custom_aspect_ratio =
(Config::Get(Config::GFX_ASPECT_RATIO) == AspectMode::Custom) ||
(Config::Get(Config::GFX_ASPECT_RATIO) == AspectMode::CustomStretch);
@ -192,8 +182,13 @@ void GeneralWidget::LoadSettings()
m_custom_aspect_height->setHidden(!is_custom_aspect_ratio);
}
void GeneralWidget::BackendWarning()
void GeneralWidget::SaveSettings()
{
// Video Backend
const auto current_backend = m_backend_combo->currentData().toString().toStdString();
if (Config::Get(Config::MAIN_GFX_BACKEND) == current_backend)
return;
if (Config::GetActiveLayerForConfig(Config::MAIN_GFX_BACKEND) == Config::LayerType::Base)
{
auto warningMessage = VideoBackendBase::GetAvailableBackends()[m_backend_combo->currentIndex()]
@ -210,14 +205,15 @@ void GeneralWidget::BackendWarning()
SetQWidgetWindowDecorations(&confirm_sw);
if (confirm_sw.exec() != QMessageBox::Yes)
{
m_backend_combo->setCurrentIndex(m_previous_backend);
m_backend_combo->setCurrentIndex(m_backend_combo->findData(
QVariant(QString::fromStdString(Config::Get(Config::MAIN_GFX_BACKEND)))));
return;
}
}
}
m_previous_backend = m_backend_combo->currentIndex();
emit BackendChanged(m_backend_combo->currentData().toString());
Config::SetBaseOrCurrent(Config::MAIN_GFX_BACKEND, current_backend);
emit BackendChanged(QString::fromStdString(current_backend));
}
void GeneralWidget::OnEmulationStateChanged(bool running)
@ -231,10 +227,7 @@ void GeneralWidget::OnEmulationStateChanged(bool running)
std::string current_backend = m_backend_combo->currentData().toString().toStdString();
if (Config::Get(Config::MAIN_GFX_BACKEND) != current_backend)
{
m_backend_combo->Load();
emit BackendChanged(QString::fromStdString(Config::Get(Config::MAIN_GFX_BACKEND)));
}
}
void GeneralWidget::AddDescriptions()
@ -355,6 +348,8 @@ void GeneralWidget::AddDescriptions()
void GeneralWidget::OnBackendChanged(const QString& backend_name)
{
m_backend_combo->setCurrentIndex(m_backend_combo->findData(QVariant(backend_name)));
const QSignalBlocker blocker(m_adapter_combo);
m_adapter_combo->clear();

View File

@ -11,8 +11,6 @@ class ConfigBool;
class ConfigChoice;
class ConfigInteger;
class ConfigRadioInt;
class ConfigStringChoice;
class GameConfigWidget;
class GraphicsWindow;
class QCheckBox;
class QComboBox;
@ -21,24 +19,17 @@ class QRadioButton;
class QGridLayout;
class ToolTipComboBox;
namespace Config
{
class Layer;
} // namespace Config
class GeneralWidget final : public QWidget
{
Q_OBJECT
public:
explicit GeneralWidget(GraphicsWindow* parent);
GeneralWidget(GameConfigWidget* parent, Config::Layer* layer);
signals:
void BackendChanged(const QString& backend);
private:
void LoadSettings();
void BackendWarning();
void SaveSettings();
void CreateWidgets();
void ConnectWidgets();
@ -49,7 +40,7 @@ private:
// Video
QGridLayout* m_video_layout;
ConfigStringChoice* m_backend_combo;
ToolTipComboBox* m_backend_combo;
ToolTipComboBox* m_adapter_combo;
ConfigChoice* m_aspect_combo;
QLabel* m_custom_aspect_label;
@ -65,6 +56,4 @@ private:
ConfigBool* m_render_main_window;
std::array<ConfigRadioInt*, 4> m_shader_compilation_mode{};
ConfigBool* m_wait_for_shaders;
int m_previous_backend = 0;
Config::Layer* m_game_layer = nullptr;
};

View File

@ -15,7 +15,6 @@
#include "DolphinQt/Config/ConfigControls/ConfigBool.h"
#include "DolphinQt/Config/ConfigControls/ConfigSlider.h"
#include "DolphinQt/Config/GameConfigWidget.h"
#include "DolphinQt/Config/Graphics/GraphicsWindow.h"
#include "DolphinQt/Config/ToolTipControls/ToolTipSlider.h"
#include "DolphinQt/Settings.h"
@ -38,14 +37,6 @@ HacksWidget::HacksWidget(GraphicsWindow* parent)
});
}
HacksWidget::HacksWidget(GameConfigWidget* parent, Config::Layer* layer) : m_game_layer(layer)
{
CreateWidgets();
LoadSettings();
ConnectWidgets();
AddDescriptions();
}
void HacksWidget::CreateWidgets()
{
auto* main_layout = new QVBoxLayout;
@ -54,14 +45,14 @@ void HacksWidget::CreateWidgets()
auto* efb_box = new QGroupBox(tr("Embedded Frame Buffer (EFB)"));
auto* efb_layout = new QGridLayout();
efb_box->setLayout(efb_layout);
m_skip_efb_cpu = new ConfigBool(tr("Skip EFB Access from CPU"),
Config::GFX_HACK_EFB_ACCESS_ENABLE, m_game_layer, true);
m_ignore_format_changes = new ConfigBool(
tr("Ignore Format Changes"), Config::GFX_HACK_EFB_EMULATE_FORMAT_CHANGES, m_game_layer, true);
m_store_efb_copies = new ConfigBool(tr("Store EFB Copies to Texture Only"),
Config::GFX_HACK_SKIP_EFB_COPY_TO_RAM, m_game_layer);
m_defer_efb_copies = new ConfigBool(tr("Defer EFB Copies to RAM"),
Config::GFX_HACK_DEFER_EFB_COPIES, m_game_layer);
m_skip_efb_cpu =
new ConfigBool(tr("Skip EFB Access from CPU"), Config::GFX_HACK_EFB_ACCESS_ENABLE, true);
m_ignore_format_changes = new ConfigBool(tr("Ignore Format Changes"),
Config::GFX_HACK_EFB_EMULATE_FORMAT_CHANGES, true);
m_store_efb_copies =
new ConfigBool(tr("Store EFB Copies to Texture Only"), Config::GFX_HACK_SKIP_EFB_COPY_TO_RAM);
m_defer_efb_copies =
new ConfigBool(tr("Defer EFB Copies to RAM"), Config::GFX_HACK_DEFER_EFB_COPIES);
efb_layout->addWidget(m_skip_efb_cpu, 0, 0);
efb_layout->addWidget(m_ignore_format_changes, 0, 1);
@ -78,8 +69,8 @@ void HacksWidget::CreateWidgets()
m_accuracy->setMaximum(2);
m_accuracy->setPageStep(1);
m_accuracy->setTickPosition(QSlider::TicksBelow);
m_gpu_texture_decoding = new ConfigBool(tr("GPU Texture Decoding"),
Config::GFX_ENABLE_GPU_TEXTURE_DECODING, m_game_layer);
m_gpu_texture_decoding =
new ConfigBool(tr("GPU Texture Decoding"), Config::GFX_ENABLE_GPU_TEXTURE_DECODING);
auto* safe_label = new QLabel(tr("Safe"));
safe_label->setAlignment(Qt::AlignRight);
@ -97,12 +88,11 @@ void HacksWidget::CreateWidgets()
auto* xfb_layout = new QVBoxLayout();
xfb_box->setLayout(xfb_layout);
m_store_xfb_copies = new ConfigBool(tr("Store XFB Copies to Texture Only"),
Config::GFX_HACK_SKIP_XFB_COPY_TO_RAM, m_game_layer);
m_immediate_xfb =
new ConfigBool(tr("Immediately Present XFB"), Config::GFX_HACK_IMMEDIATE_XFB, m_game_layer);
m_skip_duplicate_xfbs = new ConfigBool(tr("Skip Presenting Duplicate Frames"),
Config::GFX_HACK_SKIP_DUPLICATE_XFBS, m_game_layer);
m_store_xfb_copies =
new ConfigBool(tr("Store XFB Copies to Texture Only"), Config::GFX_HACK_SKIP_XFB_COPY_TO_RAM);
m_immediate_xfb = new ConfigBool(tr("Immediately Present XFB"), Config::GFX_HACK_IMMEDIATE_XFB);
m_skip_duplicate_xfbs =
new ConfigBool(tr("Skip Presenting Duplicate Frames"), Config::GFX_HACK_SKIP_DUPLICATE_XFBS);
xfb_layout->addWidget(m_store_xfb_copies);
xfb_layout->addWidget(m_immediate_xfb);
@ -114,14 +104,13 @@ void HacksWidget::CreateWidgets()
other_box->setLayout(other_layout);
m_fast_depth_calculation =
new ConfigBool(tr("Fast Depth Calculation"), Config::GFX_FAST_DEPTH_CALC, m_game_layer);
new ConfigBool(tr("Fast Depth Calculation"), Config::GFX_FAST_DEPTH_CALC);
m_disable_bounding_box =
new ConfigBool(tr("Disable Bounding Box"), Config::GFX_HACK_BBOX_ENABLE, m_game_layer, true);
m_vertex_rounding =
new ConfigBool(tr("Vertex Rounding"), Config::GFX_HACK_VERTEX_ROUNDING, m_game_layer);
m_save_texture_cache_state = new ConfigBool(
tr("Save Texture Cache to State"), Config::GFX_SAVE_TEXTURE_CACHE_TO_STATE, m_game_layer);
m_vi_skip = new ConfigBool(tr("VBI Skip"), Config::GFX_HACK_VI_SKIP, m_game_layer);
new ConfigBool(tr("Disable Bounding Box"), Config::GFX_HACK_BBOX_ENABLE, true);
m_vertex_rounding = new ConfigBool(tr("Vertex Rounding"), Config::GFX_HACK_VERTEX_ROUNDING);
m_save_texture_cache_state =
new ConfigBool(tr("Save Texture Cache to State"), Config::GFX_SAVE_TEXTURE_CACHE_TO_STATE);
m_vi_skip = new ConfigBool(tr("VBI Skip"), Config::GFX_HACK_VI_SKIP);
other_layout->addWidget(m_fast_depth_calculation, 0, 0);
other_layout->addWidget(m_disable_bounding_box, 0, 1);

View File

@ -6,22 +6,15 @@
#include <QWidget>
class ConfigBool;
class GameConfigWidget;
class GraphicsWindow;
class QLabel;
class ToolTipSlider;
namespace Config
{
class Layer;
} // namespace Config
class HacksWidget final : public QWidget
{
Q_OBJECT
public:
explicit HacksWidget(GraphicsWindow* parent);
HacksWidget(GameConfigWidget* parent, Config::Layer* layer);
private:
void LoadSettings();
@ -52,8 +45,6 @@ private:
ConfigBool* m_vi_skip;
ConfigBool* m_save_texture_cache_state;
Config::Layer* m_game_layer = nullptr;
void CreateWidgets();
void ConnectWidgets();
void AddDescriptions();

View File

@ -138,9 +138,10 @@ void GraphicsModListWidget::RefreshModList()
for (const GraphicsModConfig& mod : m_mod_group.GetMods())
{
// If no group matches the mod's features, or if the mod has no features, skip it
if (std::ranges::none_of(mod.m_features, [&groups](const GraphicsModFeatureConfig& feature) {
return groups.contains(feature.m_group);
}))
if (std::none_of(mod.m_features.begin(), mod.m_features.end(),
[&groups](const GraphicsModFeatureConfig& feature) {
return groups.contains(feature.m_group);
}))
{
continue;
}

View File

@ -598,8 +598,9 @@ void ShakeMappingIndicator::Update(float elapsed_seconds)
m_position_samples.push_front(ShakeSample{m_motion_state.position / MAX_DISTANCE});
const bool any_non_zero_samples = std::ranges::any_of(
m_position_samples, [](const ShakeSample& s) { return s.state.LengthSquared() != 0.0; });
const bool any_non_zero_samples =
std::any_of(m_position_samples.begin(), m_position_samples.end(),
[](const ShakeSample& s) { return s.state.LengthSquared() != 0.0; });
// Only start moving the line if there's non-zero data.
if (m_grid_line_position || any_non_zero_samples)

View File

@ -228,8 +228,6 @@ void MappingWidget::AddSettingWidgets(QFormLayout* layout, ControllerEmu::Contro
const auto hbox = new QHBoxLayout;
hbox->addWidget(setting_widget);
setting_widget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
hbox->addWidget(CreateSettingAdvancedMappingButton(*setting));
layout->addRow(tr(setting->GetUIName()), hbox);

View File

@ -52,8 +52,8 @@ ConvertDialog::ConvertDialog(QList<std::shared_ptr<const UICommon::GameFile>> fi
m_format->addItem(QStringLiteral("GCZ"), static_cast<int>(DiscIO::BlobType::GCZ));
m_format->addItem(QStringLiteral("WIA"), static_cast<int>(DiscIO::BlobType::WIA));
m_format->addItem(QStringLiteral("RVZ"), static_cast<int>(DiscIO::BlobType::RVZ));
if (std::ranges::all_of(
m_files, [](const auto& file) { return file->GetBlobType() == DiscIO::BlobType::PLAIN; }))
if (std::all_of(m_files.begin(), m_files.end(),
[](const auto& file) { return file->GetBlobType() == DiscIO::BlobType::PLAIN; }))
{
m_format->setCurrentIndex(m_format->count() - 1);
}
@ -153,7 +153,7 @@ void ConvertDialog::OnFormatChanged()
// To support legacy versions of dolphin, we have to check the GCZ block size
// See DiscIO::IsGCZBlockSizeLegacyCompatible() for details
const auto block_size_ok = [this](int block_size) {
return std::ranges::all_of(m_files, [block_size](const auto& file) {
return std::all_of(m_files.begin(), m_files.end(), [block_size](const auto& file) {
return DiscIO::IsGCZBlockSizeLegacyCompatible(block_size, file->GetVolumeSize());
});
};
@ -248,8 +248,9 @@ void ConvertDialog::OnFormatChanged()
m_compression->setEnabled(m_compression->count() > 1);
// Block scrubbing of RVZ containers and Datel discs
const bool scrubbing_allowed = format != DiscIO::BlobType::RVZ &&
std::ranges::none_of(m_files, &UICommon::GameFile::IsDatelDisc);
const bool scrubbing_allowed =
format != DiscIO::BlobType::RVZ &&
std::none_of(m_files.begin(), m_files.end(), std::mem_fn(&UICommon::GameFile::IsDatelDisc));
m_scrub->setEnabled(scrubbing_allowed);
if (!scrubbing_allowed)
@ -308,7 +309,7 @@ void ConvertDialog::Convert()
}
if (!scrub && format == DiscIO::BlobType::GCZ &&
std::ranges::any_of(m_files, [](const auto& file) {
std::any_of(m_files.begin(), m_files.end(), [](const auto& file) {
return file->GetPlatform() == DiscIO::Platform::WiiDisc && !file->IsDatelDisc();
}))
{
@ -320,7 +321,7 @@ void ConvertDialog::Convert()
}
}
if (std::ranges::any_of(m_files, &UICommon::GameFile::IsNKit))
if (std::any_of(m_files.begin(), m_files.end(), std::mem_fn(&UICommon::GameFile::IsNKit)))
{
if (!ShowAreYouSureDialog(
tr("Dolphin can't convert NKit files to non-NKit files. Converting an NKit file in "

View File

@ -379,12 +379,6 @@ void CodeWidget::UpdateSymbols()
{
QString name = QString::fromStdString(symbol.second.name);
// If the symbol has an object name, add it to the entry name.
if (!symbol.second.object_name.empty())
{
name += QString::fromStdString(fmt::format(" ({})", symbol.second.object_name));
}
auto* item = new QListWidgetItem(name);
if (name == selection)
item->setSelected(true);
@ -414,17 +408,8 @@ void CodeWidget::UpdateFunctionCalls(const Common::Symbol* symbol)
if (call_symbol)
{
QString name;
if (!call_symbol->object_name.empty())
{
name = QString::fromStdString(
fmt::format("< {} ({}, {:08x})", call_symbol->name, call_symbol->object_name, addr));
}
else
{
name = QString::fromStdString(fmt::format("< {} ({:08x})", call_symbol->name, addr));
}
const QString name =
QString::fromStdString(fmt::format("> {} ({:08x})", call_symbol->name, addr));
if (!name.contains(filter, Qt::CaseInsensitive))
continue;
@ -448,17 +433,8 @@ void CodeWidget::UpdateFunctionCallers(const Common::Symbol* symbol)
if (caller_symbol)
{
QString name;
if (!caller_symbol->object_name.empty())
{
name = QString::fromStdString(fmt::format("< {} ({}, {:08x})", caller_symbol->name,
caller_symbol->object_name, addr));
}
else
{
name = QString::fromStdString(fmt::format("< {} ({:08x})", caller_symbol->name, addr));
}
const QString name =
QString::fromStdString(fmt::format("< {} ({:08x})", caller_symbol->name, addr));
if (!name.contains(filter, Qt::CaseInsensitive))
continue;

View File

@ -241,7 +241,6 @@
-->
<ItemGroup>
<ClInclude Include="Config\CheatCodeEditor.h" />
<ClInclude Include="Config\ConfigControls\ConfigControl.h" />
<ClInclude Include="Config\GameConfigEdit.h" />
<ClInclude Include="Config\Mapping\MappingCommon.h" />
<ClInclude Include="Config\Mapping\MappingIndicator.h" />

View File

@ -377,15 +377,15 @@ void GameList::ShowContextMenu(const QPoint&)
{
const auto selected_games = GetSelectedGames();
if (std::ranges::all_of(selected_games,
[](const auto& game) { return game->ShouldAllowConversion(); }))
if (std::all_of(selected_games.begin(), selected_games.end(),
[](const auto& game) { return game->ShouldAllowConversion(); }))
{
menu->addAction(tr("Convert Selected Files..."), this, &GameList::ConvertFile);
menu->addSeparator();
}
if (std::ranges::all_of(selected_games,
[](const auto& game) { return DiscIO::IsWii(game->GetPlatform()); }))
if (std::all_of(selected_games.begin(), selected_games.end(),
[](const auto& game) { return DiscIO::IsWii(game->GetPlatform()); }))
{
menu->addAction(tr("Export Wii Saves"), this, &GameList::ExportWiiSave);
menu->addSeparator();
@ -546,13 +546,13 @@ void GameList::OpenProperties()
return;
PropertiesDialog* properties = new PropertiesDialog(this, *game);
// Since the properties dialog locks the game file, it's important to free it as soon as it's
// closed so that the file can be moved or deleted.
properties->setAttribute(Qt::WA_DeleteOnClose, true);
connect(properties, &PropertiesDialog::OpenGeneralSettings, this, &GameList::OpenGeneralSettings);
connect(properties, &PropertiesDialog::OpenGraphicsSettings, this,
&GameList::OpenGraphicsSettings);
connect(properties, &PropertiesDialog::finished, this,
[properties]() { properties->deleteLater(); });
#ifdef USE_RETRO_ACHIEVEMENTS
connect(properties, &PropertiesDialog::OpenAchievementSettings, this,
&GameList::OpenAchievementSettings);

View File

@ -309,9 +309,11 @@ void Settings::RemovePath(const QString& qpath)
std::string path = qpath.toStdString();
std::vector<std::string> paths = Config::GetIsoPaths();
if (std::erase(paths, path) == 0)
auto new_end = std::remove(paths.begin(), paths.end(), path);
if (new_end == paths.end())
return;
paths.erase(new_end, paths.end());
Config::SetIsoPaths(paths);
emit PathRemoved(qpath);
}

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