From 547198af6fddf804e9d012ce3d56070d6fb765b9 Mon Sep 17 00:00:00 2001 From: Stephen Miller <56742918+StevenMiller123@users.noreply.github.com> Date: Mon, 16 Feb 2026 00:31:35 -0600 Subject: [PATCH 1/2] Lib.VideoOut: Fix pending flips limit (#4039) * Hardcoded limit to pending flips Real hardware has a fixed-size queue, and doesn't depend on the number of registered buffers. While the kernel supposedly uses an array of 18 elements, my tests suggest the cap is 16 pending flips. * Assert on trying to flip unregistered buffer I haven't seen anything do this intentionally yet, but I do have cases where games do this unintentionally (do to unimplemented functions). --- src/core/libraries/videoout/driver.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/core/libraries/videoout/driver.cpp b/src/core/libraries/videoout/driver.cpp index 4951c4f1a..21163119d 100644 --- a/src/core/libraries/videoout/driver.cpp +++ b/src/core/libraries/videoout/driver.cpp @@ -224,7 +224,7 @@ bool VideoOutDriver::SubmitFlip(VideoOutPort* port, s32 index, s64 flip_arg, bool is_eop /*= false*/) { { std::unique_lock lock{port->port_mutex}; - if (index != -1 && port->flip_status.flip_pending_num >= port->NumRegisteredBuffers()) { + if (index != -1 && port->flip_status.flip_pending_num > 16) { LOG_ERROR(Lib_VideoOut, "Flip queue is full"); return false; } @@ -252,6 +252,7 @@ void VideoOutDriver::SubmitFlipInternal(VideoOutPort* port, s32 index, s64 flip_ frame = presenter->PrepareBlankFrame(false); } else { const auto& buffer = port->buffer_slots[index]; + ASSERT_MSG(buffer.group_index >= 0, "Trying to flip an unregistered buffer!"); const auto& group = port->groups[buffer.group_index]; frame = presenter->PrepareFrame(group, buffer.address_left); } From 3a99051df910ead12048e43c685388613fcc928e Mon Sep 17 00:00:00 2001 From: kalaposfos13 <153381648+kalaposfos13@users.noreply.github.com> Date: Mon, 16 Feb 2026 21:56:35 +0100 Subject: [PATCH 2/2] filesystem: fix crashes caused by returning a pointer from an std::vector (#4043) Co-authored-by: Stephen Miller <56742918+StevenMiller123@users.noreply.github.com> --- src/core/file_sys/fs.cpp | 2 +- src/core/file_sys/fs.h | 8 ++++++-- src/core/libraries/save_data/save_instance.cpp | 2 +- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/core/file_sys/fs.cpp b/src/core/file_sys/fs.cpp index cba95fe37..96a04ee5e 100644 --- a/src/core/file_sys/fs.cpp +++ b/src/core/file_sys/fs.cpp @@ -55,7 +55,7 @@ std::filesystem::path MntPoints::GetHostPath(std::string_view path, bool* is_rea if (path.length() > 255) return ""; - const MntPair* mount = GetMount(corrected_path); + const std::optional mount = GetMount(corrected_path); if (!mount) { return ""; } diff --git a/src/core/file_sys/fs.h b/src/core/file_sys/fs.h index 599d9e823..6fc6c570f 100644 --- a/src/core/file_sys/fs.h +++ b/src/core/file_sys/fs.h @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -58,14 +59,17 @@ public: return it == m_mnt_pairs.end() ? nullptr : &*it; } - const MntPair* GetMount(const std::string& guest_path) { + const std::optional GetMount(const std::string& guest_path) { std::scoped_lock lock{m_mutex}; const auto it = std::ranges::find_if(m_mnt_pairs, [&](const auto& mount) { // When doing starts-with check, add a trailing slash to make sure we don't match // against only part of the mount path. return guest_path == mount.mount || guest_path.starts_with(mount.mount + "/"); }); - return it == m_mnt_pairs.end() ? nullptr : &*it; + if (it == m_mnt_pairs.end()) { + return std::nullopt; + } + return *it; } private: diff --git a/src/core/libraries/save_data/save_instance.cpp b/src/core/libraries/save_data/save_instance.cpp index bc6bbfd72..baeec5d2c 100644 --- a/src/core/libraries/save_data/save_instance.cpp +++ b/src/core/libraries/save_data/save_instance.cpp @@ -105,7 +105,7 @@ SaveInstance::SaveInstance(int slot_num, Libraries::UserService::OrbisUserServic mount_point = "/savedata" + std::to_string(slot_num); this->exists = fs::exists(param_sfo_path); - this->mounted = g_mnt->GetMount(mount_point) != nullptr; + this->mounted = g_mnt->GetMount(mount_point) != std::nullopt; } SaveInstance::~SaveInstance() {