From 492fa7c6320bff355a9e8b82e5578d94d4506a3a Mon Sep 17 00:00:00 2001 From: oltolm Date: Fri, 21 Nov 2025 00:00:03 +0100 Subject: [PATCH 1/4] use concepts instead of SFINAE --- src/xenia/base/chrono.h | 23 ++++++++++------------- src/xenia/kernel/util/shim_utils.h | 15 ++++++++------- src/xenia/kernel/xobject.h | 8 ++++---- 3 files changed, 22 insertions(+), 24 deletions(-) diff --git a/src/xenia/base/chrono.h b/src/xenia/base/chrono.h index 1e9e0ea05..9812d1253 100644 --- a/src/xenia/base/chrono.h +++ b/src/xenia/base/chrono.h @@ -75,11 +75,10 @@ struct NtSystemClock { } // To convert XSystemClock to sys, do clock_cast(tp) first - // SFINAE hack https://stackoverflow.com/a/58813009 - template - static constexpr std::enable_if_t - to_sys(const time_point& tp) { + static constexpr std::chrono::system_clock::time_point to_sys( + const time_point& tp) + requires(domain_ == Domain::Host) + { using sys_duration = std::chrono::system_clock::duration; using sys_time = std::chrono::system_clock::time_point; @@ -91,17 +90,15 @@ struct NtSystemClock { // TODO(Gliniak): Disable until WINE will implement tzdb. /* - template - static constexpr std::enable_if_t< - domain_fresh_ == Domain::Host, - std::chrono::local_time> - to_local(const time_point& tp) { + static constexpr std::chrono::local_time + to_local(const time_point& tp) requires (domain_ == Domain::Host) { return std::chrono::current_zone()->to_local(to_sys(tp)); }*/ - template - static constexpr std::enable_if_t - from_sys(const std::chrono::system_clock::time_point& tp) { + static constexpr time_point from_sys( + const std::chrono::system_clock::time_point& tp) + requires(domain_ == Domain::Host) + { auto ctp = std::chrono::time_point_cast(tp); auto dp = time_point{ctp.time_since_epoch()}; dp -= unix_epoch_delta(); diff --git a/src/xenia/kernel/util/shim_utils.h b/src/xenia/kernel/util/shim_utils.h index 31aa85ec5..4af7166d4 100644 --- a/src/xenia/kernel/util/shim_utils.h +++ b/src/xenia/kernel/util/shim_utils.h @@ -500,15 +500,16 @@ enum class KernelModuleId { }; template -typename std::enable_if::type AppendKernelCallParams( - StringBuffer& string_buffer, xe::cpu::Export* export_entry, - const std::tuple&) {} + requires(I == sizeof...(Ps)) +void AppendKernelCallParams(StringBuffer& string_buffer, + xe::cpu::Export* export_entry, + const std::tuple&) {} template - typename std::enable_if < - I::type AppendKernelCallParams( - StringBuffer& string_buffer, xe::cpu::Export* export_entry, - const std::tuple& params) { + requires(I < sizeof...(Ps)) +void AppendKernelCallParams(StringBuffer& string_buffer, + xe::cpu::Export* export_entry, + const std::tuple& params) { if (I) { string_buffer.Append(", "); } diff --git a/src/xenia/kernel/xobject.h b/src/xenia/kernel/xobject.h index e3413622c..be6fe036d 100644 --- a/src/xenia/kernel/xobject.h +++ b/src/xenia/kernel/xobject.h @@ -286,8 +286,8 @@ class object_ref { reset(right.get()); if (value_) value_->Retain(); } - template ::value, void>::type> + template + requires std::is_convertible_v object_ref(const object_ref& right) noexcept { reset(right.get()); if (value_) value_->Retain(); @@ -379,8 +379,8 @@ bool operator!=(std::nullptr_t _Left, const object_ref<_Ty>& _Right) noexcept { } template -std::enable_if_t::value, object_ref> make_object( - Args&&... args) { + requires(!std::is_array_v) +object_ref make_object(Args&&... args) { return object_ref(new T(std::forward(args)...)); } From 169fea978a73fcb4537c2a6e2150a925a484361c Mon Sep 17 00:00:00 2001 From: The-Little-Wolf <116989599+The-Little-Wolf@users.noreply.github.com> Date: Wed, 17 Dec 2025 16:53:45 -0800 Subject: [PATCH 2/4] [XAM/XLIVE] - Set proper returns when offline - Have XLive functions return their offline values. - Have XGIUserReadStats return X_ONLINE_E_LOGON_NOT_LOGGED_ON --- src/xenia/kernel/xam/apps/xgi_app.cc | 4 +--- src/xenia/kernel/xam/apps/xlivebase_app.cc | 26 ++++++++++++++-------- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/src/xenia/kernel/xam/apps/xgi_app.cc b/src/xenia/kernel/xam/apps/xgi_app.cc index 3a642e535..dec4e4354 100644 --- a/src/xenia/kernel/xam/apps/xgi_app.cc +++ b/src/xenia/kernel/xam/apps/xgi_app.cc @@ -242,9 +242,7 @@ X_HRESULT XgiApp::DispatchMessageSync(uint32_t message, uint32_t buffer_ptr, xe::be results_guest_address; }* data = reinterpret_cast(buffer); - if (!data->results_guest_address) { - return 1; - } + return 0x80151802; // X_ONLINE_E_LOGON_NOT_LOGGED_ON } case 0x000B0036: { // Called after opening xbox live arcade and clicking on xbox live v5759 diff --git a/src/xenia/kernel/xam/apps/xlivebase_app.cc b/src/xenia/kernel/xam/apps/xlivebase_app.cc index a65a8d129..a457266c5 100644 --- a/src/xenia/kernel/xam/apps/xlivebase_app.cc +++ b/src/xenia/kernel/xam/apps/xlivebase_app.cc @@ -38,30 +38,38 @@ X_HRESULT XLiveBaseApp::DispatchMessageSync(uint32_t message, return X_E_FAIL; } case 0x00058003: { - // Called on startup of dashboard (netplay build) - XELOGD("XLiveBaseLogonGetHR, unimplemented"); - return X_E_SUCCESS; + /* Notes: + - Called on startup of dashboard (netplay build) + - used by other internet funtions to check if online (e.g. + XamGetLiveHiveValueA) + - Return is Saved elsewhere and used here + */ + XELOGD("XLiveBaseLogonGetHR, implemented in netplay"); + return 0x001510F1; // X_ONLINE_S_LOGON_DISCONNECTED } case 0x00058004: { - // Called on startup, seems to just return a bool in the buffer. + /* Notes: + - Called on startup, seems to just return a bool in the buffer. + - It is Saved elsewhere and used here + */ assert_true(!buffer_length || buffer_length == 4); XELOGD("XLiveBaseGetLogonId({:08X})", buffer_ptr); - xe::store_and_swap(buffer + 0, 1); // ? + xe::store_and_swap(buffer, 1); // ? return X_E_SUCCESS; } case 0x00058006: { + // Buffer only set when online assert_true(!buffer_length || buffer_length == 4); XELOGD("XLiveBaseGetNatType({:08X})", buffer_ptr); - xe::store_and_swap(buffer + 0, 1); // XONLINE_NAT_OPEN - return X_E_SUCCESS; + return 0x80151802; // X_ONLINE_E_LOGON_NOT_LOGGED_ON } case 0x00058007: { // Occurs if title calls XOnlineGetServiceInfo, expects dwServiceId // and pServiceInfo. pServiceInfo should contain pointer to // XONLINE_SERVICE_INFO structure. - XELOGD("CXLiveLogon::GetServiceInfo({:08X}, {:08X})", buffer_ptr, + XELOGD("XLiveBaseOnlineGetServiceInfo({:08X}, {:08X})", buffer_ptr, buffer_length); - return 0x80151802; // ERROR_CONNECTION_INVALID + return 0x80151802; // X_ONLINE_E_LOGON_NOT_LOGGED_ON } case 0x00058020: { // 0x00058004 is called right before this. From e786d5c8c363043e1e51c5d51183937e07677eb5 Mon Sep 17 00:00:00 2001 From: Gliniak Date: Mon, 22 Dec 2025 18:47:34 +0100 Subject: [PATCH 3/4] [XAM] Fixed potantial crash while upserting setting related to missing SPA - Fixed OOR asssertion caused by invalid amount of characters read by from_string --- src/xenia/kernel/xam/user_settings.h | 9 ++++++--- src/xenia/kernel/xam/user_tracker.cc | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/xenia/kernel/xam/user_settings.h b/src/xenia/kernel/xam/user_settings.h index bdc797b7a..6ac2bd0c7 100644 --- a/src/xenia/kernel/xam/user_settings.h +++ b/src/xenia/kernel/xam/user_settings.h @@ -451,15 +451,18 @@ struct GamerPictureKey { char small_tile_id[8]; uint32_t GetTitleId() const { - return string_util::from_string(title_id, true); + return string_util::from_string( + std::string(title_id, std::size(title_id)), true); } uint32_t GetBigTileId() const { - return string_util::from_string(big_tile_id, true); + return string_util::from_string( + std::string(big_tile_id, std::size(big_tile_id)), true); } uint32_t GetSmallTileId() const { - return string_util::from_string(small_tile_id, true); + return string_util::from_string( + std::string(small_tile_id, std::size(small_tile_id)), true); } }; static_assert_size(GamerPictureKey, 0x18); diff --git a/src/xenia/kernel/xam/user_tracker.cc b/src/xenia/kernel/xam/user_tracker.cc index 70cf6d1fa..d851b7f59 100644 --- a/src/xenia/kernel/xam/user_tracker.cc +++ b/src/xenia/kernel/xam/user_tracker.cc @@ -734,7 +734,7 @@ void UserTracker::UpsertSetting(uint64_t xuid, uint32_t title_id, // Sometimes games like to ignore providing expicitly title_id, so we need to // check it. if (!title_id) { - title_id = spa_data_->title_id(); + title_id = spa_data_ ? spa_data_->title_id() : kernel_state()->title_id(); } GpdInfo* info = user->GetGpd(title_id); From ac66db337b63298ab1b3513d2cdfcd743a3cb212 Mon Sep 17 00:00:00 2001 From: Adrian <78108584+AdrianCassar@users.noreply.github.com> Date: Wed, 17 Dec 2025 19:52:49 +0000 Subject: [PATCH 4/4] [XAM] Fixed size used in read_u16string_and_swap --- src/xenia/base/string_util.h | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/xenia/base/string_util.h b/src/xenia/base/string_util.h index 3d7d0e9ce..5a4cc1152 100644 --- a/src/xenia/base/string_util.h +++ b/src/xenia/base/string_util.h @@ -429,16 +429,6 @@ inline vec128_t from_string(const std::string_view value, return v; } -inline std::u16string read_u16string_and_swap(const char16_t* string_ptr) { - std::u16string input_str = std::u16string(string_ptr); - - std::u16string output_str = {}; - output_str.resize(input_str.size() + 1); - copy_and_swap_truncating(output_str.data(), input_str, input_str.size() + 1); - output_str.pop_back(); // Remove nullptr added by copy_and_swap. - return output_str; -} - inline size_t size_in_bytes(std::variant string, bool include_terminator = true) { if (std::holds_alternative(string)) { @@ -452,6 +442,17 @@ inline size_t size_in_bytes(std::variant string, return 0; } +inline std::u16string read_u16string_and_swap(const char16_t* string_ptr) { + std::u16string input_str = std::u16string(string_ptr); + + std::u16string output_str = {}; + output_str.resize(input_str.size() + 1); + copy_and_swap_truncating(output_str.data(), input_str, + size_in_bytes(input_str, false)); + output_str.pop_back(); // Remove nullptr added by copy_and_swap. + return output_str; +} + } // namespace string_util } // namespace xe