Compare commits

...

31 Commits

Author SHA1 Message Date
Carles Pastor
fe96bf4108 Flatpak: Upgrade kde runtime to 6.8
this version bundles SDL2-2.30.6, the temporary measure of building the
vendored version from exports is no longer necessary.
2024-11-10 12:06:06 +01:00
OatmealDome
deee3ee410
Merge pull request #13184 from LillyJadeKatrin/retroachievements-forever-dim
Add Approved Patches - Eternal Darkness, Monster Hunter Tri
2024-11-09 00:29:52 -05:00
LillyJadeKatrin
60a0efc69c Add Approved Patches - Eternal Darkness, Monster Hunter Tri
The primary focus of this PR is the Eternal Darkness patch which fixes hanging at startup, which prior to this fix makes Eternal Darkness unplayable in hardcore. The MHTri patch was added as well simply because it could be.
2024-11-08 23:07:06 -05:00
Tilka
4b0b9799a9
Merge pull request #13000 from tygyh/Simplify-type-specifiers
Remove redundant elaborated type specifiers
2024-11-08 23:59:08 +00:00
Tilka
97ea64164b
Merge pull request #13182 from jordan-woyak/wiimote-speaker-remove-dumping-code
WiimoteEmu: Remove disabled and no-longer-compiling wav dumping code.
2024-11-08 22:53:56 +00:00
Jordan Woyak
edb947df4f WiimoteEmu: Remove disabled and no-longer-compiling wav dumping code. 2024-11-08 15:38:05 -06:00
JMC47
7e1074b140
Merge pull request #13172 from deReeperJosh/superchargersfix
IOS/USB: Reconnect HIDv4 Devices after shutdown
2024-11-05 15:02:22 -05:00
JMC47
29172fab9e
Merge pull request #13173 from Tilka/elebits
DSPHLE/AXWii: fix Elebits sound
2024-11-04 22:36:12 -05:00
Tillmann Karras
0488ade1dc DSPHLE/AXWii: fix Elebits sound
Regressed in 37ebb13ece.
2024-11-04 20:47:55 +00:00
Joshua de Reeper
6dbffd1fee IOS/USB: Reconnect HIDv4 Devices after shutdown 2024-11-04 20:12:38 +00:00
Admiral H. Curtiss
59530966f9
Merge pull request #13164 from jordan-woyak/saveable-deduction
Config/IsSettingSaveable: Use class template argument deduction.
2024-11-04 11:05:28 +01:00
Admiral H. Curtiss
b8823457c1
Merge pull request #13165 from jordan-woyak/FullAnalogSurface-rename
InputCommon: Rename AddAnalogInputs to AddFullAnalogSurfaceInputs.
2024-11-04 11:04:50 +01:00
Admiral H. Curtiss
6a59e83bbb
Merge pull request #13168 from Dentomologist/generalwidget_recommend_default_video_backend
Generalwidget: Recommend default video backend
2024-11-04 10:57:24 +01:00
Jordan Woyak
346a9e0f97 InputCommon: Move FullAnalogSurface class definition out of header file. 2024-11-03 15:06:50 -06:00
Jordan Woyak
2f1390e9f9 InputCommon: Rename AddAnalogInputs to AddFullAnalogSurfaceInputs. 2024-11-03 15:06:50 -06:00
Dentomologist
47a86d920f GeneralWidget: Recommend default video backend in tooltip
Recommend the platform's default video backend in the Backend tooltip
instead of always recommending OpenGL.
2024-11-03 12:28:30 -08:00
Dentomologist
7b8610f4ea VideoBackendBase: Clarify function name
Rename GetDefaultBackendName to GetDefaultBackendConfigName to
distinguish it from the display name.
2024-11-03 12:26:57 -08:00
Admiral H. Curtiss
53ede795a2
Merge pull request #13167 from dreamsyntax/dualsense-player-led-disable
InputCommon: Disable Player LED for DualSense Controllers by default
2024-11-03 16:32:20 +01:00
dreamsyntax
2f38a00534 InputCommon: Disable DualSense Player LED 2024-11-02 16:49:36 -07:00
Jordan Woyak
0fd5e86677 Config/IsSettingSaveable: Remove unused includes. 2024-11-02 16:23:49 -05:00
Jordan Woyak
8da7a86b96 Config/IsSettingSaveable: Use class template argument deduction. 2024-11-02 16:22:54 -05:00
Tilka
97931a718f
Merge pull request #13151 from mitaclaw/core-global-system-6
MainWindow: Avoid Global System Accessor
2024-11-02 12:04:28 +00:00
Tilka
466e8de62c
Merge pull request #13163 from jordan-woyak/pragma-once-oopsie
Add include guard to QtUtils.h
2024-11-02 12:01:27 +00:00
Jordan Woyak
d920064779 Add include guard to QtUtils.h 2024-11-02 01:27:07 -05:00
JMC47
000e8fd83d
Merge pull request #13157 from jordan-woyak/sdl-hotplug-fix
ControllerInterface/SDL: Fix device removal event processing.
2024-11-01 18:11:17 -04:00
JosJuice
54b37f6bc4 Translation resources sync with Transifex 2024-11-01 15:00:58 +01:00
JMC47
92608073ef
Merge pull request #13159 from jordan-woyak/datetimeedit
DolphinQt: Ensure skylanders QDateTimeEdit shows a four digit year without forcing dd-mm-yyyy format.
2024-10-31 18:37:08 -04:00
Jordan Woyak
d361d4ba6e ControllerInterface/SDL: Fix device removal event processing. 2024-10-31 14:11:27 -05:00
Jordan Woyak
149a3721ff DolphinQt: Ensure skylanders QDateTimeEdit shows a four digit year without forcing dd-mm-yyyy format. 2024-10-31 02:38:45 -05:00
mitaclaw
12f8b11452 MainWindow: Avoid Global System Accessor 2024-10-24 21:41:35 -07:00
Dr. Dystopia
0aa8e0f477 Remove redundant elaborated type specifiers 2024-08-14 10:41:36 +02:00
76 changed files with 6011 additions and 5296 deletions

View File

