Compare commits

..
Author SHA1 Message Date
jasaavedandTy 93f10864c1 Input/FullscreenUI: Add Generic controller glyph style
Adds a Generic option alongside Xbox, PlayStation, and Nintendo for forcing plain, non-brand button glyphs.
2026-08-02 10:05:38 -04:00
jasaavedandTy 4f58055e76 Input/FullscreenUI: Fix SDL unknown-controller icon fallback and add missing Standard/Xbox/Nintendo button name tables
Fixes the SDL input source's icon and name lookups for controllers SDL can't confidently brand. Unknown-type pads no longer default to PlayStation glyphs, and STANDARD, XBOX360, XBOXONE, and NINTENDO_SWITCH_PRO now each get their own button name table instead of falling back to generic "Face South"-style text.

This is visible in the Qt Controller Settings binding list, and as icons in FullscreenUI's Controller Settings and save-state legend.
2026-08-02 10:05:38 -04:00
jasaavedandTy 96c1307f30 Input: Fix Xinput controller icon and layout detection
Fixes three related bugs that broke button icons and layout detection for XInput controllers:

- XInputSource::ConvertKeyToIcon checked for the wrong source type (SDL instead of XInput) and never resolved icons.
- SDLInputSource reused generic/unbranded icons for Xbox 360/One controller types instead of proper Xbox glyphs.
- InputManager::PreprocessEvent always queried the SDL source for controller layout regardless of which source produced the event, causing FullscreenUI to fall back to PlayStation icons whenever SDL was disabled.
2026-08-02 10:05:38 -04:00
jasaavedandTy 77e6a0f870 Input: Fix menu navigation incorrectly using per-profile bindings
Previously, ImGui would follow whichever pad bindings were currently active for gameplay, including per-game profile overrides. The UI's button prompts don't dynamically update to reflect this, so it could be confusing which bindings were actually in effect.

Menu navigation now uses each source's static, position-based table first (e.g. SDL's SOUTH/EAST/NORTH/WEST), falling back to the Shared/global map only for sources without one (DInput). Per-game profiles still never affect UI navigation.
2026-08-02 10:05:38 -04:00
lightningterror 2ce2cb6459 GS/DX11: Fix uav null_texture usage.
We shouldn't use Feedback alone here as it would cause issues and trigger ValidateUsageAndFormat assert, use FeedbackTarget as that's the next best without uav.
2026-08-01 19:53:35 +02:00
TheLastRarandlightningterror 779d5c4339 GS/VK: Workaround Nvidia issue when swapping ROV targets 2026-07-31 23:20:42 +02:00
lightningterror fe55f87289 GS/VK: Remove undefined unused shader macro. 2026-07-31 17:29:28 +02:00
TJnotJTandlightningterror ab6bc30aec GS:DX11: Fix typo in query destruction.
Fixes a bug when disabling then enabling pipeline stats.
2026-07-31 17:28:57 +02:00
TJnotJTandlightningterror 5793dbc1ef GS:HW: Only enable GPU timing/stats in backend if the option is enabled.
Helps prevent a crash in Mesa3D Windows drivers.
2026-07-31 17:28:57 +02:00
PCSX2 BotandTy 773f96a312 [ci skip] Qt: Update Base Translation. 2026-07-30 20:43:11 -04:00
jasaavedandTy af9b61a9f7 FullscreenUI: Fix game list appearing empty after exiting and re-entering
When FullscreenUI shuts down, the cached vector of unsorted entries isn't reset. On re-entering FSUI within the same session, if the game list hasn't changed, the populate check thinks nothing needs updating and skips the rebuild, leaving the list empty.

