mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2026-10-31 11:40:52 +00:00
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d896310692 | |||
| d16735f5b6 | |||
| d3550c4571 | |||
| 963119e7cc | |||
| 2a7e9b53b1 | |||
| 8e2d26c272 |
@@ -1,34 +0,0 @@
|
|||||||
diff --git a/libavutil/hwcontext_vulkan.c b/libavutil/hwcontext_vulkan.c
|
|
||||||
index 2859ee1..766961f 100644
|
|
||||||
--- a/libavutil/hwcontext_vulkan.c
|
|
||||||
+++ b/libavutil/hwcontext_vulkan.c
|
|
||||||
@@ -1688,10 +1688,12 @@ static int setup_queue_families(AVHWDeviceContext *ctx, VkDeviceCreateInfo *cd)
|
|
||||||
|
|
||||||
hwctx->nb_qf = 0;
|
|
||||||
hwctx->queue_flags = 0;
|
|
||||||
+/* SD gamemode vkroots crash
|
|
||||||
#ifdef VK_KHR_internally_synchronized_queues
|
|
||||||
if (p->vkctx.extensions & FF_VK_EXT_INTERNAL_QUEUE_SYNC)
|
|
||||||
hwctx->queue_flags |= VK_DEVICE_QUEUE_CREATE_INTERNALLY_SYNCHRONIZED_BIT_KHR;
|
|
||||||
#endif
|
|
||||||
+*/
|
|
||||||
|
|
||||||
/* Pick each queue family to use. */
|
|
||||||
#define PICK_QF(type, vid_op) \
|
|
||||||
diff --git a/libavutil/vulkan.c b/libavutil/vulkan.c
|
|
||||||
index b2e575c..5b3c9cf 100644
|
|
||||||
--- a/libavutil/vulkan.c
|
|
||||||
+++ b/libavutil/vulkan.c
|
|
||||||
@@ -574,10 +574,12 @@ int ff_vk_exec_pool_init(FFVulkanContext *s, AVVulkanDeviceQueueFamily *qf,
|
|
||||||
e->qf = qf->idx;
|
|
||||||
VkDeviceQueueInfo2 qinfo = {
|
|
||||||
.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2,
|
|
||||||
+/* SD gamemode vkroots crash
|
|
||||||
#ifdef VK_KHR_internally_synchronized_queues
|
|
||||||
.flags = internal_queue_sync ?
|
|
||||||
VK_DEVICE_QUEUE_CREATE_INTERNALLY_SYNCHRONIZED_BIT_KHR : 0,
|
|
||||||
#endif
|
|
||||||
+*/
|
|
||||||
.queueFamilyIndex = qf->idx,
|
|
||||||
.queueIndex = e->qi,
|
|
||||||
};
|
|
||||||
+3
-3
@@ -70,16 +70,16 @@
|
|||||||
"version": "v1.3.18"
|
"version": "v1.3.18"
|
||||||
},
|
},
|
||||||
"ffmpeg": {
|
"ffmpeg": {
|
||||||
"hash": "68f46abf0d5dc47ab95083d59e273131a8df7948b82e62db00f00fa416e1d0bd24b799671b5a60752209bb2ac0f75295055ed0085c89a98113323cde23b69710",
|
"hash": "ed177621176b3961bdcaa339187d3a7688c1c8b060b79c4bb0257cbc67ad7021ae5d5adca5303b45625abbbe3d9aafdd87ce777b8690ac295290d744c875489a",
|
||||||
"repo": "FFmpeg/FFmpeg",
|
"repo": "FFmpeg/FFmpeg",
|
||||||
"version": "6efe500d2e"
|
"version": "c7b5f1537d"
|
||||||
},
|
},
|
||||||
"ffmpeg-ci": {
|
"ffmpeg-ci": {
|
||||||
"ci": true,
|
"ci": true,
|
||||||
"name": "ffmpeg",
|
"name": "ffmpeg",
|
||||||
"package": "FFmpeg",
|
"package": "FFmpeg",
|
||||||
"repo": "crueter-ci/FFmpeg",
|
"repo": "crueter-ci/FFmpeg",
|
||||||
"version": "9.0.1-1788120736-bf1b838f2a"
|
"version": "9.0.2-1790726865-946fcce07b"
|
||||||
},
|
},
|
||||||
"fmt": {
|
"fmt": {
|
||||||
"hash": "f0da82c545b01692e9fd30fdfb613dbb8dd9716983dcd0ff19ac2a8d36f74beb5540ef38072fdecc1e34191b3682a8542ecbf3a61ef287dbba0a2679d4e023f2",
|
"hash": "f0da82c545b01692e9fd30fdfb613dbb8dd9716983dcd0ff19ac2a8d36f74beb5540ef38072fdecc1e34191b3682a8542ecbf3a61ef287dbba0a2679d4e023f2",
|
||||||
|
|||||||
+2
@@ -16,6 +16,8 @@ enum class BooleanSetting(override val key: String) : AbstractBooleanSetting {
|
|||||||
RENDERER_USE_SPEED_LIMIT("use_speed_limit"),
|
RENDERER_USE_SPEED_LIMIT("use_speed_limit"),
|
||||||
USE_CUSTOM_CPU_TICKS("use_custom_cpu_ticks"),
|
USE_CUSTOM_CPU_TICKS("use_custom_cpu_ticks"),
|
||||||
SKIP_CPU_INNER_INVALIDATION("skip_cpu_inner_invalidation"),
|
SKIP_CPU_INNER_INVALIDATION("skip_cpu_inner_invalidation"),
|
||||||
|
NCE_INVALIDATION_GPU_READBACK("nce_invalidation_gpu_readback"),
|
||||||
|
NCE_RUNTIME_NRO_PATCH("nce_runtime_nro_patch"),
|
||||||
FIX_BLOOM_EFFECTS("fix_bloom_effects"),
|
FIX_BLOOM_EFFECTS("fix_bloom_effects"),
|
||||||
EMULATE_BGR565("emulate_bgr565"),
|
EMULATE_BGR565("emulate_bgr565"),
|
||||||
RESCALE_HACK("rescale_hack"),
|
RESCALE_HACK("rescale_hack"),
|
||||||
|
|||||||
+14
@@ -866,6 +866,20 @@ abstract class SettingsItem(
|
|||||||
descriptionId = R.string.skip_cpu_inner_invalidation_description
|
descriptionId = R.string.skip_cpu_inner_invalidation_description
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
put(
|
||||||
|
SwitchSetting(
|
||||||
|
BooleanSetting.NCE_INVALIDATION_GPU_READBACK,
|
||||||
|
titleId = R.string.nce_invalidation_gpu_readback,
|
||||||
|
descriptionId = R.string.nce_invalidation_gpu_readback_description
|
||||||
|
)
|
||||||
|
)
|
||||||
|
put(
|
||||||
|
SwitchSetting(
|
||||||
|
BooleanSetting.NCE_RUNTIME_NRO_PATCH,
|
||||||
|
titleId = R.string.nce_runtime_nro_patch,
|
||||||
|
descriptionId = R.string.nce_runtime_nro_patch_description
|
||||||
|
)
|
||||||
|
)
|
||||||
put(
|
put(
|
||||||
SwitchSetting(
|
SwitchSetting(
|
||||||
BooleanSetting.FIX_BLOOM_EFFECTS,
|
BooleanSetting.FIX_BLOOM_EFFECTS,
|
||||||
|
|||||||
+2
@@ -554,6 +554,8 @@ class SettingsFragmentPresenter(
|
|||||||
add(HeaderSetting(R.string.hacks))
|
add(HeaderSetting(R.string.hacks))
|
||||||
|
|
||||||
add(BooleanSetting.SKIP_CPU_INNER_INVALIDATION.key)
|
add(BooleanSetting.SKIP_CPU_INNER_INVALIDATION.key)
|
||||||
|
add(BooleanSetting.NCE_INVALIDATION_GPU_READBACK.key)
|
||||||
|
add(BooleanSetting.NCE_RUNTIME_NRO_PATCH.key)
|
||||||
add(BooleanSetting.FIX_BLOOM_EFFECTS.key)
|
add(BooleanSetting.FIX_BLOOM_EFFECTS.key)
|
||||||
add(BooleanSetting.EMULATE_BGR565.key)
|
add(BooleanSetting.EMULATE_BGR565.key)
|
||||||
add(BooleanSetting.RENDERER_ASYNCHRONOUS_SHADERS.key)
|
add(BooleanSetting.RENDERER_ASYNCHRONOUS_SHADERS.key)
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import org.yuzu.yuzu_emu.model.Driver.Companion.toDriver
|
|||||||
import org.yuzu.yuzu_emu.utils.GpuDriverHelper
|
import org.yuzu.yuzu_emu.utils.GpuDriverHelper
|
||||||
import org.yuzu.yuzu_emu.NativeLibrary
|
import org.yuzu.yuzu_emu.NativeLibrary
|
||||||
import org.yuzu.yuzu_emu.utils.GpuDriverMetadata
|
import org.yuzu.yuzu_emu.utils.GpuDriverMetadata
|
||||||
|
import org.yuzu.yuzu_emu.utils.DirectoryInitialization
|
||||||
import org.yuzu.yuzu_emu.utils.NativeConfig
|
import org.yuzu.yuzu_emu.utils.NativeConfig
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
@@ -146,11 +147,11 @@ class DriverViewModel : ViewModel() {
|
|||||||
private fun wipeGameShaders(game: Game) {
|
private fun wipeGameShaders(game: Game) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
withContext(Dispatchers.IO) {
|
withContext(Dispatchers.IO) {
|
||||||
val externalFilesDir = YuzuApplication.appContext.getExternalFilesDir(null)
|
val userDirectory = DirectoryInitialization.userDirectory
|
||||||
?: return@withContext
|
?: return@withContext
|
||||||
val shaderDir = File(
|
val shaderDir = File(
|
||||||
externalFilesDir.absolutePath +
|
userDirectory +
|
||||||
"/shader/" + game.settingsName.lowercase()
|
"/cache/shader/" + game.settingsName.lowercase()
|
||||||
)
|
)
|
||||||
if (shaderDir.exists()) {
|
if (shaderDir.exists()) {
|
||||||
shaderDir.deleteRecursively()
|
shaderDir.deleteRecursively()
|
||||||
|
|||||||
@@ -595,6 +595,10 @@
|
|||||||
<string name="fast_gpu_time_description">Makes the game believe GPU work finishes faster than it does, so it stops lowering resolution and render distance to fit the Switch\'s clocks.</string>
|
<string name="fast_gpu_time_description">Makes the game believe GPU work finishes faster than it does, so it stops lowering resolution and render distance to fit the Switch\'s clocks.</string>
|
||||||
<string name="skip_cpu_inner_invalidation">Skip CPU Inner Invalidation</string>
|
<string name="skip_cpu_inner_invalidation">Skip CPU Inner Invalidation</string>
|
||||||
<string name="skip_cpu_inner_invalidation_description">Skips certain CPU-side cache invalidations during memory updates, reducing CPU usage and improving it\'s performance. This may cause glitches or crashes on some games.</string>
|
<string name="skip_cpu_inner_invalidation_description">Skips certain CPU-side cache invalidations during memory updates, reducing CPU usage and improving it\'s performance. This may cause glitches or crashes on some games.</string>
|
||||||
|
<string name="nce_invalidation_gpu_readback">GPU Readback Before NCE Invalidation</string>
|
||||||
|
<string name="nce_invalidation_gpu_readback_description">Temporary. Fix Ender Magnolia (and other UE titles) crashes. May reduce performance. Improvement in progress.</string>
|
||||||
|
<string name="nce_runtime_nro_patch">Patch Runtime NROs for NCE</string>
|
||||||
|
<string name="nce_runtime_nro_patch_description">Temporary. Fix Biomutant boot. May impact performance. Improvement in progress.</string>
|
||||||
<string name="fix_bloom_effects">Fix Bloom Effects</string>
|
<string name="fix_bloom_effects">Fix Bloom Effects</string>
|
||||||
<string name="fix_bloom_effects_description">Reduces bloom blur in LA/EOW (Adreno A6XX - A7XX/ Turnip), removes bloom in Burnout. Warning: may cause graphical artifacts in other games.</string>
|
<string name="fix_bloom_effects_description">Reduces bloom blur in LA/EOW (Adreno A6XX - A7XX/ Turnip), removes bloom in Burnout. Warning: may cause graphical artifacts in other games.</string>
|
||||||
<string name="emulate_bgr565">Emulate BGR565</string>
|
<string name="emulate_bgr565">Emulate BGR565</string>
|
||||||
|
|||||||
@@ -639,6 +639,10 @@ struct Values {
|
|||||||
Specialization::Default,
|
Specialization::Default,
|
||||||
true,
|
true,
|
||||||
true};
|
true};
|
||||||
|
SwitchableSetting<bool> nce_invalidation_gpu_readback{
|
||||||
|
linkage, false, "nce_invalidation_gpu_readback", Category::RendererHacks};
|
||||||
|
SwitchableSetting<bool> nce_runtime_nro_patch{
|
||||||
|
linkage, false, "nce_runtime_nro_patch", Category::RendererHacks};
|
||||||
SwitchableSetting<bool> async_presentation{linkage,
|
SwitchableSetting<bool> async_presentation{linkage,
|
||||||
#ifdef __ANDROID__
|
#ifdef __ANDROID__
|
||||||
false,
|
false,
|
||||||
|
|||||||
@@ -250,9 +250,10 @@ std::shared_ptr<FrontendApplet> FrontendAppletHolder::GetApplet(std::shared_ptr<
|
|||||||
return std::make_shared<PhotoViewer>(system, applet, mode, *frontend.photo_viewer);
|
return std::make_shared<PhotoViewer>(system, applet, mode, *frontend.photo_viewer);
|
||||||
case AppletId::NetConnect:
|
case AppletId::NetConnect:
|
||||||
return std::make_shared<NetConnect>(system, applet, mode, *frontend.net_connect);
|
return std::make_shared<NetConnect>(system, applet, mode, *frontend.net_connect);
|
||||||
|
case AppletId::None:
|
||||||
|
return nullptr;
|
||||||
default:
|
default:
|
||||||
LOG_ERROR(Service_AM, "No backend implementation exists for applet_id={:02X} program_id={:016X}"
|
UNIMPLEMENTED_MSG("No frontend implementation exists for applet_id={:02X} program_id={:016X}! Using stub applet.", static_cast<u8>(id), applet->program_id);
|
||||||
"Falling back to stub applet", static_cast<u8>(id), applet->program_id);
|
|
||||||
return std::make_shared<StubApplet>(system, applet, id, mode);
|
return std::make_shared<StubApplet>(system, applet, id, mode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -426,28 +426,30 @@ public:
|
|||||||
std::addressof(ro_size), std::addressof(rw_size),
|
std::addressof(ro_size), std::addressof(rw_size),
|
||||||
nro_info->base_address, nro_size, bss_size));
|
nro_info->base_address, nro_size, bss_size));
|
||||||
#ifdef HAS_NCE
|
#ifdef HAS_NCE
|
||||||
if (Settings::IsNceEnabled()) {
|
if (Settings::values.nce_runtime_nro_patch.GetValue()) {
|
||||||
auto* process = context->GetProcess();
|
if (Settings::IsNceEnabled()) {
|
||||||
auto& memory = process->GetMemory();
|
auto* process = context->GetProcess();
|
||||||
|
auto& memory = process->GetMemory();
|
||||||
|
|
||||||
std::vector<u8> image(total_size);
|
std::vector<u8> image(total_size);
|
||||||
memory.ReadBlock(nro_info->base_address, image.data(), rx_size);
|
memory.ReadBlock(nro_info->base_address, image.data(), rx_size);
|
||||||
|
|
||||||
Kernel::CodeSet::Segment code{.size = static_cast<u32>(rx_size)};
|
Kernel::CodeSet::Segment code{.size = static_cast<u32>(rx_size)};
|
||||||
Core::NCE::Patcher patch;
|
Core::NCE::Patcher patch;
|
||||||
patch.PatchText(image, code);
|
patch.PatchText(image, code);
|
||||||
patch.RelocateAndCopy(nro_info->base_address, code, image, nullptr);
|
patch.RelocateAndCopy(nro_info->base_address, code, image, nullptr);
|
||||||
|
|
||||||
const u64 patch_address = nro_info->base_address + total_size;
|
const u64 patch_address = nro_info->base_address + total_size;
|
||||||
const size_t patch_size = patch.GetSectionSize();
|
const size_t patch_size = patch.GetSectionSize();
|
||||||
constexpr auto permission = Kernel::Svc::MemoryPermission::ReadExecute;
|
constexpr auto permission = Kernel::Svc::MemoryPermission::ReadExecute;
|
||||||
|
|
||||||
auto* patch_memory = Kernel::KSharedMemory::Create(kernel);
|
auto* patch_memory = Kernel::KSharedMemory::Create(kernel);
|
||||||
R_TRY(patch_memory->Initialize(kernel, kernel.System().DeviceMemory(), process, permission, permission, patch_size));
|
R_TRY(patch_memory->Initialize(kernel, kernel.System().DeviceMemory(), process, permission, permission, patch_size));
|
||||||
std::memcpy(patch_memory->GetPointer(), image.data() + total_size, patch_size);
|
std::memcpy(patch_memory->GetPointer(), image.data() + total_size, patch_size);
|
||||||
R_TRY(process->AddSharedMemory(kernel, patch_memory, patch_address, patch_size));
|
R_TRY(process->AddSharedMemory(kernel, patch_memory, patch_address, patch_size));
|
||||||
R_TRY(patch_memory->Map(*process, patch_address, patch_size, permission));
|
R_TRY(patch_memory->Map(*process, patch_address, patch_size, permission));
|
||||||
memory.WriteBlock(nro_info->base_address, image.data(), rx_size);
|
memory.WriteBlock(nro_info->base_address, image.data(), rx_size);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
// Set NRO perms.
|
// Set NRO perms.
|
||||||
|
|||||||
+1
-1
@@ -757,7 +757,7 @@ struct Memory::Impl {
|
|||||||
};
|
};
|
||||||
auto& gpu = system.GPU();
|
auto& gpu = system.GPU();
|
||||||
gpu_device_memory->ApplyOpOnPointer(
|
gpu_device_memory->ApplyOpOnPointer(
|
||||||
p, scratch_buffers[core], [&](DAddr address) { gpu.InvalidateRegion(address, size); });
|
p, scratch_buffers[core], [&](DAddr address) { gpu.InvalidateRegion(address, size, true); });
|
||||||
}
|
}
|
||||||
|
|
||||||
Core::System& system;
|
Core::System& system;
|
||||||
|
|||||||
@@ -194,6 +194,14 @@ std::unique_ptr<TranslationMap> InitializeTranslations(QObject* parent) {
|
|||||||
INSERT(Settings, skip_cpu_inner_invalidation, tr("Skip CPU Inner Invalidation"),
|
INSERT(Settings, skip_cpu_inner_invalidation, tr("Skip CPU Inner Invalidation"),
|
||||||
tr("Skips certain cache invalidations during memory updates, reducing CPU usage and "
|
tr("Skips certain cache invalidations during memory updates, reducing CPU usage and "
|
||||||
"improving latency. This may cause soft-crashes."));
|
"improving latency. This may cause soft-crashes."));
|
||||||
|
INSERT(Settings, nce_invalidation_gpu_readback,
|
||||||
|
tr("GPU Readback Before NCE Invalidation"),
|
||||||
|
tr("Flushes GPU buffer data back to guest memory before NCE invalidates the whole "
|
||||||
|
"guest page, preserving it while the CPU store proceeds."));
|
||||||
|
INSERT(Settings, nce_runtime_nro_patch,
|
||||||
|
tr("Patch Runtime NROs for NCE"),
|
||||||
|
tr("Applies NCE code patches to runtime-loaded NRO modules."
|
||||||
|
"This is required for some games to run correctly."));
|
||||||
INSERT(Settings, vsync_mode, tr("VSync Mode:"),
|
INSERT(Settings, vsync_mode, tr("VSync Mode:"),
|
||||||
tr("FIFO (VSync) does not drop frames or exhibit tearing but is limited by the screen "
|
tr("FIFO (VSync) does not drop frames or exhibit tearing but is limited by the screen "
|
||||||
"refresh rate.\nFIFO Relaxed allows tearing as it recovers from a slow down.\n"
|
"refresh rate.\nFIFO Relaxed allows tearing as it recovers from a slow down.\n"
|
||||||
|
|||||||
+15
-3
@@ -226,7 +226,19 @@ struct GPU::Impl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Notify rasterizer that any caches of the specified region should be invalidated
|
/// Notify rasterizer that any caches of the specified region should be invalidated
|
||||||
void InvalidateRegion(DAddr addr, u64 size) {
|
void InvalidateRegion(DAddr addr, u64 size, bool preserve_gpu_writes) {
|
||||||
|
if (Settings::values.nce_invalidation_gpu_readback.GetValue()) {
|
||||||
|
VideoCore::RasterizerInterface* rasterizer = renderer->ReadRasterizer();
|
||||||
|
if (preserve_gpu_writes && rasterizer->MustFlushRegion(addr, size, VideoCommon::CacheType::BufferCache)) {
|
||||||
|
const u64 fence = RequestSyncOperation([rasterizer, addr, size] {
|
||||||
|
rasterizer->FlushRegion(addr, size, VideoCommon::CacheType::BufferCache);
|
||||||
|
rasterizer->OnCacheInvalidation(addr, size);
|
||||||
|
});
|
||||||
|
gpu_thread.TickGPU(is_async);
|
||||||
|
WaitForSyncOperation(fence);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
gpu_thread.InvalidateRegion(addr, size);
|
gpu_thread.InvalidateRegion(addr, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -518,8 +530,8 @@ void GPU::FlushRegion(DAddr addr, u64 size) {
|
|||||||
impl->FlushRegion(addr, size);
|
impl->FlushRegion(addr, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPU::InvalidateRegion(DAddr addr, u64 size) {
|
void GPU::InvalidateRegion(DAddr addr, u64 size, bool preserve_gpu_writes) {
|
||||||
impl->InvalidateRegion(addr, size);
|
impl->InvalidateRegion(addr, size, preserve_gpu_writes);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GPU::OnCPUWrite(DAddr addr, u64 size) {
|
bool GPU::OnCPUWrite(DAddr addr, u64 size) {
|
||||||
|
|||||||
@@ -248,7 +248,7 @@ public:
|
|||||||
void FlushRegion(DAddr addr, u64 size);
|
void FlushRegion(DAddr addr, u64 size);
|
||||||
|
|
||||||
/// Notify rasterizer that any caches of the specified region should be invalidated
|
/// Notify rasterizer that any caches of the specified region should be invalidated
|
||||||
void InvalidateRegion(DAddr addr, u64 size);
|
void InvalidateRegion(DAddr addr, u64 size, bool preserve_gpu_writes = false);
|
||||||
|
|
||||||
/// Notify rasterizer that CPU is trying to write this area. It returns true if the area is
|
/// Notify rasterizer that CPU is trying to write this area. It returns true if the area is
|
||||||
/// sensible, false otherwise, addr and size must be a valid combination
|
/// sensible, false otherwise, addr and size must be a valid combination
|
||||||
|
|||||||
+15
-11
@@ -12,25 +12,29 @@ namespace Yuzu {
|
|||||||
|
|
||||||
inline bool ContainsAllWords(const QString& haystack, const QString& userinput) {
|
inline bool ContainsAllWords(const QString& haystack, const QString& userinput) {
|
||||||
const QStringList userinput_split = userinput.split(QLatin1Char{' '}, Qt::SkipEmptyParts);
|
const QStringList userinput_split = userinput.split(QLatin1Char{' '}, Qt::SkipEmptyParts);
|
||||||
return std::all_of(userinput_split.begin(), userinput_split.end(),
|
return std::all_of(userinput_split.begin(), userinput_split.end(), [&haystack](const QString& s) {
|
||||||
[&haystack](const QString& s) { return haystack.contains(s); });
|
return haystack.contains(s);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool FilterMatches(const QString& filter, const QStandardItem* item) {
|
inline bool FilterMatches(const QString& filter, const QStandardItem* item) {
|
||||||
if (filter.isEmpty())
|
if (filter.isEmpty())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
auto const sluggify = [](const QString& s) {
|
||||||
|
QString o(s.normalized(QString::NormalizationForm_D).toLower());
|
||||||
|
return o.replace(QRegularExpression(QStringLiteral("[^a-z\\s]")), QStringLiteral(""));
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto norm_filter = sluggify(filter);
|
||||||
const auto program_id = item->data(GameListItemPath::ProgramIdRole).toULongLong();
|
const auto program_id = item->data(GameListItemPath::ProgramIdRole).toULongLong();
|
||||||
|
const QString file_path = sluggify(item->data(GameListItemPath::FullPathRole).toString());
|
||||||
const QString file_path = item->data(GameListItemPath::FullPathRole).toString().toLower();
|
const QString file_title = sluggify(item->data(GameListItemPath::TitleRole).toString());
|
||||||
const QString file_title = item->data(GameListItemPath::TitleRole).toString().toLower();
|
|
||||||
const QString file_program_id = QStringLiteral("%1").arg(program_id, 16, 16, QLatin1Char{'0'});
|
const QString file_program_id = QStringLiteral("%1").arg(program_id, 16, 16, QLatin1Char{'0'});
|
||||||
|
const QString file_name = sluggify(file_path.mid(file_path.lastIndexOf(QLatin1Char{'/'}) + 1) + QLatin1Char{' '} + file_title);
|
||||||
const QString file_name =
|
return (ContainsAllWords(file_name, norm_filter)
|
||||||
file_path.mid(file_path.lastIndexOf(QLatin1Char{'/'}) + 1) + QLatin1Char{' '} + file_title;
|
|| ContainsAllWords(file_title, norm_filter))
|
||||||
|
|| (file_program_id.size() == 16 && file_program_id.contains(norm_filter));
|
||||||
return Yuzu::ContainsAllWords(file_name, filter) ||
|
|
||||||
(file_program_id.size() == 16 && file_program_id.contains(filter));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Yuzu
|
} // namespace Yuzu
|
||||||
|
|||||||
Reference in New Issue
Block a user