@ -44,6 +44,18 @@
"title": "Dead to Rights",
"E23D98B2CE185C3993A40F2495D37E41B971BF91": "Fix audio issues"
},
"GEDE01": {
"title": "Eternal Darkness",
"21068C3CE905FB0CFFAA7408A93154AF8A5295A2": "Fix startup hang"
},
"GEDJ01": {
"title": "Eternal Darkness",
"7061F3CF11BF64D3BA7F32CCF2BAC42FF3614AB6": "Fix startup hang"
},
"GEDP01": {
"title": "Eternal Darkness",
"6F1B00517CBA30BEB738EAA90E71221378CD570D": "Fix startup hang"
},
"GEME7F": {
"title": "Egg Mania: Eggstreme Madness",
"CB04E00918C9C0F161715D21D046ED6620F7ADEF": "Force Progressive Scan"
@ -236,6 +248,14 @@
"title": "Ten Pin Alley 2",
"793642AC6862C2F3412035A9E3D7172CC4A1D5C7": "Fix crash on main menu"
},
"RMHE08": {
"title": "Monster Hunter Tri",
"CCF233DA57B3E75221870DE502955114B0D4E7FA": "Bloom OFF"
},
"RMHJ08": {
"title": "Monster Hunter Tri",
"29D3625B7ED577587E56AA07CB0EB8C47C97E823": "Bloom OFF"
},
"RMHP08": {
"title": "Monster Hunter Tri",
"1720C1173D4698167080DBFC4232F21757C4DA08": "Bloom OFF"

View File

@ -6,3 +6,6 @@ $Fix startup hang
[OnFrame_Enabled]
$Fix startup hang
[Patches_RetroAchievements_Verified]
$Fix startup hang

View File

@ -6,3 +6,6 @@ $Fix startup hang
[OnFrame_Enabled]
$Fix startup hang
[Patches_RetroAchievements_Verified]
$Fix startup hang

View File

@ -6,3 +6,6 @@ $Fix startup hang
[OnFrame_Enabled]
$Fix startup hang
[Patches_RetroAchievements_Verified]
$Fix startup hang

View File

@ -8,3 +8,6 @@ $Bloom OFF
[ActionReplay]
# Add action replay cheats here.
[Patches_RetroAchievements_Verified]
$Bloom OFF

View File

@ -12,3 +12,6 @@ SafeTextureCacheColorSamples = 0
[ActionReplay]
# Add action replay cheats here.
[Patches_RetroAchievements_Verified]
$Bloom OFF

View File

@ -11,3 +11,6 @@ $Bloom OFF
[ActionReplay]
# Add action replay cheats here.
[Patches_RetroAchievements_Verified]
$Bloom OFF

View File

@ -1,22 +0,0 @@
{
"name": "SDL2",
"buildsystem": "autotools",
"config-opts": ["--disable-static"],
"sources": [
{
"type": "dir",
"path": "../../Externals/SDL/SDL"
}
],
"cleanup": [ "/bin/sdl2-config",
"/include",
"/lib/libSDL2.la",
"/lib/libSDL2main.a",
"/lib/libSDL2main.la",
"/lib/libSDL2_test.a",
"/lib/libSDL2_test.la",
"/lib/cmake",
"/share/aclocal",
"/lib/pkgconfig"]
}

View File

@ -1,6 +1,6 @@
app-id: org.DolphinEmu.dolphin-emu
runtime: org.kde.Platform
runtime-version: '6.7'
runtime-version: '6.8'
sdk: org.kde.Sdk
command: dolphin-emu-wrapper
rename-desktop-file: dolphin-emu.desktop
@ -47,9 +47,6 @@ modules:
url: https://github.com/Unrud/xdg-screensaver-shim/archive/0.0.2.tar.gz
sha256: 0ed2a69fe6ee6cbffd2fe16f85116db737f17fb1e79bfb812d893cf15c728399
# build the vendored SDL2 from Externals until the runtime gets 2.30.6
- SDL2/SDL2.json
- name: dolphin-emu
buildsystem: cmake-ninja
config-opts:

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -302,7 +302,7 @@ public final class NativeLibrary
public static native int DefaultCPUCore();
public static native String GetDefaultGraphicsBackendName();
public static native String GetDefaultGraphicsBackendConfigName();
public static native int GetMaxLogLevel();

View File

@ -45,7 +45,7 @@ enum class StringSetting(
Settings.FILE_DOLPHIN,
Settings.SECTION_INI_CORE,
"GFXBackend",
NativeLibrary.GetDefaultGraphicsBackendName()
NativeLibrary.GetDefaultGraphicsBackendConfigName()
),
MAIN_DUMP_PATH(Settings.FILE_DOLPHIN, Settings.SECTION_INI_GENERAL, "DumpPath", ""),
MAIN_LOAD_PATH(Settings.FILE_DOLPHIN, Settings.SECTION_INI_GENERAL, "LoadPath", ""),

View File

@ -408,9 +408,10 @@ JNIEXPORT jint JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_DefaultCPUCo
}
JNIEXPORT jstring JNICALL
Java_org_dolphinemu_dolphinemu_NativeLibrary_GetDefaultGraphicsBackendName(JNIEnv* env, jclass)
Java_org_dolphinemu_dolphinemu_NativeLibrary_GetDefaultGraphicsBackendConfigName(JNIEnv* env,
jclass)
{
return ToJString(env, VideoBackendBase::GetDefaultBackendName());
return ToJString(env, VideoBackendBase::GetDefaultBackendConfigName());
}
JNIEXPORT jint JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_GetMaxLogLevel(JNIEnv*, jclass)

View File