Reset s_last_unsorted_entries on shutdown so the list rebuilds correctly on re-entering.
2026-07-30 09:36:14 -04:00
chaoticgdandTy aae9438f98 MicroVU: Unjumble EATAN coefficients 2026-07-30 09:33:41 -04:00
TellowKrinkleandlightningterror 523785d3df Qt: Remove m_pending_window_*
m_last_window_* is pretty much the same, and that way we won't forget to update one like we did in DisplaySurface::getWindowInfo
2026-07-29 21:35:02 +02:00
PCSX2 Botandlightningterror 4a92f1c472 [ci skip] Qt: Update Base Translation. 2026-07-29 02:27:59 +02:00
lightningterror 053b42d36c GameDB: Add missing tex in rt for some GITS regions. 2026-07-28 22:49:08 +02:00
Mrlinkwiiandlightningterror cf5dce2657 GameDB: add missing games and memcardFilters 2026-07-28 21:59:20 +02:00
lightningterror 645a37ad58 GS/VK: Fix crash when no device is created and vk is the selected renderer. 2026-07-28 16:50:08 +02:00
22 changed files with 484 additions and 409 deletions
+10 -1
View File
@@ -185,6 +185,7 @@ PAPX-90020:
estimateTextureRegion: 1 # Improves performance and reduces hash cache size.
halfPixelOffset: 2 # Aligns post effects.
nativeScaling: 1 # Fixes post effects.
textureInsideRT: 1 # Fixes post shuffles.
PAPX-90201:
name: "ファンタビジョン [体験版]"
name-sort: "ふぁんたびじょん [たいけんばん]"
@@ -9111,6 +9112,7 @@ SCPS-15064:
estimateTextureRegion: 1 # Improves performance and reduces hash cache size.
halfPixelOffset: 2 # Aligns post effects.
nativeScaling: 1 # Fixes post effects.
textureInsideRT: 1 # Fixes post shuffles.
patches:
A5768F53:
content: |-
@@ -32427,6 +32429,10 @@ SLKA-25255:
name-sort: "Mobile Suit Gundam Seed - Kkeunnaji Anneun Naeillo"
name-en: "Mobile Suit Gundam Seed - Never Ending Tomorrow"
region: "NTSC-K"
SLKA-25256:
name: "UEFA 챔피언스 리그 2006-2007"
name-en: "UEFA Champions League 2006-2007"
region: "NTSC-K"
SLKA-25257:
name: "풍운 막말전" # Undumped on ReDump as of 2025-08-28
name-en: "Fu-un Bakumatsu-den"
@@ -32656,7 +32662,7 @@ SLKA-25299:
SLKA-25300:
name: "디지털 데빌 사가: 아바탈 튜너 [Special Package]"
name-en: "Digital Devil Saga - Avatar Tuner [Special Package]"
region: "NTSC-J-K"
region: "NTSC-K"
compat: 5
gameFixes:
- EETimingHack
@@ -64189,6 +64195,9 @@ SLPS-73270:
name-sort: "すーぱーろぼっとたいせんZ [PlayStation2 the Best]"
name-en: "Super Robot Taisen Z [PlayStation2 the Best]"
region: "NTSC-J"
memcardFilters:
- "SLPS-73270"
- "SLPS-25887"
SLPS-73401:
name: "はじめの一歩 VICTORIOUS BOXERS CHAMPIONSHIP VERSION [PlayStation2 the Best]"
name-sort: "はじめのいっぽ VICTORIOUS BOXERS CHAMPIONSHIP VERSION [PlayStation2 the Best]"
+1 -1
View File
@@ -587,7 +587,7 @@ void main()
#define PS_FEEDBACK_LOOP_IS_NEEDED_RT (PS_TEX_IS_FB == 1 || AFAIL_NEEDS_RT || PS_FBMASK || SW_BLEND_NEEDS_RT || SW_AD_TO_HW || (PS_DATE >= 5))
#define PS_FEEDBACK_LOOP_IS_NEEDED_DEPTH (AFAIL_NEEDS_DEPTH || ZTST_NEEDS_DEPTH || AA1_NEEDS_DEPTH)
#define ZWRITE (PS_ZCLAMP || PS_ZFLOOR || SW_DEPTH || PS_FEEDBACK_LOOP_IS_NEEDED_DEPTH)
#define ZWRITE (PS_ZCLAMP || PS_ZFLOOR || PS_FEEDBACK_LOOP_IS_NEEDED_DEPTH)
#define PS_RETURN_COLOR_ROV (!PS_NO_COLOR && PS_ROV_COLOR)
#define PS_RETURN_COLOR (!PS_NO_COLOR && !PS_ROV_COLOR)
+1 -5
View File
@@ -284,7 +284,7 @@ void DisplaySurface::handleKeyInputEvent(QEvent* event)
void DisplaySurface::onResizeDebounceTimer()
{
emit windowResizedEvent(m_pending_window_width, m_pending_window_height, m_pending_window_scale);
emit windowResizedEvent(m_last_window_width, m_last_window_height, m_last_window_scale);
}
bool DisplaySurface::event(QEvent* event)
@@ -397,10 +397,6 @@ bool DisplaySurface::event(QEvent* event)
// avoid spamming resize events for paint events (sent on move on windows)
if (m_last_window_width != scaled_width || m_last_window_height != scaled_height || m_last_window_scale != dpr)
{
m_pending_window_width = scaled_width;
m_pending_window_height = scaled_height;
m_pending_window_scale = dpr;
m_last_window_width = scaled_width;
m_last_window_height = scaled_height;
m_last_window_scale = dpr;
-4
View File
@@ -70,9 +70,5 @@ private:
float m_last_window_scale = 1.0f;
QTimer* m_resize_debounce_timer = nullptr;
u32 m_pending_window_width = 0;
u32 m_pending_window_height = 0;
float m_pending_window_scale = 1.0f;
QWidget* m_container = nullptr;
};
File diff suppressed because it is too large Load Diff
+4 -4
View File
@@ -161,9 +161,9 @@ static bool OpenGSDevice(GSRendererType renderer, bool clear_state_on_fail, bool
return false;
}
if (!g_gs_device->SetGPUTimingEnabled(true))
if (GSConfig.OsdShowGPU && !g_gs_device->SetGPUTimingEnabled(true))
GSConfig.OsdShowGPU = false;
if (!g_gs_device->SetGPUPipelineStatisticsEnabled(true))
if (GSConfig.OsdShowGPUStats && !g_gs_device->SetGPUPipelineStatisticsEnabled(true))
GSConfig.OsdShowGPUStats = false;
Console.WriteLn(Color_StrongGreen, "%s Graphics Driver Info:", GSDevice::RenderAPIToString(new_api));
@@ -881,9 +881,9 @@ void GSUpdateConfig(const Pcsx2Config::GSOptions& new_config)
g_gs_renderer->PurgeTextureCache(true, false, true);
}
if (GSConfig.OsdShowGPU && !old_config.OsdShowGPU)
if (GSConfig.OsdShowGPU != old_config.OsdShowGPU)
{
if (!g_gs_device->SetGPUTimingEnabled(true))
if (!g_gs_device->SetGPUTimingEnabled(GSConfig.OsdShowGPU))
GSConfig.OsdShowGPU = false;
}
+8 -8
View File
@@ -603,7 +603,7 @@ bool GSDevice11::Create(GSVSyncMode vsync_mode, bool allow_present_throttle)
}
// 1x1 dummy texture.
const GSTexture::Usage null_usage = m_uav_texture ? GSTexture::ShaderWriteTarget : GSTexture::Feedback;
const GSTexture::Usage null_usage = m_uav_texture ? GSTexture::ShaderWriteTarget : GSTexture::FeedbackTarget;
m_null_texture = CreateSurface(null_usage, 1, 1, 1, GSTexture::Format::Color);
if (!m_null_texture)
return false;
@@ -1167,7 +1167,7 @@ void GSDevice11::DestroyTimestampQueries()
m_read_timestamp_query = 0;
m_write_timestamp_query = 0;
m_waiting_timestamp_queries = 0;
m_timestamp_query_started = 0;
m_timestamp_query_started = false;
}
void GSDevice11::PopTimestampQuery()
@@ -1286,13 +1286,13 @@ void GSDevice11::DestroyPipelineStatisticsQueries()
return;
if (m_pipeline_statistics_query_started)
m_ctx->End(m_pipeline_statistics_queries[m_write_timestamp_query].get());
m_ctx->End(m_pipeline_statistics_queries[m_write_pipeline_statistics_query].get());
m_timestamp_queries = {};
m_read_timestamp_query = 0;
m_write_timestamp_query = 0;
m_waiting_timestamp_queries = 0;
m_timestamp_query_started = 0;
m_pipeline_statistics_queries = {};
m_read_pipeline_statistics_query = 0;
m_write_pipeline_statistics_query = 0;
m_waiting_pipeline_statistics_queries = 0;
m_pipeline_statistics_query_started = false;
}
void GSDevice11::PopPipelineStatisticsQuery()
+2 -6
View File
@@ -9827,12 +9827,8 @@ bool GSRendererHW::CanUseSwPrimRender(bool no_rt, bool no_ds, bool draw_sprite_t
return false;
}
}
const u32 frame_mask = GSLocalMemory::m_psm[m_cached_ctx.FRAME.PSM].fmsk;
const u32 alpha_mask = ((m_cached_ctx.FRAME.FBMSK & frame_mask) & 0xFF000000);
const u32 rgb_mask = ((m_cached_ctx.FRAME.FBMSK & frame_mask) & 0x00FFFFFF);
const bool difficult_fbmsk = m_cached_ctx.FRAME.FBMSK != 0 && (GSLocalMemory::m_psm[m_cached_ctx.FRAME.PSM].bpp == 16 || (alpha_mask != 0 && alpha_mask != (GSLocalMemory::m_psm[m_cached_ctx.FRAME.PSM].fmsk & 0xFF000000)) ||
(rgb_mask != 0 && rgb_mask != (GSLocalMemory::m_psm[m_cached_ctx.FRAME.PSM].fmsk & 0x00FFFFFF)));
if (difficult_fbmsk || (PRIM->ABE && m_vt.m_eq.rgba == 0xffff && !m_context->ALPHA.IsOpaque(GetAlphaMinMax().min, GetAlphaMinMax().max)))
if (PRIM->ABE && m_vt.m_eq.rgba == 0xffff && !m_context->ALPHA.IsOpaque(GetAlphaMinMax().min, GetAlphaMinMax().max))
{
GSTextureCache::Target* rt = g_texture_cache->GetTargetWithSharedBits(m_cached_ctx.FRAME.Block(), m_cached_ctx.FRAME.PSM);
+1 -13
View File
@@ -545,19 +545,7 @@ bool GSRendererHWFunctions::SwPrimRender(GSRendererHW& hw, bool invalidate_tc, b
static_cast<GSSingleRasterizer*>(hw.m_sw_rasterizer.get())->Draw(data);
if (invalidate_tc)
{
GSOffset frame_offs = context->offset.fb;
if (GSLocalMemory::m_psm[context->FRAME.PSM].trbpp == 32 && context->FRAME.FBMSK)
{
if (context->FRAME.FBMSK == 0xFF000000)
frame_offs = GSRendererHW::GetInstance()->m_mem.GetOffset(context->FRAME.Block(), context->FRAME.FBW, PSMCT24);
else if (context->FRAME.FBMSK == 0x00FFFFFF)
frame_offs = GSRendererHW::GetInstance()->m_mem.GetOffset(context->FRAME.Block(), context->FRAME.FBW, PSMT8H);
}
g_texture_cache->InvalidateVideoMem(frame_offs, bbox);
}
g_texture_cache->InvalidateVideoMem(context->offset.fb, bbox);
// Jak does sw prim render, then draws to the same target, and it needs to be uploaded.
if (add_ee_transfer)
+4 -14
View File
@@ -1734,11 +1734,6 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const bool is_color, const
if (found_t && (bw != t->m_TEX0.TBW || t->m_TEX0.PSM != psm))
match = false;
// Situations where font has been uploaded to the alpha channel and they use a different buffer width, this can't currently be translated correctly.
GSLocalMemory::psm_t req_psm = GSLocalMemory::m_psm[psm];
if (!possible_shuffle && req_psm.trbpp <= 8 && req_psm.bpp == 32 && t->m_TEX0.TBW != bw && (bw * 64) != t->m_valid.z && r.w > req_psm.pgs.y)
match = false;
// Different swizzle, different width, and dirty, so probably not what we want.
// DevCon.Warning("Expected %x Got %x shuffle %d draw %d", psm, t_psm, possible_shuffle, GSState::s_n);
if (match)
@@ -7278,9 +7273,6 @@ GSTexture* GSTextureCache::LookupPaletteSource(u32 CBP, u32 CPSM, u32 CBW, GSVec
else if (GSConfig.UserHacks_GPUTargetCLUTMode == GSGPUTargetCLUTMode::InsideTarget &&
t->m_TEX0.TBP0 < CBP && t->m_end_block >= CBP)
{
// If it's more than one group of 4 blocks, it's probably going to fail, horribly.
if ((size.x > GSLocalMemory::m_psm[CPSM].bs.x || size.y > GSLocalMemory::m_psm[CPSM].bs.y) && (CBP & 0x3) != (t->m_TEX0.TBP0 & 0x3))
continue;
// Somewhere within this target, can we find it?
const GSVector4i rc(0, 0, size.x, size.y);
SurfaceOffset so = ComputeSurfaceOffset(CBP, std::max<u32>(CBW, 0), CPSM, rc, t);
@@ -7293,7 +7285,7 @@ GSTexture* GSTextureCache::LookupPaletteSource(u32 CBP, u32 CPSM, u32 CBW, GSVec
}
else
{
// Not inside this target or not aligned, skip.
// Not inside this target, skip.
continue;
}
@@ -7961,9 +7953,7 @@ void GSTextureCache::Target::Update(bool cannot_scale)
alloca(sizeof(GSDevice::MultiStretchRect) * static_cast<u32>(m_dirty.size())));
u32 ndrects = 0;
// There are cases where the alpha gets populated with font data, and the target has previously been PSMCT32 (or will be) so we need to make sure it gets filled in.
const u32 psm = (m_TEX0.PSM == PSMCT24) ? PSMCT32 : m_TEX0.PSM;
const GSOffset off(g_gs_renderer->m_mem.GetOffset(m_TEX0.TBP0, m_TEX0.TBW, psm));
const GSOffset off(g_gs_renderer->m_mem.GetOffset(m_TEX0.TBP0, m_TEX0.TBW, m_TEX0.PSM));
const u32 bpp = GSLocalMemory::m_psm[m_TEX0.PSM].bpp;
std::pair<u8, u8> alpha_minmax = {255, 0};
@@ -7986,7 +7976,7 @@ void GSTextureCache::Target::Update(bool cannot_scale)
const GSVector4i t_r(read_r - t_offset);
if (mapped)
{
if (((m_TEX0.PSM & 0xf) != PSMCT24 || m_valid_alpha_high || m_valid_alpha_low) && m_dirty[i].rgba.c.a && bpp >= 16)
if ((m_TEX0.PSM & 0xf) != PSMCT24 && m_dirty[i].rgba.c.a && bpp >= 16)
{
// TODO: Only read once in 32bit and copy to the mapped texture. Bit out of scope of this PR and not a huge impact.
const int pitch = VectorAlign(read_r.width() * sizeof(u32));
@@ -8005,7 +7995,7 @@ void GSTextureCache::Target::Update(bool cannot_scale)
const int pitch = VectorAlign(read_r.width() * sizeof(u32));
g_gs_renderer->m_mem.ReadTexture(off, read_r, s_unswizzle_buffer, pitch, TEXA);
if (((m_TEX0.PSM & 0xf) != PSMCT24 || m_valid_alpha_high || m_valid_alpha_low) &&m_dirty[i].rgba.c.a && bpp >= 16)
if ((m_TEX0.PSM & 0xf) != PSMCT24 && m_dirty[i].rgba.c.a && bpp >= 16)
{
std::pair<u8, u8> new_alpha_minmax = GSGetRGBA8AlphaMinMax(s_unswizzle_buffer, read_r.width(), read_r.height(), pitch);
alpha_minmax.first = std::min(alpha_minmax.first, new_alpha_minmax.first);
+1 -1
View File
@@ -1292,7 +1292,7 @@ bool GSDeviceOGL::SetGPUPipelineStatisticsEnabled(bool enabled)
else
DestroyPipelineStatisticsQueries();
return true;
return (enabled == m_gpu_pipeline_statistics_enabled);
}
void GSDeviceOGL::DrawPrimitive()
+17 -3
View File
@@ -1150,7 +1150,7 @@ GPUPipelineStatistics GSDeviceVK::GetAndResetAccumulatedGPUPipelineStatistics()
bool GSDeviceVK::SetGPUPipelineStatisticsEnabled(bool enabled)
{
m_gpu_pipeline_statistics_enabled = enabled && m_gpu_pipeline_statistics_supported;
return true;
return (enabled == m_gpu_pipeline_statistics_enabled);
}
void GSDeviceVK::ScanForCommandBufferCompletion()
@@ -2254,8 +2254,11 @@ void GSDeviceVK::Destroy()
m_swap_chain.reset();
DestroySpinResources();
DestroyResources();
if (m_device != VK_NULL_HANDLE)
{
DestroySpinResources();
DestroyResources();
}
VKShaderCache::Destroy();
@@ -5415,6 +5418,17 @@ void GSDeviceVK::PSSetROVs(GSTexture* rt, GSTexture* ds, bool write_rt, bool wri
PSSetShaderResource(TFX_TEXTURE_DEPTH_ROV, nullptr, false);
}
if (IsDeviceNVIDIA() && InRenderPass())
{
// Nvidia doesn't like switching ROV targets mid-render pass, doing so causes flickering or missing geometry.
// End the render pass to avoid such issues.
if (vkRt != oldVkRt || vkDs != oldVkDs)
{
GL_INS("VK: Ending render pass due to UAV switch");
EndRenderPass();
}
}
if (GSConfig.HWROVBarriersVK)
{
// This is to fix issues with some systems that seem to require barriers even with FSI.
+4 -16
View File
@@ -170,24 +170,12 @@ void FullscreenUI::ApplyLayoutSettings(const SettingsInterface* bsi)
return InputLayout::Playstation;
if (mode == "nintendo")
return InputLayout::Nintendo;
if (mode == "generic")
return InputLayout::Generic;
return InputLayout::Unknown;
};
switch (parse_glyph_layout(glyph_mode))
{
case InputLayout::Xbox:
InputManager::SetGamepadIconPreference(InputLayout::Xbox);
break;
case InputLayout::Playstation:
InputManager::SetGamepadIconPreference(InputLayout::Playstation);
break;
case InputLayout::Nintendo:
InputManager::SetGamepadIconPreference(InputLayout::Nintendo);
break;
default:
InputManager::SetGamepadIconPreference(InputLayout::Unknown);
break;
}
InputManager::SetGamepadIconPreference(parse_glyph_layout(glyph_mode));
const InputLayout layout = ImGuiFullscreen::GetGamepadLayout();
@@ -557,6 +545,7 @@ void FullscreenUI::Shutdown(bool clear_state)
CloseCoverDownloaderWindow();
s_cover_image_map.clear();
s_game_list_sorted_entries = {};
s_last_unsorted_entries = {};
s_game_list_directories_cache = {};
s_game_cheat_unlabelled_count = 0;
s_enabled_game_cheat_cache = {};
@@ -2467,7 +2456,6 @@ void FullscreenUI::PopulateGameListEntryList()
static int s_last_sort = -1;
static bool s_last_reverse = false;
static bool s_last_prefer_eng = false;
static std::vector<const GameList::Entry*> s_last_unsorted_entries;
// Sort can be expensive, try to avoid when possible
const u32 count = GameList::GetEntryCount();
+3
View File
@@ -369,6 +369,9 @@ namespace FullscreenUI
inline std::vector<const GameList::Entry*> s_game_list_sorted_entries;
inline GameListView s_game_list_view = GameListView::Grid;
// Cached list of unsorted game list entries; used to detect changes and re-sort when needed
inline std::vector<const GameList::Entry*> s_last_unsorted_entries;
//////////////////////////////////////////////////////////////////////////
// Background
//////////////////////////////////////////////////////////////////////////
+2
View File
@@ -2296,12 +2296,14 @@ void FullscreenUI::DrawInterfaceSettingsPage()
FSUI_NSTR("Xbox"),
FSUI_NSTR("PlayStation"),
FSUI_NSTR("Nintendo"),
FSUI_NSTR("Generic"),
};
static constexpr const char* glyph_values[] = {
"auto",
"xbox",
"playstation",
"nintendo",
"generic",
};
size_t glyph_index = std::size(glyph_values);
for (size_t i = 0; i < std::size(glyph_values); i++)
+9 -20
View File
@@ -971,22 +971,10 @@ InputLayout ImGuiFullscreen::GetGamepadLayout()
static InputLayout GetEffectiveGlyphLayout()
{
const InputLayout preferred_layout = InputManager::GetGamepadIconPreference();
if (preferred_layout == InputLayout::Xbox || preferred_layout == InputLayout::Playstation || preferred_layout == InputLayout::Nintendo)
if (preferred_layout != InputLayout::Unknown)
return preferred_layout;
const InputLayout detected_layout = ImGuiFullscreen::GetGamepadLayout();
switch (detected_layout)
{
case InputLayout::Playstation:
return InputLayout::Playstation;
case InputLayout::Xbox:
return InputLayout::Xbox;
case InputLayout::Nintendo:
return InputLayout::Nintendo;
case InputLayout::Unknown:
default:
return InputLayout::Playstation;
}
return ImGuiFullscreen::GetGamepadLayout();
}
ImGuiFullscreen::GamepadGlyphs ImGuiFullscreen::GetGamepadGlyphs()
@@ -994,16 +982,17 @@ ImGuiFullscreen::GamepadGlyphs ImGuiFullscreen::GetGamepadGlyphs()
const InputLayout layout = GetEffectiveGlyphLayout();
const bool xbox = (layout == InputLayout::Xbox);
const bool nintendo = (layout == InputLayout::Nintendo);
const bool unknown = (layout == InputLayout::Unknown || layout == InputLayout::Generic);
return {
nintendo ? ICON_PF_BUTTON_B : (xbox ? ICON_PF_BUTTON_A : ICON_PF_BUTTON_CROSS),
nintendo ? ICON_PF_BUTTON_A : (xbox ? ICON_PF_BUTTON_B : ICON_PF_BUTTON_CIRCLE),
nintendo ? ICON_PF_BUTTON_Y : (xbox ? ICON_PF_BUTTON_X : ICON_PF_BUTTON_SQUARE),
nintendo ? ICON_PF_BUTTON_X : (xbox ? ICON_PF_BUTTON_Y : ICON_PF_BUTTON_TRIANGLE),
unknown ? ICON_PF_BUTTON_DOWN_A : (nintendo ? ICON_PF_BUTTON_B : (xbox ? ICON_PF_BUTTON_A : ICON_PF_BUTTON_CROSS)),
unknown ? ICON_PF_BUTTON_RIGHT_B : (nintendo ? ICON_PF_BUTTON_A : (xbox ? ICON_PF_BUTTON_B : ICON_PF_BUTTON_CIRCLE)),
unknown ? ICON_PF_BUTTON_LEFT_X : (nintendo ? ICON_PF_BUTTON_Y : (xbox ? ICON_PF_BUTTON_X : ICON_PF_BUTTON_SQUARE)),
unknown ? ICON_PF_BUTTON_UP_Y : (nintendo ? ICON_PF_BUTTON_X : (xbox ? ICON_PF_BUTTON_Y : ICON_PF_BUTTON_TRIANGLE)),
xbox ? ICON_PF_XBOX_DPAD : ICON_PF_DPAD,
xbox ? ICON_PF_XBOX_DPAD_LEFT_RIGHT : ICON_PF_DPAD_LEFT_RIGHT,
xbox ? ICON_PF_XBOX_DPAD_UP_DOWN : ICON_PF_DPAD_UP_DOWN,
nintendo ? ICON_PF_MINUS : (xbox ? ICON_PF_SHARE_CAPTURE : ICON_PF_SELECT_SHARE),
nintendo ? ICON_PF_PLUS : (xbox ? ICON_PF_BURGER_MENU : ICON_PF_START),
nintendo ? ICON_PF_MINUS : ((xbox || unknown) ? ICON_PF_SHARE_CAPTURE : ICON_PF_SELECT_SHARE),
nintendo ? ICON_PF_PLUS : ((xbox || unknown) ? ICON_PF_BURGER_MENU : ICON_PF_START),
};
}
+51 -35
View File
@@ -108,7 +108,7 @@ namespace InputManager
static float ApplySingleBindingScale(float sensitivity, float deadzone, float value);
static void AddHotkeyBindings(SettingsInterface& si, bool is_profile);
static void AddPadBindings(SettingsInterface& si, u32 pad, bool is_profile);
static void AddPadBindings(SettingsInterface& si, u32 pad, bool is_profile, SettingsInterface* nav_si);
static void AddUSBBindings(SettingsInterface& si, u32 port, bool is_profile);
static void UpdateContinuedVibration();
static void GenerateRelativeMouseEvents();
@@ -874,7 +874,7 @@ void InputManager::AddHotkeyBindings(SettingsInterface& si, bool is_profile)
}
}
void InputManager::AddPadBindings(SettingsInterface& si, u32 pad_index, bool is_profile)
void InputManager::AddPadBindings(SettingsInterface& si, u32 pad_index, bool is_profile, SettingsInterface* nav_si)
{
const Pad::ControllerType type = EmuConfig.Pad.Ports[pad_index].Type;
@@ -913,30 +913,30 @@ void InputManager::AddPadBindings(SettingsInterface& si, u32 pad_index, bool is_
Pad::SetControllerState(pad_index, bind_index, ApplySingleBindingScale(sensitivity, deadzone, value));
}},
bi.bind_type, si, section.c_str(), bi.name, is_profile);
}
// Build reverse maps for controller navigation; user bindings take priority over static defaults.
if (bi.generic_mapping != GenericInputBinding::Unknown)
// So per-game bindings never affect FullscreenUI navigation.
if (nav_si && bi.generic_mapping != GenericInputBinding::Unknown)
{
for (const std::string& binding_str : nav_si->GetStringList(section.c_str(), bi.name))
{
for (const std::string& binding_str : bindings)
{
InputBindingKey bkey;
InputSource* bsrc;
if (!ParseBindingAndGetSource(binding_str, &bkey, &bsrc))
continue;
InputBindingKey bkey;
InputSource* bsrc;
if (!ParseBindingAndGetSource(binding_str, &bkey, &bsrc))
continue;
if (bkey.source_subtype == InputSubclass::ControllerButton)
{
s_controller_button_generic_map.emplace(bkey.MaskDirection(), bi.generic_mapping);
}
else if (bkey.source_subtype == InputSubclass::ControllerAxis)
{
auto& entry = s_controller_axis_generic_map[bkey.MaskDirection()];
// Negate modifier = negative half of axis (e.g. "-Axis0" → LeftStickLeft)
if (bkey.modifier == InputModifier::Negate)
entry[0] = bi.generic_mapping;
else
entry[1] = bi.generic_mapping;
}
if (bkey.source_subtype == InputSubclass::ControllerButton)
{
s_controller_button_generic_map.emplace(bkey.MaskDirection(), bi.generic_mapping);
}
else if (bkey.source_subtype == InputSubclass::ControllerAxis)
{
auto& entry = s_controller_axis_generic_map[bkey.MaskDirection()];
// Negate modifier = negative half of axis (e.g. "-Axis0" → LeftStickLeft)
if (bkey.modifier == InputModifier::Negate)
entry[0] = bi.generic_mapping;
else
entry[1] = bi.generic_mapping;
}
}
}
@@ -1312,27 +1312,42 @@ bool InputManager::PreprocessEvent(InputBindingKey key, float value, GenericInpu
}
else if (key.source_subtype == InputSubclass::ControllerButton)
{
// User binding takes priority; fall back to the generic_key passed by the source (static table).
const auto it = s_controller_button_generic_map.find(key.MaskDirection());
const GenericInputBinding resolved = (it != s_controller_button_generic_map.end()) ? it->second : generic_key;
// Static table takes priority; falls back to the Shared/global map only if the source has none (e.g. DInput).
GenericInputBinding resolved = generic_key;
if (resolved == GenericInputBinding::Unknown)
{
const auto it = s_controller_button_generic_map.find(key.MaskDirection());
if (it != s_controller_button_generic_map.end())
resolved = it->second;
}
if (resolved != GenericInputBinding::Unknown)
{
const u32 controller_id = (static_cast<u32>(key.source_type) << 8) | key.source_index;
const InputLayout layout = s_input_sources[static_cast<u32>(InputSourceType::SDL)]->GetControllerLayout(key.source_index);
const InputLayout layout = s_input_sources[static_cast<u32>(key.source_type)]->GetControllerLayout(key.source_index);
if (ImGuiManager::ProcessGenericInputEvent(resolved, layout, value, controller_id) && value != 0.0f)
return true;
}
}
else if (key.source_subtype == InputSubclass::ControllerAxis)
{
// User binding takes priority; fall back to the neg/pos keys passed by the source (static table).
const auto it = s_controller_axis_generic_map.find(key.MaskDirection());
const GenericInputBinding neg = (it != s_controller_axis_generic_map.end()) ? it->second[0] : axis_neg_key;
const GenericInputBinding pos = (it != s_controller_axis_generic_map.end()) ? it->second[1] : axis_pos_key;
// Same priority as above; map only fills in directions the source couldn't resolve.
GenericInputBinding neg = axis_neg_key;
GenericInputBinding pos = axis_pos_key;
if (neg == GenericInputBinding::Unknown || pos == GenericInputBinding::Unknown)
{
const auto it = s_controller_axis_generic_map.find(key.MaskDirection());
if (it != s_controller_axis_generic_map.end())
{
if (neg == GenericInputBinding::Unknown)
neg = it->second[0];
if (pos == GenericInputBinding::Unknown)
pos = it->second[1];
}
}
if (neg != GenericInputBinding::Unknown || pos != GenericInputBinding::Unknown)
{
const u32 controller_id = (static_cast<u32>(key.source_type) << 8) | key.source_index;
const InputLayout layout = s_input_sources[static_cast<u32>(InputSourceType::SDL)]->GetControllerLayout(key.source_index);
const InputLayout layout = s_input_sources[static_cast<u32>(key.source_type)]->GetControllerLayout(key.source_index);
ImGuiManager::ProcessGenericAxisEvent(neg, pos, layout, value, controller_id);
}
}
@@ -1619,10 +1634,11 @@ void InputManager::ReloadBindings(SettingsInterface& si, SettingsInterface& bind
// Hotkeys use the base configuration, except if the custom hotkeys option is enabled.
AddHotkeyBindings(hotkey_binding_si, is_hotkey_profile);
// If there's an input profile, we load pad bindings from it alone, rather than
// falling back to the base configuration.
// nav_si is always the base config, so per-game profiles can't affect UI navigation.
const LayeredSettingsInterface& lsi = static_cast<LayeredSettingsInterface&>(si);
SettingsInterface* base_si = lsi.GetLayer(LayeredSettingsInterface::LAYER_BASE);
for (u32 pad = 0; pad < Pad::NUM_CONTROLLER_PORTS; pad++)
AddPadBindings(binding_si, pad, is_binding_profile);
AddPadBindings(binding_si, pad, is_binding_profile, base_si);
constexpr float ui_ctrl_range = 100.0f;
constexpr float pointer_sensitivity = 0.05f;
+2 -1
View File
@@ -52,7 +52,8 @@ enum class InputLayout : u8
Unknown,
Xbox,
Playstation,
Nintendo
Nintendo,
Generic
};
enum class InputModifier : u32
+105 -18
View File
@@ -225,6 +225,38 @@ static constexpr const char* s_sdl_button_names[] = {
"Misc 5", // SDL_GAMEPAD_BUTTON_MISC5
"Misc 6", // SDL_GAMEPAD_BUTTON_MISC6
};
static constexpr const char* s_sdl_button_standard_names[] = {
"A", // SDL_GAMEPAD_BUTTON_SOUTH
"B", // SDL_GAMEPAD_BUTTON_EAST
"X", // SDL_GAMEPAD_BUTTON_WEST
"Y", // SDL_GAMEPAD_BUTTON_NORTH
};
static constexpr const char* s_sdl_button_xbox360_names[] = {
nullptr, // SDL_GAMEPAD_BUTTON_SOUTH
nullptr, // SDL_GAMEPAD_BUTTON_EAST
nullptr, // SDL_GAMEPAD_BUTTON_WEST
nullptr, // SDL_GAMEPAD_BUTTON_NORTH
nullptr, // SDL_GAMEPAD_BUTTON_BACK
nullptr, // SDL_GAMEPAD_BUTTON_GUIDE
nullptr, // SDL_GAMEPAD_BUTTON_START
nullptr, // SDL_GAMEPAD_BUTTON_LEFT_STICK
nullptr, // SDL_GAMEPAD_BUTTON_RIGHT_STICK
"LB", // SDL_GAMEPAD_BUTTON_LEFT_SHOULDER
"RB", // SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER
};
static constexpr const char* s_sdl_button_xboxone_names[] = {
nullptr, // SDL_GAMEPAD_BUTTON_SOUTH
nullptr, // SDL_GAMEPAD_BUTTON_EAST
nullptr, // SDL_GAMEPAD_BUTTON_WEST
nullptr, // SDL_GAMEPAD_BUTTON_NORTH
"View", // SDL_GAMEPAD_BUTTON_BACK
"Xbox", // SDL_GAMEPAD_BUTTON_GUIDE
"Menu", // SDL_GAMEPAD_BUTTON_START
nullptr, // SDL_GAMEPAD_BUTTON_LEFT_STICK
nullptr, // SDL_GAMEPAD_BUTTON_RIGHT_STICK
"LB", // SDL_GAMEPAD_BUTTON_LEFT_SHOULDER
"RB", // SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER
};
static constexpr const char* s_sdl_button_ps3_names[] = {
"Cross", // SDL_GAMEPAD_BUTTON_SOUTH
"Circle", // SDL_GAMEPAD_BUTTON_EAST
@@ -269,26 +301,39 @@ static constexpr const char* s_sdl_button_ps5_names[] = {
nullptr, // SDL_GAMEPAD_BUTTON_DPAD_RIGHT
"Mute", // SDL_GAMEPAD_BUTTON_MISC1
};
static constexpr const char* s_sdl_button_nintendo_names[] = {
"B", // SDL_GAMEPAD_BUTTON_SOUTH
"A", // SDL_GAMEPAD_BUTTON_EAST
"Y", // SDL_GAMEPAD_BUTTON_WEST
"X", // SDL_GAMEPAD_BUTTON_NORTH
"Minus", // SDL_GAMEPAD_BUTTON_BACK
"Home", // SDL_GAMEPAD_BUTTON_GUIDE
"Plus", // SDL_GAMEPAD_BUTTON_START
"Left Stick", // SDL_GAMEPAD_BUTTON_LEFT_STICK
"Right Stick", // SDL_GAMEPAD_BUTTON_RIGHT_STICK
"L", // SDL_GAMEPAD_BUTTON_LEFT_SHOULDER
"R", // SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER
};
static constexpr const char* const* s_sdl_button_names_list[] = {
s_sdl_button_names, // SDL_GAMEPAD_TYPE_UNKNOWN
s_sdl_button_names, // SDL_GAMEPAD_TYPE_STANDARD
s_sdl_button_names, // SDL_GAMEPAD_TYPE_XBOX360
s_sdl_button_names, // SDL_GAMEPAD_TYPE_XBOXONE
s_sdl_button_standard_names, // SDL_GAMEPAD_TYPE_STANDARD
s_sdl_button_xbox360_names, // SDL_GAMEPAD_TYPE_XBOX360
s_sdl_button_xboxone_names, // SDL_GAMEPAD_TYPE_XBOXONE
s_sdl_button_ps3_names, // SDL_GAMEPAD_TYPE_PS3
s_sdl_button_ps4_names, // SDL_GAMEPAD_TYPE_PS4
s_sdl_button_ps5_names, // SDL_GAMEPAD_TYPE_PS5
// Switch
s_sdl_button_nintendo_names, // SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_PRO
};
static constexpr size_t s_sdl_button_namesize_list[] = {
std::size(s_sdl_button_names), // SDL_GAMEPAD_TYPE_UNKNOWN
std::size(s_sdl_button_names), // SDL_GAMEPAD_TYPE_STANDARD
std::size(s_sdl_button_names), // SDL_GAMEPAD_TYPE_XBOX360
std::size(s_sdl_button_names), // SDL_GAMEPAD_TYPE_XBOXONE
std::size(s_sdl_button_standard_names), // SDL_GAMEPAD_TYPE_STANDARD
std::size(s_sdl_button_xbox360_names), // SDL_GAMEPAD_TYPE_XBOX360
std::size(s_sdl_button_xboxone_names), // SDL_GAMEPAD_TYPE_XBOXONE
std::size(s_sdl_button_ps3_names), // SDL_GAMEPAD_TYPE_PS3
std::size(s_sdl_button_ps4_names), // SDL_GAMEPAD_TYPE_PS4
std::size(s_sdl_button_ps5_names), // SDL_GAMEPAD_TYPE_PS5
// Switch
std::size(s_sdl_button_nintendo_names), // SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_PRO
};
static constexpr const char* s_sdl_face_button_icons[] = {
@@ -308,12 +353,52 @@ static constexpr const char* s_sdl_button_icons[] = {
ICON_PF_BUTTON_LEFT_X, // SDL_GAMEPAD_BUTTON_WEST
ICON_PF_BUTTON_UP_Y, // SDL_GAMEPAD_BUTTON_NORTH
ICON_PF_SHARE_CAPTURE, // SDL_GAMEPAD_BUTTON_BACK
ICON_PF_XBOX, // SDL_GAMEPAD_BUTTON_GUIDE
ICON_PF_HOME_MENU, // SDL_GAMEPAD_BUTTON_GUIDE
ICON_PF_BURGER_MENU, // SDL_GAMEPAD_BUTTON_START
ICON_PF_LEFT_ANALOG_CLICK, // SDL_GAMEPAD_BUTTON_LEFT_STICK
ICON_PF_RIGHT_ANALOG_CLICK, // SDL_GAMEPAD_BUTTON_RIGHT_STICK
ICON_PF_LEFT_SHOULDER_LB, // SDL_GAMEPAD_BUTTON_LEFT_SHOULDER
ICON_PF_RIGHT_SHOULDER_RB, // SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER
ICON_PF_DPAD_UP, // SDL_GAMEPAD_BUTTON_DPAD_UP
ICON_PF_DPAD_DOWN, // SDL_GAMEPAD_BUTTON_DPAD_DOWN
ICON_PF_DPAD_LEFT, // SDL_GAMEPAD_BUTTON_DPAD_LEFT
ICON_PF_DPAD_RIGHT, // SDL_GAMEPAD_BUTTON_DPAD_RIGHT
};
static constexpr const char* s_sdl_button_standard_icons[] = {
ICON_PF_BUTTON_A, // SDL_GAMEPAD_BUTTON_SOUTH
ICON_PF_BUTTON_B, // SDL_GAMEPAD_BUTTON_EAST
ICON_PF_BUTTON_X, // SDL_GAMEPAD_BUTTON_WEST
ICON_PF_BUTTON_Y, // SDL_GAMEPAD_BUTTON_NORTH
};
static constexpr const char* s_sdl_button_xbox360_icons[] = {
ICON_PF_BUTTON_A, // SDL_GAMEPAD_BUTTON_SOUTH
ICON_PF_BUTTON_B, // SDL_GAMEPAD_BUTTON_EAST
ICON_PF_BUTTON_X, // SDL_GAMEPAD_BUTTON_WEST
ICON_PF_BUTTON_Y, // SDL_GAMEPAD_BUTTON_NORTH
ICON_PF_JOYCON_DPAD_LEFT, // SDL_GAMEPAD_BUTTON_BACK
ICON_PF_XBOX, // SDL_GAMEPAD_BUTTON_GUIDE
ICON_PF_JOYCON_DPAD_RIGHT, // SDL_GAMEPAD_BUTTON_START
nullptr, // SDL_GAMEPAD_BUTTON_LEFT_STICK
nullptr, // SDL_GAMEPAD_BUTTON_RIGHT_STICK
nullptr, // SDL_GAMEPAD_BUTTON_LEFT_SHOULDER
nullptr, // SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER
ICON_PF_XBOX_DPAD_UP, // SDL_GAMEPAD_BUTTON_DPAD_UP
ICON_PF_XBOX_DPAD_DOWN, // SDL_GAMEPAD_BUTTON_DPAD_DOWN
ICON_PF_XBOX_DPAD_LEFT, // SDL_GAMEPAD_BUTTON_DPAD_LEFT
ICON_PF_XBOX_DPAD_RIGHT, // SDL_GAMEPAD_BUTTON_DPAD_RIGHT
};
static constexpr const char* s_sdl_button_xboxone_icons[] = {
ICON_PF_BUTTON_A, // SDL_GAMEPAD_BUTTON_SOUTH
ICON_PF_BUTTON_B, // SDL_GAMEPAD_BUTTON_EAST
ICON_PF_BUTTON_X, // SDL_GAMEPAD_BUTTON_WEST
ICON_PF_BUTTON_Y, // SDL_GAMEPAD_BUTTON_NORTH
nullptr, // SDL_GAMEPAD_BUTTON_BACK
ICON_PF_XBOX, // SDL_GAMEPAD_BUTTON_GUIDE
nullptr, // SDL_GAMEPAD_BUTTON_START
nullptr, // SDL_GAMEPAD_BUTTON_LEFT_STICK
nullptr, // SDL_GAMEPAD_BUTTON_RIGHT_STICK
nullptr, // SDL_GAMEPAD_BUTTON_LEFT_SHOULDER
nullptr, // SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER
ICON_PF_XBOX_DPAD_UP, // SDL_GAMEPAD_BUTTON_DPAD_UP
ICON_PF_XBOX_DPAD_DOWN, // SDL_GAMEPAD_BUTTON_DPAD_DOWN
ICON_PF_XBOX_DPAD_LEFT, // SDL_GAMEPAD_BUTTON_DPAD_LEFT
@@ -402,9 +487,9 @@ static constexpr const char* s_sdl_button_nintendo_icons[] = {
};
static constexpr const char* const* s_sdl_button_icons_list[] = {
s_sdl_button_icons, // SDL_GAMEPAD_TYPE_UNKNOWN
s_sdl_button_icons, // SDL_GAMEPAD_TYPE_STANDARD
s_sdl_button_icons, // SDL_GAMEPAD_TYPE_XBOX360
s_sdl_button_icons, // SDL_GAMEPAD_TYPE_XBOXONE
s_sdl_button_standard_icons, // SDL_GAMEPAD_TYPE_STANDARD
s_sdl_button_xbox360_icons, // SDL_GAMEPAD_TYPE_XBOX360
s_sdl_button_xboxone_icons, // SDL_GAMEPAD_TYPE_XBOXONE
s_sdl_button_ps3_icons, // SDL_GAMEPAD_TYPE_PS3
s_sdl_button_ps4_icons, // SDL_GAMEPAD_TYPE_PS4
s_sdl_button_ps5_icons, // SDL_GAMEPAD_TYPE_PS5
@@ -412,9 +497,9 @@ static constexpr const char* const* s_sdl_button_icons_list[] = {
};
static constexpr size_t s_sdl_button_iconsize_list[] = {
std::size(s_sdl_button_icons), // SDL_GAMEPAD_TYPE_UNKNOWN
std::size(s_sdl_button_icons), // SDL_GAMEPAD_TYPE_STANDARD
std::size(s_sdl_button_icons), // SDL_GAMEPAD_TYPE_XBOX360
std::size(s_sdl_button_icons), // SDL_GAMEPAD_TYPE_XBOXONE
std::size(s_sdl_button_standard_icons), // SDL_GAMEPAD_TYPE_STANDARD
std::size(s_sdl_button_xbox360_icons), // SDL_GAMEPAD_TYPE_XBOX360
std::size(s_sdl_button_xboxone_icons), // SDL_GAMEPAD_TYPE_XBOXONE
std::size(s_sdl_button_ps3_icons), // SDL_GAMEPAD_TYPE_PS3
std::size(s_sdl_button_ps4_icons), // SDL_GAMEPAD_TYPE_PS4
std::size(s_sdl_button_ps5_icons), // SDL_GAMEPAD_TYPE_PS5
@@ -1034,7 +1119,7 @@ TinyString SDLInputSource::ConvertKeyToString(InputBindingKey key, bool display,
if (it != m_controllers.end())
type = SDL_GetRealGamepadType(it->gamepad);
if (type > SDL_GAMEPAD_TYPE_STANDARD && type < std::size(s_sdl_button_names_list) &&
if (type > SDL_GAMEPAD_TYPE_UNKNOWN && type < std::size(s_sdl_button_names_list) &&
key.data < s_sdl_button_namesize_list[type] && s_sdl_button_names_list[type][key.data] != nullptr)
{
ret.format("SDL-{} {}", static_cast<u32>(key.source_index), s_sdl_button_names_list[type][key.data]);
@@ -1111,6 +1196,8 @@ TinyString SDLInputSource::ConvertKeyToIcon(InputBindingKey key)
type = SDL_GAMEPAD_TYPE_PS5;
else if (glyph_preference == InputLayout::Nintendo)
type = SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_PRO;
else if (glyph_preference == InputLayout::Generic)
type = SDL_GAMEPAD_TYPE_UNKNOWN;
if (key.source_subtype == InputSubclass::ControllerAxis)
{
@@ -1141,7 +1228,7 @@ TinyString SDLInputSource::ConvertKeyToIcon(InputBindingKey key)
}
else if (key.source_subtype == InputSubclass::ControllerButton)
{
if (type > SDL_GAMEPAD_TYPE_STANDARD && type < std::size(s_sdl_button_icons_list) &&
if (type > SDL_GAMEPAD_TYPE_UNKNOWN && type < std::size(s_sdl_button_icons_list) &&
key.data < s_sdl_button_iconsize_list[type] && s_sdl_button_icons_list[type][key.data] != nullptr)
{
ret.format("SDL-{} {}", static_cast<u32>(key.source_index), s_sdl_button_icons_list[type][key.data]);
@@ -1149,7 +1236,7 @@ TinyString SDLInputSource::ConvertKeyToIcon(InputBindingKey key)
else if (key.data < 4)
{
SDL_GamepadButtonLabel label = SDL_GAMEPAD_BUTTON_LABEL_UNKNOWN;
if (it != m_controllers.end() && it->gamepad)
if (glyph_preference != InputLayout::Generic && it != m_controllers.end() && it->gamepad)
label = SDL_GetGamepadButtonLabel(it->gamepad, static_cast<SDL_GamepadButton>(key.data));
if (label > SDL_GAMEPAD_BUTTON_LABEL_UNKNOWN && label < std::size(s_sdl_face_button_icons))
+2 -2
View File
@@ -79,7 +79,7 @@ static const char* s_button_names[XInputSource::NUM_BUTTONS] = {
"B", // XINPUT_GAMEPAD_B
"X", // XINPUT_GAMEPAD_X
"Y", // XINPUT_GAMEPAD_Y
"Guide", // XINPUT_GAMEPAD_GUIDE
"Xbox", // XINPUT_GAMEPAD_GUIDE
};
static const u16 s_button_masks[XInputSource::NUM_BUTTONS] = {
@@ -387,7 +387,7 @@ TinyString XInputSource::ConvertKeyToIcon(InputBindingKey key)
{
TinyString ret;
if (key.source_type == InputSourceType::SDL)
if (key.source_type == InputSourceType::XInput)
{
if (key.source_subtype == InputSubclass::ControllerAxis)
{
+1 -1
View File
@@ -3,4 +3,4 @@
/// Version number for GS and other shaders. Increment whenever any of the contents of the
/// shaders change, to invalidate the cache.
static constexpr u32 SHADER_CACHE_VERSION = 108; // Last changed in PR 14688
static constexpr u32 SHADER_CACHE_VERSION = 109; // Last changed in PR 14795
+4 -4
View File
@@ -25,10 +25,10 @@ struct mVU_Globals
u32 one [4] = __four(0x3f800000);
u32 Pi4 [4] = __four(0x3f490fdb);
u32 T1 [4] = __four(0x3f7ffff5);
u32 T5 [4] = __four(0xbeaaa61c);
u32 T2 [4] = __four(0x3e4c40a6);
u32 T3 [4] = __four(0xbe0e6c63);
u32 T4 [4] = __four(0x3dc577df);
u32 T2 [4] = __four(0xbeaaa61c);
u32 T3 [4] = __four(0x3e4c40a6);
u32 T4 [4] = __four(0xbe0e6c63);
u32 T5 [4] = __four(0x3dc577df);
u32 T6 [4] = __four(0xbd6501c4);
u32 T7 [4] = __four(0x3cb31652);
u32 T8 [4] = __four(0xbb84d7e7);