Merge branch 'master' of https://github.com/dolphin-emu/dolphin into dolphin-emu-master

This commit is contained in:
Nayla Hanegan 2024-10-23 14:29:49 -04:00
commit 4bd7d38a77
1243 changed files with 15939 additions and 15402 deletions

View file

@ -3,8 +3,6 @@ add_library(uicommon
AutoUpdate.h
CommandLineParse.cpp
CommandLineParse.h
Disassembler.cpp
Disassembler.h
DiscordPresence.cpp
DiscordPresence.h
GameFile.cpp
@ -43,6 +41,13 @@ if ((DEFINED CMAKE_ANDROID_ARCH_ABI AND CMAKE_ANDROID_ARCH_ABI MATCHES "x86|x86_
target_link_libraries(uicommon PRIVATE bdisasm)
endif()
if(UNIX AND NOT APPLE AND NOT ANDROID AND ENABLE_QT)
find_package(Qt6 REQUIRED COMPONENTS DBus)
target_sources(uicommon PRIVATE DBusUtils.cpp)
target_compile_definitions(uicommon PRIVATE -DHAVE_QTDBUS=1)
target_link_libraries(uicommon PUBLIC Qt6::DBus)
endif()
if(X11_FOUND)
target_sources(uicommon PRIVATE X11Utils.cpp)
target_link_libraries(uicommon PUBLIC PkgConfig::XRANDR PkgConfig::X11)
@ -52,28 +57,6 @@ if(TARGET LibUSB::LibUSB)
target_link_libraries(uicommon PRIVATE LibUSB::LibUSB)
endif()
if(ENABLE_LLVM)
find_package(LLVM CONFIG)
if(LLVM_FOUND)
message(STATUS "LLVM found, enabling LLVM support in disassembler")
target_compile_definitions(uicommon PRIVATE HAVE_LLVM)
# Minimal documentation about LLVM's CMake functions is available here:
# https://releases.llvm.org/16.0.0/docs/CMake.html#embedding-llvm-in-your-project
# https://groups.google.com/g/llvm-dev/c/YeEVe7HTasQ?pli=1
#
# However, you have to read the source code in any case.
# Look for LLVM-Config.cmake in your (Unix) system:
# $ find /usr -name LLVM-Config\\.cmake 2>/dev/null
llvm_expand_pseudo_components(LLVM_EXPAND_COMPONENTS
AllTargetsInfos AllTargetsDisassemblers AllTargetsCodeGens
)
llvm_config(uicommon USE_SHARED
mcdisassembler target ${LLVM_EXPAND_COMPONENTS}
)
target_include_directories(uicommon PRIVATE ${LLVM_INCLUDE_DIRS})
endif()
endif()
if(USE_DISCORD_PRESENCE)
target_compile_definitions(uicommon PRIVATE -DUSE_DISCORD_PRESENCE)
target_link_libraries(uicommon PRIVATE discord-rpc)

View file

@ -0,0 +1,204 @@
// Copyright 2024 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "UICommon/DBusUtils.h"
#include <QDBusConnection>
#include <QDBusInterface>
#include <QDBusReply>
#include <QHash>
#include <QObject>
#include <QString>
#include "Common/Logging/Log.h"
namespace DBusUtils
{
static bool InhibitFDO();
static bool InhibitXfce();
static bool InhibitMate();
static bool InhibitPortal();
static void Uninhibit();
static constexpr char s_app_id[] = "org.DolphinEmu.dolphin-emu";
// Cookie for the org.freedesktop.ScreenSaver interface
static uint32_t s_fdo_cookie = 0;
// Cookie for the org.xfce.ScreenSaver interface
static uint32_t s_xfce_cookie = 0;
// Cookie for the org.mate.ScreenSaver interface
static uint32_t s_mate_cookie = 0;
// Return handle for the org.freedesktop.portal.Desktop interface
static QString s_portal_handle;
// Uses D-Bus to inhibit the screensaver
// Tries various D-Bus interfaces until it finds one that works
void InhibitScreenSaver(bool inhibit)
{
if (inhibit)
{
if (s_fdo_cookie || s_xfce_cookie || s_mate_cookie || !s_portal_handle.isEmpty())
return;
if (!InhibitFDO() && !InhibitXfce() && !InhibitMate() && !InhibitPortal())
INFO_LOG_FMT(VIDEO, "Could not inhibit screensaver: No services available");
}
else
Uninhibit();
}
// Inhibits screensaver on Xfce desktop
static bool InhibitXfce()
{
QDBusInterface interface("org.xfce.ScreenSaver", "/", "org.xfce.ScreenSaver");
if (!interface.isValid())
return false;
QDBusReply<uint32_t> reply = interface.call("Inhibit", s_app_id, QObject::tr("Playing a game"));
if (interface.lastError().isValid())
{
WARN_LOG_FMT(VIDEO, "org.xfce.ScreenSaver::Inhibit failed: {}",
interface.lastError().message().toStdString());
return false;
}
INFO_LOG_FMT(VIDEO, "org.xfce.ScreenSaver::Inhibit succeeded");
s_xfce_cookie = reply;
return true;
}
// Inhibits screensaver on the MATE desktop
// MATE advertises support for xdg-desktop-portal Inhibit,
// but it doesn't work as of Fedora 40
static bool InhibitMate()
{
QDBusInterface interface("org.mate.ScreenSaver", "/org/mate/ScreenSaver", "org.mate.ScreenSaver");
if (!interface.isValid())
return false;
QDBusReply<uint32_t> reply = interface.call("Inhibit", s_app_id, QObject::tr("Playing a game"));
if (interface.lastError().isValid())
{
WARN_LOG_FMT(VIDEO, "org.mate.ScreenSaver::Inhibit failed: {}",
interface.lastError().message().toStdString());
return false;
}
INFO_LOG_FMT(VIDEO, "org.mate.ScreenSaver::Inhibit succeeded");
s_mate_cookie = reply;
return true;
}
// Inhibits screensaver on GNOME, KDE and Cinnamon
static bool InhibitFDO()
{
QDBusInterface interface("org.freedesktop.ScreenSaver", "/org/freedesktop/ScreenSaver",
"org.freedesktop.ScreenSaver");
if (!interface.isValid())
return false;
QDBusReply<uint32_t> reply = interface.call("Inhibit", s_app_id, QObject::tr("Playing a game"));
if (interface.lastError().isValid())
{
WARN_LOG_FMT(VIDEO, "org.freedesktop.ScreenSaver::Inhibit failed: {}",
interface.lastError().message().toStdString());
return false;
}
INFO_LOG_FMT(VIDEO, "org.freedesktop.ScreenSaver::Inhibit succeeded");
s_fdo_cookie = reply;
return true;
}
// Inhibits screensaver when sandboxed through Flatpak
// Does not work on KDE Plasma versions before 6.1.5
static bool InhibitPortal()
{
QDBusInterface interface("org.freedesktop.portal.Desktop", "/org/freedesktop/portal/desktop",
"org.freedesktop.portal.Inhibit");
if (!interface.isValid())
return false;
QHash<QString, QVariant> options;
options["handle_token"] = "dolphin_" + QString::number(std::rand(), 0x10);
options["reason"] = QObject::tr("Playing a game");
uint32_t flags = 9; // logout | idle
QDBusReply<QDBusObjectPath> reply = interface.call("Inhibit", "", flags, options);
if (interface.lastError().isValid())
{
WARN_LOG_FMT(VIDEO, "org.freedesktop.portal.Desktop::Inhibit failed: {}",
interface.lastError().message().toStdString());
return false;
}
INFO_LOG_FMT(VIDEO, "org.freedesktop.portal.Desktop::Inhibit succeeded");
s_portal_handle = reply.value().path();
return true;
}
static void Uninhibit()
{
if (s_fdo_cookie)
{
QDBusInterface interface("org.freedesktop.ScreenSaver", "/org/freedesktop/ScreenSaver",
"org.freedesktop.ScreenSaver");
interface.call("UnInhibit", s_fdo_cookie);
if (interface.lastError().isValid())
{
WARN_LOG_FMT(VIDEO, "org.freedesktop.ScreenSaver::UnInhibit failed: {}",
interface.lastError().message().toStdString());
}
else
{
INFO_LOG_FMT(VIDEO, "org.freedesktop.ScreenSaver::UnInhibit succeeded");
}
s_fdo_cookie = 0;
}
if (s_xfce_cookie)
{
QDBusInterface interface("org.xfce.ScreenSaver", "/org/xfce/ScreenSaver",
"org.xfce.ScreenSaver");
interface.call("UnInhibit", s_xfce_cookie);
if (interface.lastError().isValid())
{
WARN_LOG_FMT(VIDEO, "org.xfce.ScreenSaver::UnInhibit failed: {}",
interface.lastError().message().toStdString());
}
else
{
INFO_LOG_FMT(VIDEO, "org.xfce.ScreenSaver::UnInhibit succeeded");
}
s_xfce_cookie = 0;
}
if (s_mate_cookie)
{
QDBusInterface interface("org.mate.ScreenSaver", "/", "org.mate.ScreenSaver");
interface.call("UnInhibit", s_mate_cookie);
if (interface.lastError().isValid())
{
WARN_LOG_FMT(VIDEO, "org.mate.ScreenSaver::UnInhibit failed: {}",
interface.lastError().message().toStdString());
}
else
{
INFO_LOG_FMT(VIDEO, "org.mate.ScreenSaver::UnInhibit succeeded");
}
s_mate_cookie = 0;
}
if (!s_portal_handle.isEmpty())
{
QDBusInterface interface("org.freedesktop.portal.Desktop", s_portal_handle,
"org.freedesktop.portal.Request");
interface.call("Close");
if (interface.lastError().isValid())
{
WARN_LOG_FMT(VIDEO, "org.freedesktop.portal.Request::Close failed: {}",
interface.lastError().message().toStdString());
}
else
{
INFO_LOG_FMT(VIDEO, "org.freedesktop.portal.Request::Close succeeded");
}
s_portal_handle = QString();
}
}
} // namespace DBusUtils

View file

@ -0,0 +1,11 @@
// Copyright 2024 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
namespace DBusUtils
{
void InhibitScreenSaver(bool inhibit);
} // namespace DBusUtils

View file

@ -1,208 +0,0 @@
// Copyright 2008 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "UICommon/Disassembler.h"
#include <sstream>
#if defined(HAVE_LLVM)
#include <fmt/format.h>
#include <llvm-c/Disassembler.h>
#include <llvm-c/Target.h>
#elif defined(_M_X86_64)
#include <disasm.h> // Bochs
#endif
#include "Common/Assert.h"
#include "Common/VariantUtil.h"
#include "Core/PowerPC/JitInterface.h"
#include "Core/System.h"
#if defined(HAVE_LLVM)
class HostDisassemblerLLVM : public HostDisassembler
{
public:
HostDisassemblerLLVM(const std::string& host_disasm, int inst_size = -1,
const std::string& cpu = "");
~HostDisassemblerLLVM()
{
if (m_can_disasm)
LLVMDisasmDispose(m_llvm_context);
}
private:
bool m_can_disasm;
LLVMDisasmContextRef m_llvm_context;
int m_instruction_size;
std::string DisassembleHostBlock(const u8* code_start, const u32 code_size,
u32* host_instructions_count, u64 starting_pc) override;
};
HostDisassemblerLLVM::HostDisassemblerLLVM(const std::string& host_disasm, int inst_size,
const std::string& cpu)
: m_can_disasm(false), m_instruction_size(inst_size)
{
LLVMInitializeAllTargetInfos();
LLVMInitializeAllTargetMCs();
LLVMInitializeAllDisassemblers();
m_llvm_context =
LLVMCreateDisasmCPU(host_disasm.c_str(), cpu.c_str(), nullptr, 0, nullptr, nullptr);
// Couldn't create llvm context
if (!m_llvm_context)
return;
LLVMSetDisasmOptions(m_llvm_context, LLVMDisassembler_Option_AsmPrinterVariant |
LLVMDisassembler_Option_PrintLatency);
m_can_disasm = true;
}
std::string HostDisassemblerLLVM::DisassembleHostBlock(const u8* code_start, const u32 code_size,
u32* host_instructions_count,
u64 starting_pc)
{
if (!m_can_disasm)
return "(No LLVM context)";
u8* disasmPtr = (u8*)code_start;
const u8* end = code_start + code_size;
std::ostringstream x86_disasm;
while ((u8*)disasmPtr < end)
{
char inst_disasm[256];
size_t inst_size = LLVMDisasmInstruction(m_llvm_context, disasmPtr, (u64)(end - disasmPtr),
starting_pc, inst_disasm, 256);
x86_disasm << "0x" << std::hex << starting_pc << "\t";
if (!inst_size)
{
x86_disasm << "Invalid inst:";
if (m_instruction_size != -1)
{
// If we are on an architecture that has a fixed instruction size
// We can continue onward past this bad instruction.
std::string inst_str;
for (int i = 0; i < m_instruction_size; ++i)
inst_str += fmt::format("{:02x}", disasmPtr[i]);
x86_disasm << inst_str << std::endl;
disasmPtr += m_instruction_size;
}
else
{
// We can't continue if we are on an architecture that has flexible instruction sizes
// Dump the rest of the block instead
std::string code_block;
for (int i = 0; (disasmPtr + i) < end; ++i)
code_block += fmt::format("{:02x}", disasmPtr[i]);
x86_disasm << code_block << std::endl;
break;
}
}
else
{
x86_disasm << inst_disasm << std::endl;
disasmPtr += inst_size;
starting_pc += inst_size;
}
(*host_instructions_count)++;
}
return x86_disasm.str();
}
#elif defined(_M_X86_64)
class HostDisassemblerX86 : public HostDisassembler
{
public:
HostDisassemblerX86();
private:
disassembler m_disasm;
std::string DisassembleHostBlock(const u8* code_start, const u32 code_size,
u32* host_instructions_count, u64 starting_pc) override;
};
HostDisassemblerX86::HostDisassemblerX86()
{
m_disasm.set_syntax_intel();
}
std::string HostDisassemblerX86::DisassembleHostBlock(const u8* code_start, const u32 code_size,
u32* host_instructions_count, u64 starting_pc)
{
u64 disasmPtr = (u64)code_start;
const u8* end = code_start + code_size;
std::ostringstream x86_disasm;
while ((u8*)disasmPtr < end)
{
char inst_disasm[256];
disasmPtr += m_disasm.disasm64(disasmPtr, disasmPtr, (u8*)disasmPtr, inst_disasm);
x86_disasm << inst_disasm << std::endl;
(*host_instructions_count)++;
}
return x86_disasm.str();
}
#endif
std::unique_ptr<HostDisassembler> GetNewDisassembler(const std::string& arch)
{
#if defined(HAVE_LLVM)
if (arch == "x86")
return std::make_unique<HostDisassemblerLLVM>("x86_64-none-unknown");
if (arch == "aarch64")
return std::make_unique<HostDisassemblerLLVM>("aarch64-none-unknown", 4, "cortex-a57");
if (arch == "armv7")
return std::make_unique<HostDisassemblerLLVM>("armv7-none-unknown", 4, "cortex-a15");
#elif defined(_M_X86_64)
if (arch == "x86")
return std::make_unique<HostDisassemblerX86>();
#endif
return std::make_unique<HostDisassembler>();
}
DisassembleResult DisassembleBlock(HostDisassembler* disasm, u32 address)
{
auto res = Core::System::GetInstance().GetJitInterface().GetHostCode(address);
return std::visit(overloaded{[&](JitInterface::GetHostCodeError error) {
DisassembleResult result;
switch (error)
{
case JitInterface::GetHostCodeError::NoJitActive:
result.text = "(No JIT active)";
break;
case JitInterface::GetHostCodeError::NoTranslation:
result.text = "(No translation)";
break;
default:
ASSERT(false);
break;
}
result.entry_address = address;
result.instruction_count = 0;
result.code_size = 0;
return result;
},
[&](JitInterface::GetHostCodeResult host_result) {
DisassembleResult new_result;
u32 instruction_count = 0;
new_result.text = disasm->DisassembleHostBlock(
host_result.code, host_result.code_size, &instruction_count,
(u64)host_result.code);
new_result.entry_address = host_result.entry_address;
new_result.code_size = host_result.code_size;
new_result.instruction_count = instruction_count;
return new_result;
}},
res);
}

View file

@ -1,30 +0,0 @@
// Copyright 2008 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <memory>
#include <string>
#include "Common/CommonTypes.h"
class HostDisassembler
{
public:
virtual ~HostDisassembler() {}
virtual std::string DisassembleHostBlock(const u8* code_start, const u32 code_size,
u32* host_instructions_count, u64 starting_pc)
{
return "(No disassembler)";
}
};
struct DisassembleResult
{
std::string text;
u32 entry_address = 0;
u32 instruction_count = 0;
u32 code_size = 0;
};
std::unique_ptr<HostDisassembler> GetNewDisassembler(const std::string& arch);
DisassembleResult DisassembleBlock(HostDisassembler* disasm, u32 address);

View file

@ -613,11 +613,10 @@ bool GameFile::CheckIfTwoDiscGame(const std::string& game_id) const
"S6T",
"SDQ",
};
static_assert(std::is_sorted(two_disc_game_id_prefixes.begin(), two_disc_game_id_prefixes.end()));
static_assert(std::ranges::is_sorted(two_disc_game_id_prefixes));
std::string_view game_id_prefix(game_id.data(), GAME_ID_PREFIX_SIZE);
return std::binary_search(two_disc_game_id_prefixes.begin(), two_disc_game_id_prefixes.end(),
game_id_prefix);
return std::ranges::binary_search(two_disc_game_id_prefixes, game_id_prefix);
}
std::string GameFile::GetNetPlayName(const Core::TitleDatabase& title_database) const

View file

@ -85,7 +85,7 @@ std::vector<ResourcePack>& GetPacks()
std::vector<ResourcePack*> GetLowerPriorityPacks(const ResourcePack& pack)
{
std::vector<ResourcePack*> list;
for (auto it = std::find(packs.begin(), packs.end(), pack) + 1; it != packs.end(); ++it)
for (auto it = std::ranges::find(packs, pack) + 1; it != packs.end(); ++it)
{
auto& entry = *it;
if (!IsInstalled(pack))
@ -100,7 +100,7 @@ std::vector<ResourcePack*> GetLowerPriorityPacks(const ResourcePack& pack)
std::vector<ResourcePack*> GetHigherPriorityPacks(const ResourcePack& pack)
{
std::vector<ResourcePack*> list;
auto end = std::find(packs.begin(), packs.end(), pack);
auto end = std::ranges::find(packs, pack);
for (auto it = packs.begin(); it != end; ++it)
{
@ -145,7 +145,7 @@ bool Remove(ResourcePack& pack)
if (!result)
return false;
auto pack_iterator = std::find(packs.begin(), packs.end(), pack);
auto pack_iterator = std::ranges::find(packs, pack);
if (pack_iterator == packs.end())
return false;

View file

@ -170,10 +170,9 @@ bool ResourcePack::Install(const std::string& path)
continue;
const std::string texture_name = texture_zip_path.substr(texture_zip_path_prefix.size());
auto texture_it = std::find_if(
m_textures.cbegin(), m_textures.cend(), [&texture_name](const std::string& texture) {
return mz_path_compare_wc(texture.c_str(), texture_name.c_str(), 1) == MZ_OK;
});
auto texture_it = std::ranges::find_if(m_textures, [&texture_name](const std::string& texture) {
return mz_path_compare_wc(texture.c_str(), texture_name.c_str(), 1) == MZ_OK;
});
if (texture_it == m_textures.cend())
continue;
const auto texture = *texture_it;
@ -307,9 +306,4 @@ bool ResourcePack::operator==(const ResourcePack& pack) const
return pack.GetPath() == m_path;
}
bool ResourcePack::operator!=(const ResourcePack& pack) const
{
return !operator==(pack);
}
} // namespace ResourcePack

View file

@ -30,7 +30,6 @@ public:
bool Uninstall(const std::string& path);
bool operator==(const ResourcePack& pack) const;
bool operator!=(const ResourcePack& pack) const;
private:
bool m_valid = true;

View file

@ -50,8 +50,8 @@
#include "UICommon/DiscordPresence.h"
#include "UICommon/USBUtils.h"
#ifdef HAVE_X11
#include "UICommon/X11Utils.h"
#ifdef HAVE_QTDBUS
#include "UICommon/DBusUtils.h"
#endif
#ifdef __APPLE__
@ -225,7 +225,7 @@ void SetLocale(std::string locale_name)
if (locale_name == "en")
locale_name = "en_GB";
std::replace(locale_name.begin(), locale_name.end(), OTHER_SEPARATOR, PREFERRED_SEPARATOR);
std::ranges::replace(locale_name, OTHER_SEPARATOR, PREFERRED_SEPARATOR);
// Use the specified locale if supported.
if (set_locale(locale_name))
@ -480,17 +480,13 @@ bool TriggerSTMPowerEvent()
return true;
}
#ifdef HAVE_X11
void InhibitScreenSaver(Window win, bool inhibit)
#else
void InhibitScreenSaver(bool inhibit)
#endif
{
// Inhibit the screensaver. Depending on the operating system this may also
// disable low-power states and/or screen dimming.
#ifdef HAVE_X11
X11Utils::InhibitScreensaver(win, inhibit);
#ifdef HAVE_QTDBUS
DBusUtils::InhibitScreenSaver(inhibit);
#endif
#ifdef _WIN32

View file

@ -17,11 +17,7 @@ void Shutdown();
void InitControllers(const WindowSystemInfo& wsi);
void ShutdownControllers();
#ifdef HAVE_X11
void InhibitScreenSaver(unsigned long win, bool enable);
#else
void InhibitScreenSaver(bool enable);
#endif
void InhibitScreenSaver(bool inhibit);
// Calls std::locale::global, selecting a fallback locale if the
// requested locale isn't available

View file

@ -45,24 +45,6 @@ bool ToggleFullscreen(Display* dpy, Window win)
return true;
}
void InhibitScreensaver(Window win, bool suspend)
{
char id[11];
snprintf(id, sizeof(id), "0x%lx", win);
// Call xdg-screensaver
char* argv[4] = {(char*)"xdg-screensaver", (char*)(suspend ? "suspend" : "resume"), id, nullptr};
pid_t pid;
if (!posix_spawnp(&pid, "xdg-screensaver", nullptr, nullptr, argv, environ))
{
int status;
while (waitpid(pid, &status, 0) == -1)
;
INFO_LOG_FMT(VIDEO, "Started xdg-screensaver (PID = {})", pid);
}
}
#ifdef HAVE_XRANDR
XRRConfiguration::XRRConfiguration(Display* _dpy, Window _win)
: dpy(_dpy), win(_win), screenResources(nullptr), outputInfo(nullptr), crtcInfo(nullptr),

View file

@ -20,10 +20,6 @@
namespace X11Utils
{
bool ToggleFullscreen(Display* dpy, Window win);
Window XWindowFromHandle(void* Handle);
Display* XDisplayFromHandle(void* Handle);
void InhibitScreensaver(Window win, bool suspend);
#ifdef HAVE_XRANDR
class XRRConfiguration