@ -70,8 +70,8 @@ public:
static constexpr std::string_view BLUE = "#0B71C1";
static constexpr std::string_view APPROVED_LIST_FILENAME = "ApprovedInis.json";
static const inline Common::SHA1::Digest APPROVED_LIST_HASH = {
0x50, 0x2F, 0x58, 0x02, 0x94, 0x60, 0x1B, 0x9F, 0x92, 0xC7,
0x04, 0x17, 0x50, 0x2E, 0xF3, 0x09, 0x8C, 0x8C, 0xD6, 0xC0};
0xCC, 0xB4, 0x05, 0x2D, 0x2B, 0xEE, 0xF4, 0x06, 0x4A, 0xC9,
0x57, 0x5D, 0xA9, 0xE9, 0xDE, 0xB7, 0x98, 0xF8, 0x1A, 0x6D};
struct LeaderboardEntry
{

View File

@ -212,7 +212,7 @@ const Info<bool> MAIN_RAM_OVERRIDE_ENABLE{{System::Main, "Core", "RAMOverrideEna
const Info<u32> MAIN_MEM1_SIZE{{System::Main, "Core", "MEM1Size"}, Memory::MEM1_SIZE_RETAIL};
const Info<u32> MAIN_MEM2_SIZE{{System::Main, "Core", "MEM2Size"}, Memory::MEM2_SIZE_RETAIL};
const Info<std::string> MAIN_GFX_BACKEND{{System::Main, "Core", "GFXBackend"},
VideoBackendBase::GetDefaultBackendName()};
VideoBackendBase::GetDefaultBackendConfigName()};
const Info<HSP::HSPDeviceType> MAIN_HSP_DEVICE{{System::Main, "Core", "HSPDevice"},
HSP::HSPDeviceType::None};
const Info<u32> MAIN_ARAM_EXPANSION_SIZE{{System::Main, "Core", "ARAMExpansionSize"}, 0x400000};

View File

@ -6,19 +6,14 @@
#include <algorithm>
#include <array>
#include "Common/Config/Config.h"
#include "Core/Config/AchievementSettings.h"
#include "Core/Config/GraphicsSettings.h"
#include "Core/Config/MainSettings.h"
#include "Core/Config/UISettings.h"
#include "Core/Config/WiimoteSettings.h"
namespace ConfigLoaders
{
bool IsSettingSaveable(const Config::Location& config_location)
{
static constexpr std::array<Config::System, 3> systems_not_saveable = {
Config::System::GCPad, Config::System::WiiPad, Config::System::GCKeyboard};
static constexpr std::array systems_not_saveable = {Config::System::GCPad, Config::System::WiiPad,
Config::System::GCKeyboard};
if (std::find(begin(systems_not_saveable), end(systems_not_saveable), config_location.system) ==
end(systems_not_saveable))

View File

@ -418,7 +418,7 @@ void AXWiiUCode::WritePB(Memory::MemoryManager& memory, u32 addr, const AXPBWii&
case 0xadbc06bd:
memory.CopyToEmuSwapped<u16>(addr, (const u16*)src, updates_begin);
memory.CopyToEmuSwapped<u16>(addr + updates_begin, (const u16*)(src + updates_end),
sizeof(PBUpdatesWii));
gap_begin - updates_end);
memory.CopyToEmuSwapped<u16>(addr + gap_begin, (const u16*)(src + gap_end),
sizeof(pb) - gap_end);
break;

View File

@ -834,7 +834,7 @@ BbaTcpSocket::ConnectingState BbaTcpSocket::Connected(StackRef* ref)
fd_set read_fds;
fd_set write_fds;
fd_set except_fds;
struct timeval t = {0, 0};
timeval t = {0, 0};
FD_ZERO(&read_fds);
FD_ZERO(&write_fds);
FD_ZERO(&except_fds);
@ -965,7 +965,7 @@ sf::Socket::Status BbaUdpSocket::Bind(u16 port, u32 net_ip)
// Subscribe to the SSDP multicast group
// NB: Other groups aren't supported because of HLE
struct ip_mreq mreq;
ip_mreq mreq;
mreq.imr_multiaddr.s_addr = std::bit_cast<u32>(Common::IP_ADDR_SSDP);
mreq.imr_interface.s_addr = net_ip;
if (setsockopt(getHandle(), IPPROTO_IP, IP_ADD_MEMBERSHIP, reinterpret_cast<const char*>(&mreq),

View File

@ -8,21 +8,12 @@
#include "AudioCommon/AudioCommon.h"
#include "Common/CommonTypes.h"
#include "Common/Logging/Log.h"
#include "Common/MathUtil.h"
#include "Core/ConfigManager.h"
#include "Core/HW/WiimoteEmu/WiimoteEmu.h"
#include "Core/System.h"
#include "InputCommon/ControllerEmu/ControlGroup/ControlGroup.h"
#include "InputCommon/ControllerEmu/Setting/NumericSetting.h"
//#define WIIMOTE_SPEAKER_DUMP
#ifdef WIIMOTE_SPEAKER_DUMP
#include <cstdlib>
#include <fstream>
#include "AudioCommon/WaveFile.h"
#include "Common/FileUtil.h"
#endif
namespace WiimoteEmu
{
// Yamaha ADPCM decoder code based on The ffmpeg Project (Copyright (s) 2001-2003)
@ -60,17 +51,6 @@ static s16 adpcm_yamaha_expand_nibble(ADPCMState& s, u8 nibble)
return s.predictor;
}
#ifdef WIIMOTE_SPEAKER_DUMP
std::ofstream ofile;
WaveFileWriter wav;
void stopdamnwav()
{
wav.Stop();
ofile.close();
}
#endif
void SpeakerLogic::SpeakerData(const u8* data, int length, float speaker_pan)
{
// TODO: should we still process samples for the decoder state?
@ -151,28 +131,6 @@ void SpeakerLogic::SpeakerData(const u8* data, int length, float speaker_pan)
const unsigned int sample_rate = sample_rate_dividend / reg_data.sample_rate;
sound_stream->GetMixer()->PushWiimoteSpeakerSamples(
samples.get(), sample_length, Mixer::FIXED_SAMPLE_RATE_DIVIDEND / (sample_rate * 2));
#ifdef WIIMOTE_SPEAKER_DUMP
static int num = 0;
if (num == 0)
{
File::Delete("rmtdump.wav");
File::Delete("rmtdump.bin");
atexit(stopdamnwav);
File::OpenFStream(ofile, "rmtdump.bin", ofile.binary | ofile.out);
wav.Start("rmtdump.wav", 6000);
}
wav.AddMonoSamples(samples.get(), length * 2);
if (ofile.good())
{
for (int i = 0; i < length; i++)
{
ofile << data[i];
}
}
num++;
#endif
}
void SpeakerLogic::Reset()

View File

@ -197,8 +197,8 @@ void init_lib()
namespace WiimoteReal
{
int IOWrite(HANDLE& dev_handle, OVERLAPPED& hid_overlap_write, enum WinWriteMethod& stack,
const u8* buf, size_t len, DWORD* written);
int IOWrite(HANDLE& dev_handle, OVERLAPPED& hid_overlap_write, WinWriteMethod& stack, const u8* buf,
size_t len, DWORD* written);
int IORead(HANDLE& dev_handle, OVERLAPPED& hid_overlap_read, u8* buf, int index);
template <typename T>

View File

@ -798,7 +798,7 @@ IPCReply NetIPTopDevice::HandleInetAToNRequest(const IOCtlRequest& request)
auto& memory = system.GetMemory();
const std::string hostname = memory.GetString(request.buffer_in);
struct hostent* remoteHost = gethostbyname(hostname.c_str());
hostent* remoteHost = gethostbyname(hostname.c_str());
if (remoteHost == nullptr || remoteHost->h_addr_list == nullptr ||
remoteHost->h_addr_list[0] == nullptr)

View File

@ -27,7 +27,7 @@
static DRESULT read_vff_header(IOS::HLE::FS::FileHandle* vff, FATFS* fs)
{
struct IOS::HLE::NWC24::VFFHeader header;
IOS::HLE::NWC24::VFFHeader header;
if (!vff->Read(&header, 1))
{
ERROR_LOG_FMT(IOS_WC24, "Failed to read VFF header.");

View File

@ -770,7 +770,7 @@ WiiSocket::ConnectingState WiiSocket::GetConnectingState() const
fd_set read_fds;
fd_set write_fds;
fd_set except_fds;
struct timeval t = {0, 0};
timeval t = {0, 0};
FD_ZERO(&read_fds);
FD_ZERO(&write_fds);
FD_ZERO(&except_fds);
@ -998,7 +998,7 @@ void WiiSockMan::Update()
{
s32 nfds = 0;
fd_set read_fds, write_fds, except_fds;
struct timeval t = {0, 0};
timeval t = {0, 0};
FD_ZERO(&read_fds);
FD_ZERO(&write_fds);
FD_ZERO(&except_fds);

View File

@ -2505,7 +2505,7 @@ struct hci_filter
uint32_t mask[8]; /* 256 bits */
};
static __inline void hci_filter_set(uint8_t bit, struct hci_filter* filter)
static __inline void hci_filter_set(uint8_t bit, hci_filter* filter)
{
uint8_t off = bit - 1;
@ -2513,7 +2513,7 @@ static __inline void hci_filter_set(uint8_t bit, struct hci_filter* filter)
filter->mask[off] |= (1 << ((bit - 1) & 0x1f));
}
static __inline void hci_filter_clr(uint8_t bit, struct hci_filter* filter)
static __inline void hci_filter_clr(uint8_t bit, hci_filter* filter)
{
uint8_t off = bit - 1;
@ -2581,7 +2581,7 @@ struct btreq
uint16_t btri_link_policy; /* Link Policy */
uint16_t btri_packet_type; /* Packet Type */
} btri;
struct bt_stats btrs; /* unit stats */
bt_stats btrs; /* unit stats */
} btru;
};

View File

@ -96,10 +96,11 @@ std::optional<IPCReply> USB_HIDv4::GetDeviceChange(const IOCtlRequest& request)
m_devicechange_hook_request = std::make_unique<IOCtlRequest>(GetSystem(), request.address);
// If there are pending changes, the reply is sent immediately (instead of on device
// insertion/removal).
if (m_has_pending_changes)
if (m_has_pending_changes || m_is_shut_down)
{
TriggerDeviceChangeReply();
m_has_pending_changes = false;
m_is_shut_down = false;
}
return std::nullopt;
}
@ -114,6 +115,7 @@ IPCReply USB_HIDv4::Shutdown(const IOCtlRequest& request)
memory.Write_U32(0xffffffff, m_devicechange_hook_request->buffer_out);
GetEmulationKernel().EnqueueIPCReply(*m_devicechange_hook_request, -1);
m_devicechange_hook_request.reset();
m_is_shut_down = true;
}
return IPCReply(IPC_SUCCESS);
}

View File

@ -45,6 +45,7 @@ private:
static constexpr u8 HID_CLASS = 0x03;
bool m_has_pending_changes = true;
bool m_is_shut_down = false;
std::mutex m_devicechange_hook_address_mutex;
std::unique_ptr<IOCtlRequest> m_devicechange_hook_request;

View File

@ -258,7 +258,7 @@ static void ReadCommand()
static bool IsDataAvailable()
{
struct timeval t;
timeval t;
fd_set _fds, *fds = &_fds;
FD_ZERO(fds);

View File

@ -318,6 +318,8 @@ add_executable(dolphin-emu
QtUtils/ParallelProgressDialog.h
QtUtils/PartiallyClosableTabWidget.cpp
QtUtils/PartiallyClosableTabWidget.h
QtUtils/QtUtils.cpp
QtUtils/QtUtils.h
QtUtils/SetWindowDecorations.cpp
QtUtils/SetWindowDecorations.h
QtUtils/SignalBlocking.h

View File

@ -239,7 +239,7 @@ void GeneralWidget::AddDescriptions()
"recommended. Different games and different GPUs will behave differently on each "
"backend, so for the best emulation experience it is recommended to try each and "
"select the backend that is least problematic.<br><br><dolphin_emphasis>If unsure, "
"select OpenGL.</dolphin_emphasis>");
"select %1.</dolphin_emphasis>");
static const char TR_FULLSCREEN_DESCRIPTION[] =
QT_TR_NOOP("Uses the entire screen for rendering.<br><br>If disabled, a "
"render window will be created instead.<br><br><dolphin_emphasis>If "
@ -311,7 +311,9 @@ void GeneralWidget::AddDescriptions()
"unsure, leave this unchecked.</dolphin_emphasis>");
m_backend_combo->SetTitle(tr("Backend"));
m_backend_combo->SetDescription(tr(TR_BACKEND_DESCRIPTION));
m_backend_combo->SetDescription(
tr(TR_BACKEND_DESCRIPTION)
.arg(QString::fromStdString(VideoBackendBase::GetDefaultBackendDisplayName())));
m_adapter_combo->SetTitle(tr("Adapter"));

View File

@ -197,6 +197,7 @@
<ClCompile Include="QtUtils\ModalMessageBox.cpp" />
<ClCompile Include="QtUtils\NonDefaultQPushButton.cpp" />
<ClCompile Include="QtUtils\PartiallyClosableTabWidget.cpp" />
<ClCompile Include="QtUtils\QtUtils.cpp" />
<ClCompile Include="QtUtils\SetWindowDecorations.cpp" />
<ClCompile Include="QtUtils\UTF8CodePointCountValidator.cpp" />
<ClCompile Include="QtUtils\WindowActivationEventFilter.cpp" />
@ -404,6 +405,7 @@
<ClInclude Include="QtUtils\FromStdString.h" />
<QtMoc Include="QtUtils\ParallelProgressDialog.h" />
<QtMoc Include="QtUtils\PartiallyClosableTabWidget.h" />
<ClInclude Include="QtUtils\QtUtils.h" />
<ClInclude Include="QtUtils\SetWindowDecorations.h" />
<QtMoc Include="QtUtils\UTF8CodePointCountValidator.h" />
<QtMoc Include="QtUtils\WindowActivationEventFilter.h" />

View File

@ -249,7 +249,8 @@ int main(int argc, char* argv[])
Settings::Instance().InitDefaultPalette();
Settings::Instance().ApplyStyle();
MainWindow win{std::move(boot), static_cast<const char*>(options.get("movie"))};
MainWindow win{Core::System::GetInstance(), std::move(boot),
static_cast<const char*>(options.get("movie"))};
#if defined(USE_ANALYTICS) && USE_ANALYTICS
if (!Config::Get(Config::MAIN_ANALYTICS_PERMISSION_ASKED))

View File

@ -217,9 +217,9 @@ static std::vector<std::string> StringListToStdVector(QStringList list)
return result;
}
MainWindow::MainWindow(std::unique_ptr<BootParameters> boot_parameters,
MainWindow::MainWindow(Core::System& system, std::unique_ptr<BootParameters> boot_parameters,
const std::string& movie_path)
: QMainWindow(nullptr)
: QMainWindow(nullptr), m_system(system)
{
setWindowTitle(QString::fromStdString(Common::GetScmRevStr()));
setWindowIcon(Resources::GetAppIcon());
@ -292,7 +292,7 @@ MainWindow::MainWindow(std::unique_ptr<BootParameters> boot_parameters,
if (!movie_path.empty())
{
std::optional<std::string> savestate_path;
if (Core::System::GetInstance().GetMovie().PlayInput(movie_path, &savestate_path))
if (m_system.GetMovie().PlayInput(movie_path, &savestate_path))
{
m_pending_boot->boot_session_data.SetSavestateData(std::move(savestate_path),
DeleteSavestateAfterBoot::No);
@ -465,17 +465,17 @@ void MainWindow::CreateComponents()
m_wii_tas_input_windows[i] = new WiiTASInputWindow(nullptr, i);
}
m_jit_widget = new JITWidget(Core::System::GetInstance(), this);
m_jit_widget = new JITWidget(m_system, this);
m_log_widget = new LogWidget(this);
m_log_config_widget = new LogConfigWidget(this);
m_memory_widget = new MemoryWidget(Core::System::GetInstance(), this);
m_memory_widget = new MemoryWidget(m_system, this);
m_network_widget = new NetworkWidget(this);
m_register_widget = new RegisterWidget(this);
m_thread_widget = new ThreadWidget(this);
m_watch_widget = new WatchWidget(this);
m_breakpoint_widget = new BreakpointWidget(this);
m_code_widget = new CodeWidget(this);
m_cheats_manager = new CheatsManager(Core::System::GetInstance(), this);
m_cheats_manager = new CheatsManager(m_system, this);
m_assembler_widget = new AssemblerWidget(this);
const auto request_watch = [this](QString name, u32 addr) {
@ -512,7 +512,7 @@ void MainWindow::CreateComponents()
connect(m_memory_widget, &MemoryWidget::RequestWatch, request_watch);
connect(m_breakpoint_widget, &BreakpointWidget::ShowCode, [this](u32 address) {
if (Core::GetState(Core::System::GetInstance()) == Core::State::Paused)
if (Core::GetState(m_system) == Core::State::Paused)
m_code_widget->SetAddress(address, CodeViewWidget::SetAddressUpdate::WithDetailedUpdate);
});
connect(m_breakpoint_widget, &BreakpointWidget::ShowMemory, m_memory_widget,
@ -653,7 +653,7 @@ void MainWindow::ConnectHotkeys()
connect(m_hotkey_scheduler, &HotkeyScheduler::ConnectWiiRemote, this,
&MainWindow::OnConnectWiiRemote);
connect(m_hotkey_scheduler, &HotkeyScheduler::ToggleReadOnlyMode, [this] {
auto& movie = Core::System::GetInstance().GetMovie();
auto& movie = m_system.GetMovie();
bool read_only = !movie.IsReadOnly();
movie.SetReadOnly(read_only);
emit ReadOnlyModeChanged(read_only);
@ -808,14 +808,12 @@ void MainWindow::ChangeDisc()
if (paths.empty())
return;
auto& system = Core::System::GetInstance();
system.GetDVDInterface().ChangeDisc(Core::CPUThreadGuard{system}, paths);
m_system.GetDVDInterface().ChangeDisc(Core::CPUThreadGuard{m_system}, paths);
}
void MainWindow::EjectDisc()
{
auto& system = Core::System::GetInstance();
system.GetDVDInterface().EjectDisc(Core::CPUThreadGuard{system}, DVD::EjectCause::User);
m_system.GetDVDInterface().EjectDisc(Core::CPUThreadGuard{m_system}, DVD::EjectCause::User);
}
void MainWindow::OpenUserFolder()
@ -840,9 +838,9 @@ void MainWindow::Play(const std::optional<std::string>& savestate_path)
// Otherwise, play the default game.
// Otherwise, play the last played game, if there is one.
// Otherwise, prompt for a new game.
if (Core::GetState(Core::System::GetInstance()) == Core::State::Paused)
if (Core::GetState(m_system) == Core::State::Paused)
{
Core::SetState(Core::System::GetInstance(), Core::State::Running);
Core::SetState(m_system, Core::State::Running);
}
else
{
@ -870,12 +868,12 @@ void MainWindow::Play(const std::optional<std::string>& savestate_path)
void MainWindow::Pause()
{
Core::SetState(Core::System::GetInstance(), Core::State::Paused);
Core::SetState(m_system, Core::State::Paused);
}
void MainWindow::TogglePause()
{
if (Core::GetState(Core::System::GetInstance()) == Core::State::Paused)
if (Core::GetState(m_system) == Core::State::Paused)
{
Play();
}
@ -918,7 +916,7 @@ void MainWindow::OnStopComplete()
bool MainWindow::RequestStop()
{
if (Core::IsUninitialized(Core::System::GetInstance()))
if (Core::IsUninitialized(m_system))
{
Core::QueueHostJob([this](Core::System&) { OnStopComplete(); }, true);
return true;
@ -944,13 +942,13 @@ bool MainWindow::RequestStop()
Common::ScopeGuard confirm_lock([this] { m_stop_confirm_showing = false; });
const Core::State state = Core::GetState(Core::System::GetInstance());
const Core::State state = Core::GetState(m_system);
// Only pause the game, if NetPlay is not running
bool pause = !Settings::Instance().GetNetPlayClient();
if (pause)
Core::SetState(Core::System::GetInstance(), Core::State::Paused);
Core::SetState(m_system, Core::State::Paused);
if (rendered_widget_was_active)
{
@ -980,7 +978,7 @@ bool MainWindow::RequestStop()
m_render_widget->SetWaitingForMessageBox(false);
if (pause)
Core::SetState(Core::System::GetInstance(), state);
Core::SetState(m_system, state);
return false;
}
@ -1001,8 +999,8 @@ bool MainWindow::RequestStop()
// Unpause because gracefully shutting down needs the game to actually request a shutdown.
// TODO: Do not unpause in debug mode to allow debugging until the complete shutdown.
if (Core::GetState(Core::System::GetInstance()) == Core::State::Paused)
Core::SetState(Core::System::GetInstance(), Core::State::Running);
if (Core::GetState(m_system) == Core::State::Paused)
Core::SetState(m_system, Core::State::Running);
// Tell NetPlay about the power event
if (NetPlay::IsNetPlayRunning())
@ -1021,21 +1019,20 @@ bool MainWindow::RequestStop()
void MainWindow::ForceStop()
{
Core::Stop(Core::System::GetInstance());
Core::Stop(m_system);
}
void MainWindow::Reset()
{
auto& system = Core::System::GetInstance();
auto& movie = system.GetMovie();
auto& movie = m_system.GetMovie();
if (movie.IsRecordingInput())
movie.SetReset(true);
system.GetProcessorInterface().ResetButton_Tap();
m_system.GetProcessorInterface().ResetButton_Tap();
}
void MainWindow::FrameAdvance()
{
Core::DoFrameStep(Core::System::GetInstance());
Core::DoFrameStep(m_system);
}
void MainWindow::FullScreen()
@ -1126,7 +1123,7 @@ void MainWindow::StartGame(std::unique_ptr<BootParameters>&& parameters)
}
// If we're running, only start a new game once we've stopped the last.
if (!Core::IsUninitialized(Core::System::GetInstance()))
if (!Core::IsUninitialized(m_system))
{
if (!RequestStop())
return;
@ -1140,7 +1137,7 @@ void MainWindow::StartGame(std::unique_ptr<BootParameters>&& parameters)
ShowRenderWidget();
// Boot up, show an error if it fails to load the game.
if (!BootManager::BootCore(Core::System::GetInstance(), std::move(parameters),
if (!BootManager::BootCore(m_system, std::move(parameters),
::GetWindowSystemInfo(m_render_widget->windowHandle())))
{
ModalMessageBox::critical(this, tr("Error"), tr("Failed to init core"), QMessageBox::Ok);
@ -1379,8 +1376,7 @@ void MainWindow::ShowFIFOPlayer()
{
if (!m_fifo_window)
{
m_fifo_window = new FIFOPlayerWindow(Core::System::GetInstance().GetFifoPlayer(),
Core::System::GetInstance().GetFifoRecorder());
m_fifo_window = new FIFOPlayerWindow(m_system.GetFifoPlayer(), m_system.GetFifoRecorder());
connect(m_fifo_window, &FIFOPlayerWindow::LoadFIFORequested, this,
[this](const QString& path) { StartGame(path, ScanForSecondDisc::No); });
}
@ -1426,7 +1422,7 @@ void MainWindow::StateLoad()
this, tr("Select a File"), dialog_path, tr("All Save States (*.sav *.s##);; All Files (*)"));
Config::SetBase(Config::MAIN_CURRENT_STATE_PATH, QFileInfo(path).dir().path().toStdString());
if (!path.isEmpty())
State::LoadAs(Core::System::GetInstance(), path.toStdString());
State::LoadAs(m_system, path.toStdString());
}
void MainWindow::StateSave()
@ -1438,47 +1434,47 @@ void MainWindow::StateSave()
this, tr("Select a File"), dialog_path, tr("All Save States (*.sav *.s##);; All Files (*)"));
Config::SetBase(Config::MAIN_CURRENT_STATE_PATH, QFileInfo(path).dir().path().toStdString());
if (!path.isEmpty())
State::SaveAs(Core::System::GetInstance(), path.toStdString());
State::SaveAs(m_system, path.toStdString());
}
void MainWindow::StateLoadSlot()
{
State::Load(Core::System::GetInstance(), m_state_slot);
State::Load(m_system, m_state_slot);
}
void MainWindow::StateSaveSlot()
{
State::Save(Core::System::GetInstance(), m_state_slot);
State::Save(m_system, m_state_slot);
}
void MainWindow::StateLoadSlotAt(int slot)
{
State::Load(Core::System::GetInstance(), slot);
State::Load(m_system, slot);
}
void MainWindow::StateLoadLastSavedAt(int slot)
{
State::LoadLastSaved(Core::System::GetInstance(), slot);
State::LoadLastSaved(m_system, slot);
}
void MainWindow::StateSaveSlotAt(int slot)
{
State::Save(Core::System::GetInstance(), slot);
State::Save(m_system, slot);
}
void MainWindow::StateLoadUndo()
{
State::UndoLoadState(Core::System::GetInstance());
State::UndoLoadState(m_system);
}
void MainWindow::StateSaveUndo()
{
State::UndoSaveState(Core::System::GetInstance());
State::UndoSaveState(m_system);
}
void MainWindow::StateSaveOldest()
{
State::SaveFirstSaved(Core::System::GetInstance());
State::SaveFirstSaved(m_system);
}
void MainWindow::SetStateSlot(int slot)
@ -1550,7 +1546,7 @@ void MainWindow::NetPlayInit()
bool MainWindow::NetPlayJoin()
{
if (!Core::IsUninitialized(Core::System::GetInstance()))
if (!Core::IsUninitialized(m_system))
{
ModalMessageBox::critical(nullptr, tr("Error"),
tr("Can't start a NetPlay Session while a game is still running!"));
@ -1617,7 +1613,7 @@ bool MainWindow::NetPlayJoin()
bool MainWindow::NetPlayHost(const UICommon::GameFile& game)
{
if (!Core::IsUninitialized(Core::System::GetInstance()))
if (!Core::IsUninitialized(m_system))
{
ModalMessageBox::critical(nullptr, tr("Error"),
tr("Can't start a NetPlay Session while a game is still running!"));
@ -1679,7 +1675,7 @@ void MainWindow::NetPlayQuit()
void MainWindow::UpdateScreenSaverInhibition()
{
const bool inhibit = Config::Get(Config::MAIN_DISABLE_SCREENSAVER) &&
(Core::GetState(Core::System::GetInstance()) == Core::State::Running);
(Core::GetState(m_system) == Core::State::Running);
if (inhibit == m_is_screensaver_inhibited)
return;
@ -1840,7 +1836,7 @@ void MainWindow::OnPlayRecording()
if (dtm_file.isEmpty())
return;
auto& movie = Core::System::GetInstance().GetMovie();
auto& movie = m_system.GetMovie();
if (!movie.IsReadOnly())
{
// let's make the read-only flag consistent at the start of a movie.
@ -1859,10 +1855,9 @@ void MainWindow::OnPlayRecording()
void MainWindow::OnStartRecording()
{
auto& system = Core::System::GetInstance();
auto& movie = system.GetMovie();
if (Core::GetState(system) == Core::State::Starting ||
Core::GetState(system) == Core::State::Stopping || movie.IsRecordingInput() ||
auto& movie = m_system.GetMovie();
if (Core::GetState(m_system) == Core::State::Starting ||
Core::GetState(m_system) == Core::State::Stopping || movie.IsRecordingInput() ||
movie.IsPlayingInput())
{
return;
@ -1894,14 +1889,14 @@ void MainWindow::OnStartRecording()
{
emit RecordingStatusChanged(true);
if (Core::IsUninitialized(system))
if (Core::IsUninitialized(m_system))
Play();
}
}
void MainWindow::OnStopRecording()
{
auto& movie = Core::System::GetInstance().GetMovie();
auto& movie = m_system.GetMovie();
if (movie.IsRecordingInput())
OnExportRecording();
if (movie.IsMovieActive())
@ -1911,13 +1906,12 @@ void MainWindow::OnStopRecording()
void MainWindow::OnExportRecording()
{
auto& system = Core::System::GetInstance();
const Core::CPUThreadGuard guard(system);
const Core::CPUThreadGuard guard(m_system);
QString dtm_file = DolphinFileDialog::getSaveFileName(
this, tr("Save Recording File As"), QString(), tr("Dolphin TAS Movies (*.dtm)"));
if (!dtm_file.isEmpty())
system.GetMovie().SaveRecording(dtm_file.toStdString());
m_system.GetMovie().SaveRecording(dtm_file.toStdString());
}
void MainWindow::OnActivateChat()
@ -1955,11 +1949,10 @@ void MainWindow::ShowTASInput()
}
}
auto& system = Core::System::GetInstance();
for (int i = 0; i < num_wii_controllers; i++)
{
if (Config::Get(Config::GetInfoForWiimoteSource(i)) == WiimoteSource::Emulated &&
(!Core::IsRunning(system) || system.IsWii()))
(!Core::IsRunning(m_system) || m_system.IsWii()))
{
SetQWidgetWindowDecorations(m_wii_tas_input_windows[i]);
m_wii_tas_input_windows[i]->show();
@ -1971,7 +1964,7 @@ void MainWindow::ShowTASInput()
void MainWindow::OnConnectWiiRemote(int id)
{
const Core::CPUThreadGuard guard(Core::System::GetInstance());
const Core::CPUThreadGuard guard(m_system);
if (const auto bt = WiiUtils::GetBluetoothEmuDevice())
{
const auto wm = bt->AccessWiimoteByIndex(id);

View File

@ -54,6 +54,11 @@ class WatchWidget;
class WiiTASInputWindow;
struct WindowSystemInfo;
namespace Core
{
class System;
}
namespace DiscIO
{
enum class Region;
@ -74,7 +79,7 @@ class MainWindow final : public QMainWindow
Q_OBJECT
public:
explicit MainWindow(std::unique_ptr<BootParameters> boot_parameters,
explicit MainWindow(Core::System& system, std::unique_ptr<BootParameters> boot_parameters,
const std::string& movie_path);
~MainWindow();
@ -213,6 +218,8 @@ private:
void dropEvent(QDropEvent* event) override;
QSize sizeHint() const override;
Core::System& m_system;
#ifdef HAVE_XRANDR
std::unique_ptr<X11Utils::XRRConfiguration> m_xrr_config;
#endif

View File

@ -0,0 +1,22 @@
// Copyright 2024 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "DolphinQt/QtUtils/QtUtils.h"
#include <QDateTimeEdit>
namespace QtUtils
{
void ShowFourDigitYear(QDateTimeEdit* widget)
{
if (!widget->displayFormat().contains(QStringLiteral("yyyy")))
{
// Always show the full year, no matter what the locale specifies. Otherwise, two-digit years
// will always be interpreted as in the 21st century.
widget->setDisplayFormat(
widget->displayFormat().replace(QStringLiteral("yy"), QStringLiteral("yyyy")));
}
}
} // namespace QtUtils

View File

@ -0,0 +1,13 @@
// Copyright 2024 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
class QDateTimeEdit;
namespace QtUtils
{
void ShowFourDigitYear(QDateTimeEdit* widget);
}

View File

@ -24,6 +24,7 @@
#include "Core/System.h"
#include "DolphinQt/Config/ConfigControls/ConfigBool.h"
#include "DolphinQt/QtUtils/QtUtils.h"
#include "DolphinQt/QtUtils/SignalBlocking.h"
#include "DolphinQt/Settings.h"
@ -168,13 +169,7 @@ void AdvancedPane::CreateLayout()
m_custom_rtc_datetime->setDisplayFormat(m_custom_rtc_datetime->displayFormat().replace(
QStringLiteral("mm"), QStringLiteral("mm:ss")));
if (!m_custom_rtc_datetime->displayFormat().contains(QStringLiteral("yyyy")))
{
// Always show the full year, no matter what the locale specifies. Otherwise, two-digit years
// will always be interpreted as in the 21st century.
m_custom_rtc_datetime->setDisplayFormat(m_custom_rtc_datetime->displayFormat().replace(
QStringLiteral("yy"), QStringLiteral("yyyy")));
}
QtUtils::ShowFourDigitYear(m_custom_rtc_datetime);
m_custom_rtc_datetime->setDateTimeRange(QDateTime({2000, 1, 1}, {0, 0, 0}, Qt::UTC),
QDateTime({2099, 12, 31}, {23, 59, 59}, Qt::UTC));
m_custom_rtc_datetime->setTimeSpec(Qt::UTC);

View File

@ -17,6 +17,7 @@
#include "Core/IOS/USB/Emulated/Skylanders/Skylander.h"
#include "Core/System.h"
#include "DolphinQt/QtUtils/QtUtils.h"
#include "DolphinQt/QtUtils/SetWindowDecorations.h"
SkylanderModifyDialog::SkylanderModifyDialog(QWidget* parent, u8 slot)
@ -168,8 +169,9 @@ void SkylanderModifyDialog::PopulateSkylanderOptions(QVBoxLayout* layout)
edit_nick->setValidator(
new QRegularExpressionValidator(QRegularExpression(QStringLiteral("^\\p{L}{0,15}$")), this));
edit_playtime->setValidator(new QIntValidator(0, INT_MAX, this));
edit_last_reset->setDisplayFormat(QStringLiteral("dd/MM/yyyy hh:mm"));
edit_last_placed->setDisplayFormat(QStringLiteral("dd/MM/yyyy hh:mm"));
QtUtils::ShowFourDigitYear(edit_last_reset);
QtUtils::ShowFourDigitYear(edit_last_placed);
edit_toy_code->setToolTip(tr("The toy code for this figure. Only available for real figures."));
edit_money->setToolTip(tr("The amount of money this Skylander has. Between 0 and 65000"));

View File

@ -693,7 +693,7 @@ private:
negative = new AndroidAxis(source, axis, true);
if (positive && negative)
AddAnalogInputs(positive, negative);
AddFullAnalogSurfaceInputs(positive, negative);
else if (positive || negative)
AddInput(positive ? positive : negative);
}

View File

@ -130,38 +130,50 @@ bool Device::Control::IsHidden() const
return false;
}
ControlState Device::FullAnalogSurface::GetState() const
class FullAnalogSurface final : public Device::Input
{
return (1 + std::max(0.0, m_high.GetState()) - std::max(0.0, m_low.GetState())) / 2;
}
public:
FullAnalogSurface(Input* low, Input* high) : m_low(*low), m_high(*high) {}
std::string Device::FullAnalogSurface::GetName() const
ControlState GetState() const override
{
return (1 + std::max(0.0, m_high.GetState()) - std::max(0.0, m_low.GetState())) / 2;
}
std::string GetName() const override
{
// E.g. "Full Axis X+"
return "Full " + m_high.GetName();
}
bool IsDetectable() const override { return m_low.IsDetectable() && m_high.IsDetectable(); }
bool IsHidden() const override { return m_low.IsHidden() && m_high.IsHidden(); }
bool IsMatchingName(std::string_view name) const override
{
if (Control::IsMatchingName(name))
return true;
// Old naming scheme was "Axis X-+" which is too visually similar to "Axis X+".
// This has caused countless problems for users with mysterious misconfigurations.
// We match this old name to support old configurations.
const auto old_name = m_low.GetName() + *m_high.GetName().rbegin();
return old_name == name;
}
private:
Input& m_low;
Input& m_high;
};
void Device::AddFullAnalogSurfaceInputs(Input* low, Input* high)
{
// E.g. "Full Axis X+"
return "Full " + m_high.GetName();
}
bool Device::FullAnalogSurface::IsDetectable() const
{
return m_low.IsDetectable() && m_high.IsDetectable();
}
bool Device::FullAnalogSurface::IsHidden() const
{
return m_low.IsHidden() && m_high.IsHidden();
}
bool Device::FullAnalogSurface::IsMatchingName(std::string_view name) const
{
if (Control::IsMatchingName(name))
return true;
// Old naming scheme was "Axis X-+" which is too visually similar to "Axis X+".
// This has caused countless problems for users with mysterious misconfigurations.
// We match this old name to support old configurations.
const auto old_name = m_low.GetName() + *m_high.GetName().rbegin();
return old_name == name;
AddInput(low);
AddInput(high);
AddInput(new FullAnalogSurface(low, high));
AddInput(new FullAnalogSurface(high, low));
}
void Device::AddCombinedInput(std::string name, const std::pair<std::string, std::string>& inputs)

View File

@ -163,28 +163,14 @@ protected:
void AddInput(Input* const i);
void AddOutput(Output* const o);
class FullAnalogSurface final : public Input
{
public:
FullAnalogSurface(Input* low, Input* high) : m_low(*low), m_high(*high) {}
ControlState GetState() const override;
std::string GetName() const override;
bool IsDetectable() const override;
bool IsHidden() const override;
bool IsMatchingName(std::string_view name) const override;
private:
Input& m_low;
Input& m_high;
};
void AddAnalogInputs(Input* low, Input* high)
{
AddInput(low);
AddInput(high);
AddInput(new FullAnalogSurface(low, high));
AddInput(new FullAnalogSurface(high, low));
}
// Pass Inputs for center-neutral (- and +) directions of some axis.
// This function adds those Inputs and also a FullAnalogSurface Input for each direction.
// This is only needed when it's not known if the particular axis is neutral in the center
// or neutral on one of the extremes.
// Some e.g. DInput devices expose a trigger across the full analog surface
// but we have no way of knowing this until the user actually maps the Input,
// so both center-neutral and full-surface Inputs need to be created in that case.
void AddFullAnalogSurfaceInputs(Input* low, Input* high);
void AddCombinedInput(std::string name, const std::pair<std::string, std::string>& inputs);

View File

@ -167,8 +167,8 @@ Joystick::Joystick(const LPDIRECTINPUTDEVICE8 device) : m_device(device)
const LONG& ax = (&m_state_in.lX)[offset];
// each axis gets a negative and a positive input instance associated with it
AddAnalogInputs(new Axis(offset, ax, base, range.lMin - base),
new Axis(offset, ax, base, range.lMax - base));
AddFullAnalogSurfaceInputs(new Axis(offset, ax, base, range.lMin - base),
new Axis(offset, ax, base, range.lMax - base));
}
}

View File

@ -129,7 +129,7 @@ void PipeDevice::AddAxis(const std::string& name, double value)
ax_lo->SetState(value);
m_axes[name + " +"] = ax_hi;
m_axes[name + " -"] = ax_lo;
AddAnalogInputs(ax_lo, ax_hi);
AddFullAnalogSurfaceInputs(ax_lo, ax_hi);
}
void PipeDevice::SetAxis(const std::string& entry, double value)

View File

@ -263,18 +263,16 @@ private:
};
public:
GameController(SDL_GameController* const gamecontroller, SDL_Joystick* const joystick,
const int sdl_index);
GameController(SDL_GameController* const gamecontroller, SDL_Joystick* const joystick);
~GameController();
std::string GetName() const override;
std::string GetSource() const override;
int GetSDLIndex() const;
int GetSDLInstanceID() const;
private:
SDL_GameController* const m_gamecontroller;
std::string m_name;
int m_sdl_index;
SDL_Joystick* const m_joystick;
SDL_Haptic* m_haptic = nullptr;
};
@ -318,7 +316,7 @@ void InputBackend::OpenAndAddDevice(int index)
// SDL tries parsing these as Joysticks
return;
}
auto gamecontroller = std::make_shared<GameController>(gc, js, index);
auto gamecontroller = std::make_shared<GameController>(gc, js);
if (!gamecontroller->Inputs().empty() || !gamecontroller->Outputs().empty())
GetControllerInterface().AddDevice(std::move(gamecontroller));
}
@ -326,25 +324,20 @@ void InputBackend::OpenAndAddDevice(int index)
bool InputBackend::HandleEventAndContinue(const SDL_Event& e)
{
if (e.type == SDL_CONTROLLERDEVICEADDED || e.type == SDL_JOYDEVICEADDED)
if (e.type == SDL_JOYDEVICEADDED)
{
// Avoid handling the event twice on a GameController
if (e.type == SDL_JOYDEVICEADDED && SDL_IsGameController(e.jdevice.which))
{
return true;
}
// NOTE: SDL_JOYDEVICEADDED's `jdevice.which` is a device index in SDL2.
// It will change to an "instance ID" in SDL3.
// OpenAndAddDevice impl and calls will need refactoring when changing to SDL3.
static_assert(!SDL_VERSION_ATLEAST(3, 0, 0), "Refactoring is needed for SDL3.");
OpenAndAddDevice(e.jdevice.which);
}
else if (e.type == SDL_CONTROLLERDEVICEREMOVED || e.type == SDL_JOYDEVICEREMOVED)
else if (e.type == SDL_JOYDEVICEREMOVED)
{
// Avoid handling the event twice on a GameController
if (e.type == SDL_JOYDEVICEREMOVED && SDL_IsGameController(e.jdevice.which))
{
return true;
}
// NOTE: SDL_JOYDEVICEREMOVED's `jdevice.which` is an "instance ID".
GetControllerInterface().RemoveDevice([&e](const auto* device) {
return device->GetSource() == "SDL" &&
static_cast<const GameController*>(device)->GetSDLIndex() == e.jdevice.which;
static_cast<const GameController*>(device)->GetSDLInstanceID() == e.jdevice.which;
});
}
else if (e.type == m_populate_event_type)
@ -442,6 +435,9 @@ InputBackend::InputBackend(ControllerInterface* controller_interface)
// We want buttons to come in as positions, not labels
SDL_SetHint(SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS, "0");
// Disable DualSense Player LEDs; We already colorize the Primary LED
SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS5_PLAYER_LED, "0");
m_hotplug_thread = std::thread([this] {
Common::ScopeGuard quit_guard([] {
// TODO: there seems to be some sort of memory leak with SDL, quit isn't freeing everything up
@ -585,8 +581,8 @@ static constexpr SDLMotionAxisList SDL_AXES_GYRO = {{
// clang-format on
GameController::GameController(SDL_GameController* const gamecontroller,
SDL_Joystick* const joystick, const int sdl_index)
: m_gamecontroller(gamecontroller), m_sdl_index(sdl_index), m_joystick(joystick)
SDL_Joystick* const joystick)
: m_gamecontroller(gamecontroller), m_joystick(joystick)
{
const char* name;
if (gamecontroller)
@ -714,8 +710,8 @@ GameController::GameController(SDL_GameController* const gamecontroller,
const bool is_registered = registered_axes.contains(i);
// each axis gets a negative and a positive input instance associated with it
AddAnalogInputs(new LegacyAxis(m_joystick, i, -32768, is_registered),
new LegacyAxis(m_joystick, i, 32767, is_registered));
AddFullAnalogSurfaceInputs(new LegacyAxis(m_joystick, i, -32768, is_registered),
new LegacyAxis(m_joystick, i, 32767, is_registered));
}
// Hats
@ -809,9 +805,9 @@ std::string GameController::GetSource() const
return "SDL";
}
int GameController::GetSDLIndex() const
int GameController::GetSDLInstanceID() const
{
return m_sdl_index;
return SDL_JoystickInstanceID(m_joystick);
}
std::string GameController::Button::GetName() const

View File

@ -125,9 +125,8 @@ public:
u32 i = 0;
for (auto& axis : m_axes)
{
// AddAnalogInputs adds additional "FullAnalogSurface" Inputs.
AddAnalogInputs(new IndexedAxis(&axis, 0.5, +0.5, i),
new IndexedAxis(&axis, 0.5, -0.5, i));
AddFullAnalogSurfaceInputs(new IndexedAxis(&axis, 0.5, +0.5, i),
new IndexedAxis(&axis, 0.5, -0.5, i));
++i;
}
}

View File

@ -572,7 +572,8 @@ bool evdevDevice::AddNode(std::string devnode, int fd, libevdev* dev)
{
if (libevdev_has_event_code(dev, EV_ABS, axis))
{
AddAnalogInputs(new Axis(num_axis, axis, false, dev), new Axis(num_axis, axis, true, dev));
AddFullAnalogSurfaceInputs(new Axis(num_axis, axis, false, dev),
new Axis(num_axis, axis, true, dev));
++num_axis;
}
}

View File

@ -222,12 +222,18 @@ static VideoBackendBase* GetDefaultVideoBackend()
return backends.front().get();
}
std::string VideoBackendBase::GetDefaultBackendName()
std::string VideoBackendBase::GetDefaultBackendConfigName()
{
auto* default_backend = GetDefaultVideoBackend();
return default_backend ? default_backend->GetName() : "";
}
std::string VideoBackendBase::GetDefaultBackendDisplayName()
{
auto* const default_backend = GetDefaultVideoBackend();
return default_backend ? default_backend->GetDisplayName() : "";
}
const std::vector<std::unique_ptr<VideoBackendBase>>& VideoBackendBase::GetAvailableBackends()
{
static auto s_available_backends = [] {

View File

@ -64,7 +64,8 @@ public:
u32 Video_GetQueryResult(PerfQueryType type);
u16 Video_GetBoundingBox(int index);
static std::string GetDefaultBackendName();
static std::string GetDefaultBackendConfigName();
static std::string GetDefaultBackendDisplayName();
static const std::vector<std::unique_ptr<VideoBackendBase>>& GetAvailableBackends();
static void ActivateBackend(const std::string& name);