Compare commits

..
22 changed files with 409 additions and 484 deletions
+1 -10
View File
@@ -185,7 +185,6 @@ 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: "ふぁんたびじょん [たいけんばん]"
@@ -9112,7 +9111,6 @@ 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: |-
@@ -32429,10 +32427,6 @@ 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"
@@ -32662,7 +32656,7 @@ SLKA-25299:
SLKA-25300:
name: "디지털 데빌 사가: 아바탈 튜너 [Special Package]"
name-en: "Digital Devil Saga - Avatar Tuner [Special Package]"
region: "NTSC-K"
region: "NTSC-J-K"
compat: 5
gameFixes:
- EETimingHack
@@ -64195,9 +64189,6 @@ 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 || PS_FEEDBACK_LOOP_IS_NEEDED_DEPTH)
#define ZWRITE (PS_ZCLAMP || PS_ZFLOOR || SW_DEPTH || 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)
+5 -1
View File
@@ -284,7 +284,7 @@ void DisplaySurface::handleKeyInputEvent(QEvent* event)
void DisplaySurface::onResizeDebounceTimer()
{
emit windowResizedEvent(m_last_window_width, m_last_window_height, m_last_window_scale);
emit windowResizedEvent(m_pending_window_width, m_pending_window_height, m_pending_window_scale);
}
bool DisplaySurface::event(QEvent* event)
@@ -397,6 +397,10 @@ 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,5 +70,9 @@ 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 (GSConfig.OsdShowGPU && !g_gs_device->SetGPUTimingEnabled(true))
if (!g_gs_device->SetGPUTimingEnabled(true))
GSConfig.OsdShowGPU = false;
if (GSConfig.OsdShowGPUStats && !g_gs_device->SetGPUPipelineStatisticsEnabled(true))
if (!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(GSConfig.OsdShowGPU))
if (!g_gs_device->SetGPUTimingEnabled(true))
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::FeedbackTarget;
const GSTexture::Usage null_usage = m_uav_texture ? GSTexture::ShaderWriteTarget : GSTexture::Feedback;
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 = false;
m_timestamp_query_started = 0;
}
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_pipeline_statistics_query].get());
m_ctx->End(m_pipeline_statistics_queries[m_write_timestamp_query].get());
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;
m_timestamp_queries = {};
m_read_timestamp_query = 0;
m_write_timestamp_query = 0;
m_waiting_timestamp_queries = 0;
m_timestamp_query_started = 0;
}
void GSDevice11::PopPipelineStatisticsQuery()
+6 -2
View File
@@ -9827,8 +9827,12 @@ bool GSRendererHW::CanUseSwPrimRender(bool no_rt, bool no_ds, bool draw_sprite_t
return false;
}
}
if (PRIM->ABE && m_vt.m_eq.rgba == 0xffff && !m_context->ALPHA.IsOpaque(GetAlphaMinMax().min, GetAlphaMinMax().max))
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)))
{
GSTextureCache::Target* rt = g_texture_cache->GetTargetWithSharedBits(m_cached_ctx.FRAME.Block(), m_cached_ctx.FRAME.PSM);
+13 -1
View File
@@ -545,7 +545,19 @@ bool GSRendererHWFunctions::SwPrimRender(GSRendererHW& hw, bool invalidate_tc, b
static_cast<GSSingleRasterizer*>(hw.m_sw_rasterizer.get())->Draw(data);
if (invalidate_tc)
g_texture_cache->InvalidateVideoMem(context->offset.fb, bbox);
{
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);
}
// Jak does sw prim render, then draws to the same target, and it needs to be uploaded.
if (add_ee_transfer)
+14 -4
View File
@@ -1734,6 +1734,11 @@ 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)
@@ -7273,6 +7278,9 @@ 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);
@@ -7285,7 +7293,7 @@ GSTexture* GSTextureCache::LookupPaletteSource(u32 CBP, u32 CPSM, u32 CBW, GSVec
}
else
{
// Not inside this target, skip.
// Not inside this target or not aligned, skip.
continue;
}
@@ -7953,7 +7961,9 @@ void GSTextureCache::Target::Update(bool cannot_scale)
alloca(sizeof(GSDevice::MultiStretchRect) * static_cast<u32>(m_dirty.size())));
u32 ndrects = 0;
const GSOffset off(g_gs_renderer->m_mem.GetOffset(m_TEX0.TBP0, m_TEX0.TBW, m_TEX0.PSM));
// 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 u32 bpp = GSLocalMemory::m_psm[m_TEX0.PSM].bpp;
std::pair<u8, u8> alpha_minmax = {255, 0};
@@ -7976,7 +7986,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_dirty[i].rgba.c.a && bpp >= 16)
if (((m_TEX0.PSM & 0xf) != PSMCT24 || m_valid_alpha_high || m_valid_alpha_low) && 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));
@@ -7995,7 +8005,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_dirty[i].rgba.c.a && bpp >= 16)
if (((m_TEX0.PSM & 0xf) != PSMCT24 || m_valid_alpha_high || m_valid_alpha_low) &&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 (enabled == m_gpu_pipeline_statistics_enabled);
return true;
}
void GSDeviceOGL::DrawPrimitive()
+3 -17
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 (enabled == m_gpu_pipeline_statistics_enabled);
return true;
}
void GSDeviceVK::ScanForCommandBufferCompletion()
@@ -2254,11 +2254,8 @@ void GSDeviceVK::Destroy()
m_swap_chain.reset();
if (m_device != VK_NULL_HANDLE)
{
DestroySpinResources();
DestroyResources();
}
DestroySpinResources();
DestroyResources();
VKShaderCache::Destroy();
@@ -5418,17 +5415,6 @@ 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.
+16 -4
View File
@@ -170,12 +170,24 @@ void FullscreenUI::ApplyLayoutSettings(const SettingsInterface* bsi)
return InputLayout::Playstation;
if (mode == "nintendo")
return InputLayout::Nintendo;
if (mode == "generic")
return InputLayout::Generic;
return InputLayout::Unknown;
};
InputManager::SetGamepadIconPreference(parse_glyph_layout(glyph_mode));
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;
}
const InputLayout layout = ImGuiFullscreen::GetGamepadLayout();
@@ -545,7 +557,6 @@ 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 = {};
@@ -2456,6 +2467,7 @@ 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,9 +369,6 @@ 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,14 +2296,12 @@ 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++)
+20 -9
View File
@@ -971,10 +971,22 @@ InputLayout ImGuiFullscreen::GetGamepadLayout()
static InputLayout GetEffectiveGlyphLayout()
{
const InputLayout preferred_layout = InputManager::GetGamepadIconPreference();
if (preferred_layout != InputLayout::Unknown)
if (preferred_layout == InputLayout::Xbox || preferred_layout == InputLayout::Playstation || preferred_layout == InputLayout::Nintendo)
return preferred_layout;
return ImGuiFullscreen::GetGamepadLayout();
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;
}
}
ImGuiFullscreen::GamepadGlyphs ImGuiFullscreen::GetGamepadGlyphs()
@@ -982,17 +994,16 @@ 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 {
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)),
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),
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 || unknown) ? ICON_PF_SHARE_CAPTURE : ICON_PF_SELECT_SHARE),
nintendo ? ICON_PF_PLUS : ((xbox || unknown) ? ICON_PF_BURGER_MENU : ICON_PF_START),
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),
};
}
+35 -51
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, SettingsInterface* nav_si);
static void AddPadBindings(SettingsInterface& si, u32 pad, bool is_profile);
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, SettingsInterface* nav_si)
void InputManager::AddPadBindings(SettingsInterface& si, u32 pad_index, bool is_profile)
{
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);
}
// 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))
// Build reverse maps for controller navigation; user bindings take priority over static defaults.
if (bi.generic_mapping != GenericInputBinding::Unknown)
{
InputBindingKey bkey;
InputSource* bsrc;
if (!ParseBindingAndGetSource(binding_str, &bkey, &bsrc))
continue;
for (const std::string& binding_str : bindings)
{
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,42 +1312,27 @@ bool InputManager::PreprocessEvent(InputBindingKey key, float value, GenericInpu
}
else if (key.source_subtype == InputSubclass::ControllerButton)
{
// 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;
}
// 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;
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>(key.source_type)]->GetControllerLayout(key.source_index);
const InputLayout layout = s_input_sources[static_cast<u32>(InputSourceType::SDL)]->GetControllerLayout(key.source_index);
if (ImGuiManager::ProcessGenericInputEvent(resolved, layout, value, controller_id) && value != 0.0f)
return true;
}
}
else if (key.source_subtype == InputSubclass::ControllerAxis)
{
// 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];
}
}
// 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;
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>(key.source_type)]->GetControllerLayout(key.source_index);
const InputLayout layout = s_input_sources[static_cast<u32>(InputSourceType::SDL)]->GetControllerLayout(key.source_index);
ImGuiManager::ProcessGenericAxisEvent(neg, pos, layout, value, controller_id);
}
}
@@ -1634,11 +1619,10 @@ 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);
// 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);
// If there's an input profile, we load pad bindings from it alone, rather than
// falling back to the base configuration.
for (u32 pad = 0; pad < Pad::NUM_CONTROLLER_PORTS; pad++)
AddPadBindings(binding_si, pad, is_binding_profile, base_si);
AddPadBindings(binding_si, pad, is_binding_profile);
constexpr float ui_ctrl_range = 100.0f;
constexpr float pointer_sensitivity = 0.05f;
+1 -2
View File
@@ -52,8 +52,7 @@ enum class InputLayout : u8
Unknown,
Xbox,
Playstation,
Nintendo,
Generic
Nintendo
};
enum class InputModifier : u32
+18 -105
View File
@@ -225,38 +225,6 @@ 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
@@ -301,39 +269,26 @@ 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_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_names, // SDL_GAMEPAD_TYPE_STANDARD
s_sdl_button_names, // SDL_GAMEPAD_TYPE_XBOX360
s_sdl_button_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
s_sdl_button_nintendo_names, // SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_PRO
// Switch
};
static constexpr size_t s_sdl_button_namesize_list[] = {
std::size(s_sdl_button_names), // SDL_GAMEPAD_TYPE_UNKNOWN
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_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_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
std::size(s_sdl_button_nintendo_names), // SDL_GAMEPAD_TYPE_NINTENDO_SWITCH_PRO
// Switch
};
static constexpr const char* s_sdl_face_button_icons[] = {
@@ -353,52 +308,12 @@ 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_HOME_MENU, // SDL_GAMEPAD_BUTTON_GUIDE
ICON_PF_XBOX, // 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
@@ -487,9 +402,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_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_icons, // SDL_GAMEPAD_TYPE_STANDARD
s_sdl_button_icons, // SDL_GAMEPAD_TYPE_XBOX360
s_sdl_button_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
@@ -497,9 +412,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_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_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_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
@@ -1119,7 +1034,7 @@ TinyString SDLInputSource::ConvertKeyToString(InputBindingKey key, bool display,
if (it != m_controllers.end())
type = SDL_GetRealGamepadType(it->gamepad);
if (type > SDL_GAMEPAD_TYPE_UNKNOWN && type < std::size(s_sdl_button_names_list) &&
if (type > SDL_GAMEPAD_TYPE_STANDARD && 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]);
@@ -1196,8 +1111,6 @@ 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)
{
@@ -1228,7 +1141,7 @@ TinyString SDLInputSource::ConvertKeyToIcon(InputBindingKey key)
}
else if (key.source_subtype == InputSubclass::ControllerButton)
{
if (type > SDL_GAMEPAD_TYPE_UNKNOWN && type < std::size(s_sdl_button_icons_list) &&
if (type > SDL_GAMEPAD_TYPE_STANDARD && 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]);
@@ -1236,7 +1149,7 @@ TinyString SDLInputSource::ConvertKeyToIcon(InputBindingKey key)
else if (key.data < 4)
{
SDL_GamepadButtonLabel label = SDL_GAMEPAD_BUTTON_LABEL_UNKNOWN;
if (glyph_preference != InputLayout::Generic && it != m_controllers.end() && it->gamepad)
if (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
"Xbox", // XINPUT_GAMEPAD_GUIDE
"Guide", // 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::XInput)
if (key.source_type == InputSourceType::SDL)
{
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 = 109; // Last changed in PR 14795
static constexpr u32 SHADER_CACHE_VERSION = 108; // Last changed in PR 14688
+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 T2 [4] = __four(0xbeaaa61c);
u32 T3 [4] = __four(0x3e4c40a6);
u32 T4 [4] = __four(0xbe0e6c63);
u32 T5 [4] = __four(0x3dc577df);
u32 T5 [4] = __four(0xbeaaa61c);
u32 T2 [4] = __four(0x3e4c40a6);
u32 T3 [4] = __four(0xbe0e6c63);
u32 T4 [4] = __four(0x3dc577df);
u32 T6 [4] = __four(0xbd6501c4);
u32 T7 [4] = __four(0x3cb31652);
u32 T8 [4] = __four(0xbb84d7e7);